PageRenderTime 82ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/buildscripts/libdeps/graph_visualizer_web_stack/src/GraphPaths.js

https://github.com/mongodb/mongo
JavaScript | 294 lines | 275 code | 19 blank | 0 comment | 8 complexity | cd299b4f30249bc4e97b54f2cb784c4c MD5 | raw file
Possible License(s): BSD-2-Clause, 0BSD, MPL-2.0, WTFPL, BSD-3-Clause-No-Nuclear-License-2014, Apache-2.0, GPL-3.0, BSD-3-Clause, GPL-2.0
  1. import React from "react";
  2. import { connect } from "react-redux";
  3. import { FixedSizeList } from "react-window";
  4. import SplitPane from "react-split-pane";
  5. import { makeStyles, withStyles } from "@material-ui/core/styles";
  6. import ListItem from "@material-ui/core/ListItem";
  7. import ListItemText from "@material-ui/core/ListItemText";
  8. import Paper from "@material-ui/core/Paper";
  9. import Typography from "@material-ui/core/Typography";
  10. import Box from "@material-ui/core/Box";
  11. import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
  12. import MuiAccordion from "@material-ui/core/Accordion";
  13. import MuiAccordionSummary from "@material-ui/core/AccordionSummary";
  14. import MuiAccordionDetails from "@material-ui/core/AccordionDetails";
  15. import { socket } from "./connect";
  16. import useResizeAware from "react-resize-aware";
  17. import { getSelected } from "./redux/store";
  18. import { selectedGraphPaths, setSelectedPath } from "./redux/graphPaths";
  19. import OverflowTooltip from "./OverflowTooltip";
  20. const rowHeight = 25;
  21. const Accordion = withStyles({
  22. root: {
  23. border: "1px solid rgba(0, 0, 0, .125)",
  24. boxShadow: "none",
  25. "&:not(:last-child)": {
  26. borderBottom: 0,
  27. },
  28. "&:before": {
  29. display: "none",
  30. },
  31. "&$expanded": {
  32. margin: "auto",
  33. },
  34. },
  35. expanded: {},
  36. })(MuiAccordion);
  37. const AccordionSummary = withStyles({
  38. root: {
  39. backgroundColor: "rgba(0, 0, 0, .03)",
  40. borderBottom: "1px solid rgba(0, 0, 0, .125)",
  41. marginBottom: -1,
  42. minHeight: 56,
  43. "&$expanded": {
  44. minHeight: 56,
  45. },
  46. },
  47. content: {
  48. "&$expanded": {
  49. margin: "12px 0",
  50. },
  51. },
  52. expanded: {},
  53. })(MuiAccordionSummary);
  54. const AccordionDetails = withStyles((theme) => ({
  55. root: {
  56. padding: theme.spacing(2),
  57. },
  58. }))(MuiAccordionDetails);
  59. const GraphPaths = ({ selectedNodes, graphPaths, setSelectedPath, width }) => {
  60. const [fromNode, setFromNode] = React.useState("");
  61. const [toNode, setToNode] = React.useState("");
  62. const [fromNodeId, setFromNodeId] = React.useState(0);
  63. const [toNodeId, setToNodeId] = React.useState(0);
  64. const [fromNodeExpanded, setFromNodeExpanded] = React.useState(false);
  65. const [toNodeExpanded, setToNodeExpanded] = React.useState(false);
  66. const [paneSize, setPaneSize] = React.useState("50%");
  67. const [fromResizeListener, fromSizes] = useResizeAware();
  68. const [toResizeListener, toSizes] = useResizeAware();
  69. const useStyles = makeStyles((theme) => ({
  70. root: {
  71. width: "100%",
  72. maxWidth: width,
  73. backgroundColor: theme.palette.background.paper,
  74. },
  75. nested: {
  76. paddingLeft: theme.spacing(4),
  77. },
  78. listItem: {
  79. width: width,
  80. },
  81. }));
  82. const classes = useStyles();
  83. function toNodeRow({ index, style, data }) {
  84. return (
  85. <ListItem
  86. button
  87. style={style}
  88. key={index}
  89. onClick={() => {
  90. setToNode(data[index].name);
  91. setToNodeId(index);
  92. setToNodeExpanded(false);
  93. setPaneSize("50%");
  94. if (fromNode != "" && data[fromNodeId]) {
  95. const nodes = {
  96. fromNode: data[fromNodeId].node,
  97. toNode: data[index].node,
  98. };
  99. socket.emit("receive_graph_paths", nodes);
  100. }
  101. }}
  102. >
  103. <ListItemText primary={data[index].name} />
  104. </ListItem>
  105. );
  106. }
  107. function fromNodeRow({ index, style, data }) {
  108. return (
  109. <ListItem
  110. button
  111. style={style}
  112. key={index}
  113. onClick={() => {
  114. setFromNode(data[index].name);
  115. setFromNodeId(index);
  116. setFromNodeExpanded(false);
  117. setPaneSize("50%");
  118. if (toNode != "" && data[toNodeId]) {
  119. const nodes = {
  120. fromNode: data[index].node,
  121. toNode: data[toNodeId].node,
  122. };
  123. socket.emit("receive_graph_paths", nodes);
  124. }
  125. }}
  126. >
  127. <ListItemText primary={data[index].name} />
  128. </ListItem>
  129. );
  130. }
  131. function pathRow({ index, style, data }) {
  132. return (
  133. <ListItem
  134. button
  135. style={style}
  136. key={index}
  137. onClick={() => {
  138. setSelectedPath(index);
  139. }}
  140. >
  141. <ListItemText
  142. primary={
  143. "Path #" +
  144. (index + 1).toString() +
  145. " - Hops: " +
  146. (data[index].length - 1).toString()
  147. }
  148. />
  149. </ListItem>
  150. );
  151. }
  152. function listHeight(numItems, minHeight, maxHeight) {
  153. const size = numItems * rowHeight;
  154. if (size > maxHeight) {
  155. return maxHeight;
  156. }
  157. if (size < minHeight) {
  158. return minHeight;
  159. }
  160. return size;
  161. }
  162. const handleToChange = (panel) => (event, newExpanded) => {
  163. setPaneSize(newExpanded ? "0%" : "50%");
  164. setToNodeExpanded(newExpanded ? panel : false);
  165. };
  166. const handleFromChange = (panel) => (event, newExpanded) => {
  167. setPaneSize(newExpanded ? "100%" : "50%");
  168. setFromNodeExpanded(newExpanded ? panel : false);
  169. };
  170. return (
  171. <Paper elevation={3} style={{ backgroundColor: "rgba(0, 0, 0, .03)" }}>
  172. <SplitPane
  173. split="vertical"
  174. minSize={"50%"}
  175. size={paneSize}
  176. style={{ position: "relative" }}
  177. defaultSize={"50%"}
  178. pane1Style={{ height: "100%" }}
  179. pane2Style={{ height: "100%", width: "100%" }}
  180. >
  181. <Accordion
  182. expanded={fromNodeExpanded}
  183. onChange={handleFromChange(!fromNodeExpanded)}
  184. >
  185. <AccordionSummary
  186. expandIcon={<ExpandMoreIcon />}
  187. aria-controls="panel1a-content"
  188. id="panel1a-header"
  189. >
  190. <Box
  191. style={{
  192. display: "flex",
  193. flexDirection: "column",
  194. }}
  195. >
  196. <Typography className={classes.heading}>From Node:</Typography>
  197. <Typography
  198. className={classes.heading}
  199. style={{ width: fromSizes.width - 50 }}
  200. noWrap={true}
  201. display={"block"}
  202. >
  203. {fromResizeListener}
  204. {fromNode}
  205. </Typography>
  206. </Box>
  207. </AccordionSummary>
  208. <AccordionDetails>
  209. <FixedSizeList
  210. height={listHeight(selectedNodes.length, 100, 200)}
  211. width={width}
  212. itemSize={rowHeight}
  213. itemCount={selectedNodes.length}
  214. itemData={selectedNodes}
  215. >
  216. {fromNodeRow}
  217. </FixedSizeList>
  218. </AccordionDetails>
  219. </Accordion>
  220. <Accordion
  221. expanded={toNodeExpanded}
  222. onChange={handleToChange(!toNodeExpanded)}
  223. >
  224. <AccordionSummary
  225. expandIcon={<ExpandMoreIcon />}
  226. aria-controls="panel1a-content"
  227. id="panel1a-header"
  228. >
  229. <Box style={{ display: "flex", flexDirection: "column" }}>
  230. <Typography className={classes.heading}>To Node:</Typography>
  231. <Typography
  232. className={classes.heading}
  233. style={{ width: toSizes.width - 50 }}
  234. noWrap={true}
  235. display={"block"}
  236. >
  237. {toResizeListener}
  238. {toNode}
  239. </Typography>
  240. </Box>
  241. </AccordionSummary>
  242. <AccordionDetails>
  243. <FixedSizeList
  244. height={listHeight(selectedNodes.length, 100, 200)}
  245. width={width}
  246. itemSize={rowHeight}
  247. itemCount={selectedNodes.length}
  248. itemData={selectedNodes}
  249. >
  250. {toNodeRow}
  251. </FixedSizeList>
  252. </AccordionDetails>
  253. </Accordion>
  254. </SplitPane>
  255. <Paper elevation={2} style={{ backgroundColor: "rgba(0, 0, 0, .03)" }}>
  256. <Typography className={classes.heading} style={{ margin: "10px" }}>
  257. Num Paths: {graphPaths.paths.length}{" "}
  258. </Typography>
  259. </Paper>
  260. <FixedSizeList
  261. height={listHeight(graphPaths.paths.length, 100, 200)}
  262. width={width}
  263. itemSize={rowHeight}
  264. itemCount={graphPaths.paths.length}
  265. itemData={graphPaths.paths}
  266. style={{ margin: "10px" }}
  267. >
  268. {pathRow}
  269. </FixedSizeList>
  270. </Paper>
  271. );
  272. };
  273. export default connect(getSelected, { selectedGraphPaths, setSelectedPath })(
  274. GraphPaths
  275. );