From 421a102291cfb1fc1fbbc0fb31d8268e2fd5f0e9 Mon Sep 17 00:00:00 2001 From: Nidhi Tandon Date: Sun, 27 Jun 2021 08:47:46 +0530 Subject: [PATCH] refactor: add ts support to selectedSpanDetails and TraceGanttChartHelpers, change folder structure --- .../modules/Traces/SelectedSpanDetails.tsx | 115 +++++++++--------- .../modules/Traces/TraceGantChartHelpers.js | 41 ------- .../src/modules/Traces/TraceGanttChart.css | 13 -- .../TraceGanttChart/TraceGanttChart.css | 13 ++ .../{ => TraceGanttChart}/TraceGanttChart.tsx | 103 +++++++++------- .../TraceGanttChart/TraceGanttChartHelpers.ts | 40 ++++++ .../modules/Traces/TraceGanttChart/index.js | 1 + .../modules/Traces/TraceGanttChartHelpers.js | 0 frontend/src/modules/Traces/TraceGraph.tsx | 8 +- 9 files changed, 173 insertions(+), 161 deletions(-) delete mode 100644 frontend/src/modules/Traces/TraceGantChartHelpers.js delete mode 100644 frontend/src/modules/Traces/TraceGanttChart.css create mode 100644 frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.css rename frontend/src/modules/Traces/{ => TraceGanttChart}/TraceGanttChart.tsx (81%) create mode 100644 frontend/src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers.ts create mode 100644 frontend/src/modules/Traces/TraceGanttChart/index.js delete mode 100644 frontend/src/modules/Traces/TraceGanttChartHelpers.js diff --git a/frontend/src/modules/Traces/SelectedSpanDetails.tsx b/frontend/src/modules/Traces/SelectedSpanDetails.tsx index 96a350e7d2..699d80fca6 100644 --- a/frontend/src/modules/Traces/SelectedSpanDetails.tsx +++ b/frontend/src/modules/Traces/SelectedSpanDetails.tsx @@ -1,14 +1,14 @@ import React from "react"; import { Card, Space, Tabs, Typography } from "antd"; import styled from "styled-components"; -import { pushDStree } from "../../store/actions"; +import { pushDStree } from "Src/store/actions"; const { TabPane } = Tabs; const { Text } = Typography; interface SelectedSpanDetailsProps { - data: pushDStree + data: pushDStree; } const Title = styled(Text)` @@ -17,79 +17,82 @@ const Title = styled(Text)` `; const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => { - - let spanTags = props.data.tags; + let spanTags = props.data?.tags; let service = props.data?.name?.split(":")[0]; let operation = props.data?.name?.split(":")[1]; return ( - + - Details for selected Span - - Service - - - {service} - + Service + {service} - - Operation - - - {operation} - + Operation + {operation} - {spanTags && spanTags.map((tags, index) => { - return ( - <> - {tags.value && ( - <> - - {tags.key} - -
{ + return ( + <> + {tags.value && ( + <> + + {tags.key} + +
+ {tags.key === "error" ? "true" : tags.value} +
+ + )} + + ); + })} + + + {spanTags && + spanTags + .filter((tags) => tags.key === "error") + .map((error) => ( + <> + + {error.key} + +
- {tags.key === "error" ? "true" : tags.value} -
- - )} - - ); - })} -
- - {spanTags && spanTags - .filter((tags) => tags.key === "error") - .map((error) => ( - <> - - {error.key} - -
- true -
- - ))} + }} + > + true +
+ + ))}
diff --git a/frontend/src/modules/Traces/TraceGantChartHelpers.js b/frontend/src/modules/Traces/TraceGantChartHelpers.js deleted file mode 100644 index fb610b6c5f..0000000000 --- a/frontend/src/modules/Traces/TraceGantChartHelpers.js +++ /dev/null @@ -1,41 +0,0 @@ -// Doing DFS traversal on the tree -// resultCount : how many entries you want. where -1 means all possible entries. -// func(obj) : takes one element of the data structure and returns true if need to select or not - -// program to implement stack data structure -import { isEmpty } from "lodash-es"; - -const getTreeData = (tree, callback, resultCount = -1) => { - if (resultCount === 0 || isEmpty(tree) || tree.id === "empty") return null; - - let data = tree; - let result = []; - let stk = []; - stk.push(data); - - while (!isEmpty(stk)) { - let x = stk[stk.length - 1]; - - // marked means seeing the node for the second time. - if (x.marked) { - delete x.marked; - stk.pop(); - x.map((item) => { - if (callback(item) === true) { - result.push(item); - if (resultCount !== -1 && result.length === resultCount) return result; - } - }); - } else { - x.marked = true; - x.map((item) => { - if (item.children.length > 0) { - stk.push(item.children); - } - }); - } - } - return result; -}; - -export default getTreeData; diff --git a/frontend/src/modules/Traces/TraceGanttChart.css b/frontend/src/modules/Traces/TraceGanttChart.css deleted file mode 100644 index 037b52b651..0000000000 --- a/frontend/src/modules/Traces/TraceGanttChart.css +++ /dev/null @@ -1,13 +0,0 @@ -.row-styles{ - cursor: pointer -} -.hide{ - display: none; -} -.ant-tabs-nav-list{ - justify-content: space-between; - width: 100%; -} -.ant-table-body table { - margin-bottom: 64px; -} \ No newline at end of file diff --git a/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.css b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.css new file mode 100644 index 0000000000..d16aaa1b7f --- /dev/null +++ b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.css @@ -0,0 +1,13 @@ +.row-styles { + cursor: pointer; +} +.hide { + display: none; +} +.ant-tabs-nav-list { + justify-content: space-between; + width: 100%; +} +.ant-table-body table { + margin-bottom: 64px; +} diff --git a/frontend/src/modules/Traces/TraceGanttChart.tsx b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx similarity index 81% rename from frontend/src/modules/Traces/TraceGanttChart.tsx rename to frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx index 844fb4c6e0..7197a9cd04 100644 --- a/frontend/src/modules/Traces/TraceGanttChart.tsx +++ b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx @@ -3,8 +3,8 @@ import { Table, Progress, Tabs, Button, Row, Col } from "antd"; import "./TraceGanttChart.css"; import { max, isEmpty, has } from "lodash-es"; import styled from "styled-components"; -import getTreeData from "Src/modules/Traces/TraceGantChartHelpers"; -import { pushDStree } from "../../store/actions"; +import { pushDStree } from "Src/store/actions"; +import traverseTreeData from "Src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers"; const { TabPane } = Tabs; @@ -17,11 +17,11 @@ const StyledButton = styled(Button)` `; interface TraceGanttChartProps { - treeData: pushDStree; + treeData: pushDStree[]; clickedSpan: pushDStree; selectedSpan: pushDStree; resetZoom: () => {}; - setSpanTagsInfo: () => {}; + setSpanTagsInfo: (p: { data: any }) => {}; } const TraceGanttChart = ({ @@ -37,12 +37,9 @@ const TraceGanttChart = ({ const [defaultExpandedRows, setDefaultExpandedRows] = useState([]); const [sortedTreeData, setSortedTreeData] = useState(treeData); const [isReset, setIsReset] = useState(false); - const [rowId, setRowId] = useState(0); const [tabsContainerWidth, setTabsContainerWidth] = useState(0); const tableRef = useRef(""); - let tabsContainer = document.querySelector( - "#collapsable .ant-tabs-nav-list", - ); + let tabsContainer = document.querySelector("#collapsable .ant-tabs-nav-list"); let tabs = document.querySelectorAll("#collapsable .ant-tabs-tab"); @@ -58,7 +55,7 @@ const TraceGanttChart = ({ if (clickedSpan) { setClickedSpanData(clickedSpan); } - setTabsContainerWidth(tabsContainer?.offsetWidth) + setTabsContainerWidth(tabsContainer?.offsetWidth); } // handleScroll(selectedSpan?.id); }, [sortedTreeData, treeData, clickedSpan]); @@ -67,13 +64,11 @@ const TraceGanttChart = ({ if ( !isEmpty(clickedSpanData) && clickedSpan && - !selectedRows.includes(clickedSpan.id) - && !isReset + !selectedRows.includes(clickedSpan.id) && + !isReset ) { setSelectedRows([clickedSpan.id]); getParentKeys(clickedSpan); - let keys = [clickedSpan?.id, ...parentKeys]; - // setDefaultExpandedRows(keys) handleFocusOnSelectedPath("", [clickedSpan.id], clickedSpan); } }, [clickedSpan, selectedRows, isReset, clickedSpanData]); @@ -87,17 +82,16 @@ const TraceGanttChart = ({ } }; - const getChildrenKeys = (obj) =>{ + const getChildrenKeys = (obj) => { if (has(obj, "children")) { childrenKeys.push(obj.id); - if(!isEmpty(obj.children)){ - obj.children.map((item)=>{ + if (!isEmpty(obj.children)) { + obj.children.map((item) => { getChildrenKeys(item); - }) + }); } - } - } + }; useEffect(() => { if (!isEmpty(selectedSpan) && isEmpty(clickedSpan)) { @@ -111,7 +105,6 @@ const TraceGanttChart = ({ setDefaultExpandedRows([treeData?.[0]?.id]); // /.setSpanTagsInfo({data: treeData?.[0]}) } - }, [selectedSpan, treeData]); const getMaxEndTime = (treeData) => { @@ -142,7 +135,7 @@ const TraceGanttChart = ({ totalWidth = width of container */ const getPaddingLeft = (timeDiff, totalTime, totalWidth) => { - return ((timeDiff / totalTime) * totalWidth ).toFixed(0); + return ((timeDiff / totalTime) * totalWidth).toFixed(0); }; let tabMinVal = 0; @@ -178,14 +171,18 @@ const TraceGanttChart = ({ let paddingLeft = 0; let startTime = parseFloat(record.startTime); let duration = parseFloat((record.time / 1000000).toFixed(2)); - paddingLeft = parseInt(getPaddingLeft(startTime - minGlobal, maxGlobal - minGlobal, tabsContainerWidth)); - let textPadding = paddingLeft; - if(paddingLeft === tabsContainerWidth - 20){ - textPadding = tabsContainerWidth - 40 - } - length = ((duration / (maxGlobal - startTime)) * 100).toFixed( - 2, + paddingLeft = parseInt( + getPaddingLeft( + startTime - minGlobal, + maxGlobal - minGlobal, + tabsContainerWidth, + ), ); + let textPadding = paddingLeft; + if (paddingLeft === tabsContainerWidth - 20) { + textPadding = tabsContainerWidth - 40; + } + length = ((duration / (maxGlobal - startTime)) * 100).toFixed(2); return ( <> @@ -203,15 +200,22 @@ const TraceGanttChart = ({ const handleFocusOnSelectedPath = (event, selectedRowsList = selectedRows) => { if (!isEmpty(selectedRowsList)) { - let node: pushDStree = getTreeData( - treeData, - (item: pushDStree) => item.id === selectedRowsList[0], - 1, - ); - setSpanTagsInfo({ data: node[0] }); + let node = {}; + traverseTreeData(treeData, (item: pushDStree) => { + if (item.id === selectedRowsList[0]) { + node = item; + } + }); - getParentKeys(node[0]); - getChildrenKeys(node[0]); + try { + setSpanTagsInfo({ data: node }); + } catch (e) { + // TODO: error logging. + console.error("Node not found in Tree Data."); + } + + getParentKeys(node); + getChildrenKeys(node); let rows = document.querySelectorAll("#collapsable table tbody tr"); Array.from(rows).map((row) => { @@ -255,21 +259,26 @@ const TraceGanttChart = ({ setIsReset(false); } }, - onSelect:(record)=>{ - handleRowOnClick(record) + onSelect: (record) => { + handleRowOnClick(record); }, selectedRowKeys: selectedRows, }; const handleRowOnClick = (record) => { - setRowId(record.id); + let node = {}; + traverseTreeData(treeData, (item: pushDStree) => { + if (item.id === record.id) { + node = item; + } + }); - let node: pushDStree = getTreeData( - treeData, - (item: pushDStree) => item.id === record.id, - 1, - ); - setSpanTagsInfo({ data: node[0] }); + try { + setSpanTagsInfo({ data: node }); + } catch (e) { + // TODO: error logging. + console.error("Node not found in TreeData."); + } const selectedRowKeys = selectedRows; if (selectedRowKeys.indexOf(record.id) >= 0) { @@ -310,7 +319,7 @@ const TraceGanttChart = ({ refs={tableRef} hideSelectAll={true} columns={columns} - rowSelection={{ ...rowSelection, checkStrictly, type:'radio' }} + rowSelection={{ ...rowSelection, checkStrictly, type: "radio" }} dataSource={sortedTreeData} rowKey="id" sticky={true} @@ -322,7 +331,7 @@ const TraceGanttChart = ({ expandedRowKeys={defaultExpandedRows} onExpandedRowsChange={handleOnExpandedRowsChange} pagination={false} - scroll={{ y: 540}} + scroll={{ y: 540 }} rowClassName="row-styles" filterMultiple={false} /> diff --git a/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers.ts b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers.ts new file mode 100644 index 0000000000..534de8b8c0 --- /dev/null +++ b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers.ts @@ -0,0 +1,40 @@ +import { isEmpty } from "lodash-es"; +import { pushDStree } from "Src/store/actions"; + +interface itemProps { + treeData: pushDStree[]; + marked: boolean; +} + +// Doing DFS traversal on the tree. +// Callback to be called for each element in the tree once. +const traverseTreeData = ( + tree: pushDStree[], + callback: (item: pushDStree) => void, +): void => { + if (isEmpty(tree) || tree[0].id === "empty") return; + let node = { treeData: tree, marked: false }; + let stk: [itemProps] = [node]; + + while (!isEmpty(stk)) { + let x = stk[stk.length - 1]; + + // marked means seeing the node for the second time. + if (x.marked) { + x.marked = false; + stk.pop(); + x.treeData.map((item: pushDStree) => { + callback(item); + }); + } else { + x.marked = true; + x.treeData.map((item) => { + if (item.children.length > 0) { + stk.push({ treeData: item.children, marked: false }); + } + }); + } + } +}; + +export default traverseTreeData; diff --git a/frontend/src/modules/Traces/TraceGanttChart/index.js b/frontend/src/modules/Traces/TraceGanttChart/index.js new file mode 100644 index 0000000000..345b7af8bc --- /dev/null +++ b/frontend/src/modules/Traces/TraceGanttChart/index.js @@ -0,0 +1 @@ +export { default } from "./TraceGanttChart"; diff --git a/frontend/src/modules/Traces/TraceGanttChartHelpers.js b/frontend/src/modules/Traces/TraceGanttChartHelpers.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frontend/src/modules/Traces/TraceGraph.tsx b/frontend/src/modules/Traces/TraceGraph.tsx index 1e8dbd3a44..ab7501bc74 100644 --- a/frontend/src/modules/Traces/TraceGraph.tsx +++ b/frontend/src/modules/Traces/TraceGraph.tsx @@ -6,13 +6,13 @@ import { Card, Row, Col, Space, Affix } from "antd"; import * as d3 from "d3"; import * as d3Tip from "d3-tip"; import "./TraceGraph.css"; -import { spanToTreeUtil } from "../../utils/spanToTree"; +import { spanToTreeUtil } from "Src/utils/spanToTree"; import { fetchTraceItem, pushDStree, spansWSameTraceIDResponse, } from "../../store/actions"; -import { StoreState } from "../../store/reducers"; +import { StoreState } from "Src/store/reducers"; import SelectedSpanDetails from "./SelectedSpanDetails"; import TraceGanttChart from "./TraceGanttChart"; import styled from "styled-components"; @@ -36,11 +36,11 @@ const _TraceGraph = (props: TraceGraphProps) => { const [selectedSpan, setSelectedSpan] = useState({}); const [clickedSpan, setClickedSpan] = useState(null); const [resetZoom, setResetZoom] = useState(false); - const [sortedTreeData, setSortedTreeData] = useState([]); + const [sortedTreeData, setSortedTreeData] = useState([]); let sortedData = {}; - const getSortedData = (treeData: [pushDStree], parent = {}) => { + const getSortedData = (treeData: pushDStree[], parent = {}) => { if (!isEmpty(treeData)) { if (treeData[0].id !== "empty") { return Array.from(treeData).map((item, key) => {