diff --git a/web/src/components/AnalyzerResult/RuleResult.tsx b/web/src/components/AnalyzerResult/RuleResult.tsx
index 89a42f8bd1..9ad5ce6a10 100644
--- a/web/src/components/AnalyzerResult/RuleResult.tsx
+++ b/web/src/components/AnalyzerResult/RuleResult.tsx
@@ -27,36 +27,46 @@ const RuleResult = ({index, data: {results, id, errorDescription}, style}: IProp
dispatch(selectSpan({spanId}));
}, [dispatch, spanId]);
- return (
-
-
} onClick={onClick} type="link" $error={!passed}>
- {trace.flat[spanId].name ?? ''}
-
+ const getTooltipOverlayFn = useMemo(
+ () =>
+ !passed && !!errors.length
+ ? () => (
+ <>
+ {errors.length > 1 && (
+ <>
+
+ {errorDescription}
+
+
+ {errors.map(error => (
+
+ {error.value}
+
+ ))}
+
+ >
+ )}
- {!passed && errors.length > 1 && (
- <>
-
- {errorDescription}
-
-
- {errors.map(error => (
-
-
- {error.value}
-
-
- ))}
-
- >
- )}
+ {errors.length === 1 && (
+
+ {errors[0].description}
+
+ )}
- {!passed && errors.length === 1 && (
-
- {errors[0].description}
-
- )}
+
+ >
+ )
+ : null,
+ [passed, errors, errorDescription, id]
+ );
- {!passed &&
}
+ return (
+
+
+ } onClick={onClick} type="link" $error={!passed}>
+ {trace.flat[spanId].name ?? ''}
+
+
);
};
diff --git a/web/src/components/ResizablePanels/FillPanel.tsx b/web/src/components/ResizablePanels/FillPanel.tsx
index 4973a4df75..207c688695 100644
--- a/web/src/components/ResizablePanels/FillPanel.tsx
+++ b/web/src/components/ResizablePanels/FillPanel.tsx
@@ -1,5 +1,5 @@
import * as Spaces from 'react-spaces';
-const FillPanel: React.FC = ({children}) =>
{children};
+const FillPanel: React.FC = ({children}) =>
{children};
export default FillPanel;
diff --git a/web/src/components/RunDetailTest/RunDetailTest.styled.ts b/web/src/components/RunDetailTest/RunDetailTest.styled.ts
index 8c3b8eb12b..795ce5e272 100644
--- a/web/src/components/RunDetailTest/RunDetailTest.styled.ts
+++ b/web/src/components/RunDetailTest/RunDetailTest.styled.ts
@@ -1,5 +1,5 @@
import {Badge} from 'antd';
-import styled from 'styled-components';
+import styled, {css} from 'styled-components';
export const Container = styled.div`
display: flex;
@@ -11,10 +11,17 @@ export const Section = styled.div`
flex: 1;
`;
-export const SectionLeft = styled(Section)`
+export const SectionLeft = styled(Section)<{$isTimeline: boolean}>`
background-color: ${({theme}) => theme.color.background};
box-shadow: inset 20px 0px 24px -20px rgba(153, 155, 168, 0.18), inset -20px 0 24px -20px rgba(153, 155, 168, 0.18);
z-index: 1;
+
+ ${({$isTimeline}) =>
+ $isTimeline &&
+ css`
+ max-size: calc(100% - 695px);
+ overflow: scroll;
+ `}
`;
export const SectionRight = styled(Section)`
diff --git a/web/src/components/RunDetailTest/TestPanel.tsx b/web/src/components/RunDetailTest/TestPanel.tsx
index e7b3b19dd8..34d17c6485 100644
--- a/web/src/components/RunDetailTest/TestPanel.tsx
+++ b/web/src/components/RunDetailTest/TestPanel.tsx
@@ -100,18 +100,10 @@ const TestPanel = ({run, testId, runEvents}: IProps) => {
[revert]
);
- const handleSelectSpan = useCallback(
- (spanId: string) => {
- onSelectSpan(spanId);
- onSetFocusedSpan(spanId);
- },
- [onSelectSpan, onSetFocusedSpan]
- );
-
return (
-
+
{run.state === TestState.FINISHED && (
) : (
- `
display: flex;
height: 100%;
width: 100%;
+ min-width: ${({$isTimeline}) => $isTimeline && '1000px'};
`;
export const SearchContainer = styled.div`
diff --git a/web/src/components/RunDetailTrace/RunDetailTrace.tsx b/web/src/components/RunDetailTrace/RunDetailTrace.tsx
index 5953b75b25..07a43fa872 100644
--- a/web/src/components/RunDetailTrace/RunDetailTrace.tsx
+++ b/web/src/components/RunDetailTrace/RunDetailTrace.tsx
@@ -26,7 +26,7 @@ export function getIsDAGDisabled(totalSpans: number = 0): boolean {
const RunDetailTrace = ({run, runEvents, testId, skipTraceCollection}: IProps) => {
return (
-
+
diff --git a/web/src/components/RunDetailTrace/TracePanel.tsx b/web/src/components/RunDetailTrace/TracePanel.tsx
index ed958e3f09..5b7a3dacb8 100644
--- a/web/src/components/RunDetailTrace/TracePanel.tsx
+++ b/web/src/components/RunDetailTrace/TracePanel.tsx
@@ -26,7 +26,7 @@ const TracePanel = ({run, testId, runEvents, skipTraceCollection}: TProps) => {
return (
-
+
diff --git a/web/src/components/RunDetailTrace/Visualization.tsx b/web/src/components/RunDetailTrace/Visualization.tsx
index b2a52f9135..00b889975c 100644
--- a/web/src/components/RunDetailTrace/Visualization.tsx
+++ b/web/src/components/RunDetailTrace/Visualization.tsx
@@ -9,7 +9,7 @@ import TraceSelectors from 'selectors/Trace.selectors';
import TestRunService from 'services/TestRun.service';
import Trace from 'models/Trace.model';
import {TTestRunState} from 'types/TestRun.types';
-import TimelineV2 from 'components/Visualization/components/Timeline/TimelineV2';
+import TimelineV2 from 'components/Visualization/components/Timeline/Timeline';
import {VisualizationType} from './RunDetailTrace';
import TraceDAG from './TraceDAG';
diff --git a/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNode.tsx b/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNode.tsx
index ff6a241e24..af6908a38e 100644
--- a/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNode.tsx
+++ b/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNode.tsx
@@ -1,75 +1,61 @@
-import {Group} from '@visx/group';
-
-import {AxisOffset, BaseLeftPadding, NodeHeight, NodeOverlayHeight} from 'constants/Timeline.constants';
import Span from 'models/Span.model';
-import Collapse from './Collapse';
import Connector from './Connector';
-import Label from './Label';
import {IPropsComponent} from '../SpanNodeFactory';
+import {useTimeline} from '../Timeline.provider';
import * as S from '../Timeline.styled';
+function toPercent(value: number) {
+ return `${(value * 100).toFixed(1)}%`;
+}
+
+function getHintSide(viewStart: number, viewEnd: number) {
+ return viewStart > 1 - viewEnd ? 'left' : 'right';
+}
+
interface IProps extends IPropsComponent {
- className?: string;
- header?: React.ReactNode;
span: Span;
}
-const BaseSpanNode = ({
- className,
- header,
- index,
- indexParent,
- isCollapsed = false,
- isMatched = false,
- isSelected = false,
- minStartTime,
- node,
- onClick,
- onCollapse,
- span,
- xScale,
-}: IProps) => {
- const isParent = Boolean(node.children);
- const hasParent = indexParent !== -1;
- const positionTop = index * NodeHeight;
- const durationWidth = span.endTime - span.startTime;
- const durationX = span.startTime - minStartTime;
- const leftPadding = node.depth * BaseLeftPadding;
+const BaseSpanNode = ({index, node, span, style}: IProps) => {
+ const {collapsedSpans, getScale, matchedSpans, onSpanCollapse, onSpanClick, selectedSpan} = useTimeline();
+ const {start: viewStart, end: viewEnd} = getScale(span.startTime, span.endTime);
+ const hintSide = getHintSide(viewStart, viewEnd);
+ const isSelected = selectedSpan === node.data.id;
+ const isMatched = matchedSpans.includes(node.data.id);
+ const isCollapsed = collapsedSpans.includes(node.data.id);
return (
-
- {hasParent && }
-
- onClick(node.data.id)} top={0}>
-
-
-
-
-
-
- {isParent && (
-
- )}
-
-
-
-
-
-
+
+ onSpanClick(node.data.id)}
+ $isEven={index % 2 === 0}
+ $isMatched={isMatched}
+ $isSelected={isSelected}
+ >
+
+
+
+
+ {span.name}
+
+
+
+
+
+
+
+ {span.duration}
+
+
+
+
);
};
diff --git a/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNodeV2.tsx b/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNodeV2.tsx
deleted file mode 100644
index 96934f48a1..0000000000
--- a/web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNodeV2.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import Span from 'models/Span.model';
-import Connector from './ConnectorV2';
-import {IPropsComponent} from '../SpanNodeFactoryV2';
-import {useTimeline} from '../Timeline.provider';
-import * as S from '../TimelineV2.styled';
-
-function toPercent(value: number) {
- return `${(value * 100).toFixed(1)}%`;
-}
-
-function getHintSide(viewStart: number, viewEnd: number) {
- return viewStart > 1 - viewEnd ? 'left' : 'right';
-}
-
-interface IProps extends IPropsComponent {
- span: Span;
-}
-
-const BaseSpanNode = ({index, node, span, style}: IProps) => {
- const {collapsedSpans, getScale, matchedSpans, onSpanCollapse, onSpanClick, selectedSpan} = useTimeline();
- const {start: viewStart, end: viewEnd} = getScale(span.startTime, span.endTime);
- const hintSide = getHintSide(viewStart, viewEnd);
- const isSelected = selectedSpan === node.data.id;
- const isMatched = matchedSpans.includes(node.data.id);
- const isCollapsed = collapsedSpans.includes(node.data.id);
-
- return (
-
- onSpanClick(node.data.id)}
- $isEven={index % 2 === 0}
- $isMatched={isMatched}
- $isSelected={isSelected}
- >
-
-
-
-
- {span.name}
-
-
-
-
-
-
-
- {span.duration}
-
-
-
-
- );
-};
-
-export default BaseSpanNode;
diff --git a/web/src/components/Visualization/components/Timeline/BaseSpanNode/Collapse.tsx b/web/src/components/Visualization/components/Timeline/BaseSpanNode/Collapse.tsx
deleted file mode 100644
index 7844c5349a..0000000000
--- a/web/src/components/Visualization/components/Timeline/BaseSpanNode/Collapse.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import * as S from '../Timeline.styled';
-
-interface IProps {
- id: string;
- isCollapsed?: boolean;
- onCollapse(id: string): void;
- totalChildren: number;
-}
-
-const collapsedShape = 'M18.629 15.997l-7.083-7.081L13.462 7l8.997 8.997L13.457 25l-1.916-1.916z';
-const expandedShape = 'M16.003 18.626l7.081-7.081L25 13.46l-8.997 8.998-9.003-9 1.917-1.916z';
-
-const Collapse = ({id, isCollapsed, onCollapse, totalChildren}: IProps) => (
- {
- event.stopPropagation();
- onCollapse(id);
- }}
- top={0}
- >
-
-
-
-
- {totalChildren}
-
-
-);
-
-export default Collapse;
diff --git a/web/src/components/Visualization/components/Timeline/BaseSpanNode/Connector.tsx b/web/src/components/Visualization/components/Timeline/BaseSpanNode/Connector.tsx
index 56e79b9f15..574280caab 100644
--- a/web/src/components/Visualization/components/Timeline/BaseSpanNode/Connector.tsx
+++ b/web/src/components/Visualization/components/Timeline/BaseSpanNode/Connector.tsx
@@ -1,19 +1,55 @@
-import {NodeHeight} from 'constants/Timeline.constants';
+import {BaseLeftPaddingV2} from 'constants/Timeline.constants';
import * as S from '../Timeline.styled';
interface IProps {
- distance: number;
- leftPadding: number;
+ hasParent: boolean;
+ id: string;
+ isCollapsed: boolean;
+ nodeDepth: number;
+ onCollapse(id: string): void;
+ totalChildren: number;
}
-const Connector = ({distance, leftPadding}: IProps) => {
- const connectorX = distance * NodeHeight - 24;
+const Connector = ({hasParent, id, isCollapsed, nodeDepth, onCollapse, totalChildren}: IProps) => {
+ const leftPadding = nodeDepth * BaseLeftPaddingV2;
return (
- <>
-
-
- >
+
+ {hasParent && (
+ <>
+
+
+ >
+ )}
+
+ {totalChildren > 0 ? (
+ <>
+ {!isCollapsed && }
+
+
+ {totalChildren}
+
+ {
+ event.stopPropagation();
+ onCollapse(id);
+ }}
+ />
+ >
+ ) : (
+
+ )}
+
+ {new Array(nodeDepth).fill(0).map((_, index) => {
+ return ;
+ })}
+
);
};
diff --git a/web/src/components/Visualization/components/Timeline/BaseSpanNode/ConnectorV2.tsx b/web/src/components/Visualization/components/Timeline/BaseSpanNode/ConnectorV2.tsx
deleted file mode 100644
index cb332a3f84..0000000000
--- a/web/src/components/Visualization/components/Timeline/BaseSpanNode/ConnectorV2.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import {BaseLeftPaddingV2} from 'constants/Timeline.constants';
-import * as S from '../TimelineV2.styled';
-
-interface IProps {
- hasParent: boolean;
- id: string;
- isCollapsed: boolean;
- nodeDepth: number;
- onCollapse(id: string): void;
- totalChildren: number;
-}
-
-const Connector = ({hasParent, id, isCollapsed, nodeDepth, onCollapse, totalChildren}: IProps) => {
- const leftPadding = nodeDepth * BaseLeftPaddingV2;
-
- return (
-
- {hasParent && (
- <>
-
-
- >
- )}
-
- {totalChildren > 0 ? (
- <>
- {!isCollapsed && }
-
-
- {totalChildren}
-
- {
- event.stopPropagation();
- onCollapse(id);
- }}
- />
- >
- ) : (
-
- )}
-
- {new Array(nodeDepth).fill(0).map((_, index) => {
- return ;
- })}
-
- );
-};
-
-export default Connector;
diff --git a/web/src/components/Visualization/components/Timeline/BaseSpanNode/Label.tsx b/web/src/components/Visualization/components/Timeline/BaseSpanNode/Label.tsx
deleted file mode 100644
index b741c0fc5d..0000000000
--- a/web/src/components/Visualization/components/Timeline/BaseSpanNode/Label.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import {Group} from '@visx/group';
-
-import settingIcon from 'assets/setting.svg';
-import {SemanticGroupNames, SemanticGroupNamesToText} from 'constants/SemanticGroupNames.constants';
-import {SpanKind, SpanKindToText} from 'constants/Span.constants';
-import * as S from '../Timeline.styled';
-
-interface IProps {
- duration: string;
- header?: React.ReactNode;
- kind: SpanKind;
- name: string;
- service: string;
- system: string;
- type: SemanticGroupNames;
-}
-
-const Label = ({duration, header, kind, name, service, system, type}: IProps) => (
-
-
-
-
- {SemanticGroupNamesToText[type]}
-
-
-
-
- {header}
-
-
-
-
- {name}
-
-
-
-
-
- {`${service} ${SpanKindToText[kind]}`}
- {Boolean(system) && {` - ${system}`}}
- {` - ${duration}`}
-
-
-
-);
-
-export default Label;
diff --git a/web/src/components/Visualization/components/Timeline/Header.tsx b/web/src/components/Visualization/components/Timeline/Header.tsx
index d5ff7cdc41..ed12e7f44f 100644
--- a/web/src/components/Visualization/components/Timeline/Header.tsx
+++ b/web/src/components/Visualization/components/Timeline/Header.tsx
@@ -1,5 +1,5 @@
import Ticks from './Ticks/Ticks';
-import * as S from './TimelineV2.styled';
+import * as S from './Timeline.styled';
const NUM_TICKS = 5;
diff --git a/web/src/components/Visualization/components/Timeline/ListWrapper.tsx b/web/src/components/Visualization/components/Timeline/ListWrapper.tsx
index cda954bfb7..cc8af525dd 100644
--- a/web/src/components/Visualization/components/Timeline/ListWrapper.tsx
+++ b/web/src/components/Visualization/components/Timeline/ListWrapper.tsx
@@ -1,7 +1,7 @@
import {FixedSizeList as List} from 'react-window';
import Header from './Header';
-import SpanNodeFactory from './SpanNodeFactoryV2';
-import * as S from './TimelineV2.styled';
+import SpanNodeFactory from './SpanNodeFactory';
+import * as S from './Timeline.styled';
import {useTimeline} from './Timeline.provider';
const HEADER_HEIGHT = 242;
diff --git a/web/src/components/Visualization/components/Timeline/SpanNodeFactory.tsx b/web/src/components/Visualization/components/Timeline/SpanNodeFactory.tsx
index 877cd4b46f..fb61d7f081 100644
--- a/web/src/components/Visualization/components/Timeline/SpanNodeFactory.tsx
+++ b/web/src/components/Visualization/components/Timeline/SpanNodeFactory.tsx
@@ -1,35 +1,30 @@
-import {AxisScale} from '@visx/axis';
import {NodeTypesEnum} from 'constants/Visualization.constants';
import {TNode} from 'types/Timeline.types';
-import TestSpanNode from './TestSpanNode/TestSpanNode';
+// import TestSpanNode from './TestSpanNode/TestSpanNode';
import TraceSpanNode from './TraceSpanNode/TraceSpanNode';
export interface IPropsComponent {
index: number;
- indexParent: number;
- isCollapsed?: boolean;
- isMatched?: boolean;
- isSelected?: boolean;
- minStartTime: number;
node: TNode;
- onClick(id: string): void;
- onCollapse(id: string): void;
- xScale: AxisScale;
+ style: React.CSSProperties;
}
const ComponentMap: Record React.ReactElement> = {
- [NodeTypesEnum.TestSpan]: TestSpanNode,
+ [NodeTypesEnum.TestSpan]: TraceSpanNode,
[NodeTypesEnum.TraceSpan]: TraceSpanNode,
};
-interface IProps extends IPropsComponent {
- type: NodeTypesEnum;
+interface IProps {
+ data: TNode[];
+ index: number;
+ style: React.CSSProperties;
}
-const SpanNodeFactory = ({type, ...props}: IProps) => {
- const Component = ComponentMap[type];
+const SpanNodeFactory = ({data, ...props}: IProps) => {
+ const node = data[props.index];
+ const Component = ComponentMap[node.type];
- return ;
+ return ;
};
export default SpanNodeFactory;
diff --git a/web/src/components/Visualization/components/Timeline/SpanNodeFactoryV2.tsx b/web/src/components/Visualization/components/Timeline/SpanNodeFactoryV2.tsx
deleted file mode 100644
index 9e6aed970c..0000000000
--- a/web/src/components/Visualization/components/Timeline/SpanNodeFactoryV2.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import {NodeTypesEnum} from 'constants/Visualization.constants';
-import {TNode} from 'types/Timeline.types';
-// import TestSpanNode from './TestSpanNode/TestSpanNode';
-import TraceSpanNode from './TraceSpanNode/TraceSpanNodeV2';
-
-export interface IPropsComponent {
- index: number;
- node: TNode;
- style: React.CSSProperties;
-}
-
-const ComponentMap: Record React.ReactElement> = {
- [NodeTypesEnum.TestSpan]: TraceSpanNode,
- [NodeTypesEnum.TraceSpan]: TraceSpanNode,
-};
-
-interface IProps {
- data: TNode[];
- index: number;
- style: React.CSSProperties;
-}
-
-const SpanNodeFactory = ({data, ...props}: IProps) => {
- const node = data[props.index];
- const Component = ComponentMap[node.type];
-
- return ;
-};
-
-export default SpanNodeFactory;
diff --git a/web/src/components/Visualization/components/Timeline/TestSpanNode/Header.tsx b/web/src/components/Visualization/components/Timeline/TestSpanNode/Header.tsx
deleted file mode 100644
index 719cc274e2..0000000000
--- a/web/src/components/Visualization/components/Timeline/TestSpanNode/Header.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import {Group} from '@visx/group';
-import * as S from '../Timeline.styled';
-
-interface IProps {
- hasOutputs?: boolean;
- totalFailedChecks?: number;
- totalPassedChecks?: number;
-}
-
-function getOutputsX(totalFailedChecks?: number, totalPassedChecks?: number): number {
- if (totalFailedChecks && totalPassedChecks) {
- return 44;
- }
- if (totalFailedChecks || totalPassedChecks) {
- return 24;
- }
-
- return 0;
-}
-
-const Header = ({hasOutputs, totalFailedChecks, totalPassedChecks}: IProps) => {
- const failedChecksX = totalPassedChecks ? 20 : 0;
- const outputsX = getOutputsX(totalFailedChecks, totalPassedChecks);
-
- return (
- <>
-
- {!!totalPassedChecks && (
- <>
-
-
- {totalPassedChecks}
-
- >
- )}
- {!!totalFailedChecks && (
- <>
-
-
- {totalFailedChecks}
-
- >
- )}
-
-
- {hasOutputs && (
- <>
-
-
- O
-
- >
- )}
-
- >
- );
-};
-
-export default Header;
diff --git a/web/src/components/Visualization/components/Timeline/TestSpanNode/SelectAsCurrent.tsx b/web/src/components/Visualization/components/Timeline/TestSpanNode/SelectAsCurrent.tsx
deleted file mode 100644
index cc19df7d63..0000000000
--- a/web/src/components/Visualization/components/Timeline/TestSpanNode/SelectAsCurrent.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import {Group} from '@visx/group';
-import * as S from '../Timeline.styled';
-
-interface IProps {
- isLoading: boolean;
- onSelectAsCurrent(): void;
- positionTop: number;
-}
-
-const SelectAsCurrent = ({isLoading, onSelectAsCurrent, positionTop}: IProps) => (
- !isLoading && onSelectAsCurrent()}>
-
-
- {isLoading ? 'Updating selected span' : 'Select as current span'}
-
-
-);
-
-export default SelectAsCurrent;
diff --git a/web/src/components/Visualization/components/Timeline/TestSpanNode/TestSpanNode.tsx b/web/src/components/Visualization/components/Timeline/TestSpanNode/TestSpanNode.tsx
deleted file mode 100644
index aa6ccc64dd..0000000000
--- a/web/src/components/Visualization/components/Timeline/TestSpanNode/TestSpanNode.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import {NodeHeight} from 'constants/Timeline.constants';
-import useSpanData from 'hooks/useSpanData';
-import Header from './Header';
-import SelectAsCurrent from './SelectAsCurrent';
-import BaseSpanNode from '../BaseSpanNode/BaseSpanNode';
-import {IPropsComponent} from '../SpanNodeFactory';
-import useSelectAsCurrent from '../../../hooks/useSelectAsCurrent';
-
-const TestSpanNode = (props: IPropsComponent) => {
- const {index, isMatched, isSelected, node} = props;
- const {span, testSpecs, testOutputs} = useSpanData(node.data.id);
- const {isLoading, onSelectAsCurrent, showSelectAsCurrent} = useSelectAsCurrent({
- selected: isSelected ?? false,
- matched: isMatched ?? false,
- span,
- });
- const positionTop = index * NodeHeight;
-
- return (
- <>
-
- }
- span={span}
- />
- {showSelectAsCurrent && (
-
- )}
- >
- );
-};
-
-export default TestSpanNode;
diff --git a/web/src/components/Visualization/components/Timeline/Timeline.styled.ts b/web/src/components/Visualization/components/Timeline/Timeline.styled.ts
index 285dcd96f6..42ef21dce2 100644
--- a/web/src/components/Visualization/components/Timeline/Timeline.styled.ts
+++ b/web/src/components/Visualization/components/Timeline/Timeline.styled.ts
@@ -1,132 +1,151 @@
-import {Group} from '@visx/group';
+import {Typography} from 'antd';
+import {SemanticGroupNames, SemanticGroupNamesToColor} from 'constants/SemanticGroupNames.constants';
import styled, {css} from 'styled-components';
-import {
- SemanticGroupNames,
- SemanticGroupNamesToColor,
- SemanticGroupNamesToLightColor,
-} from 'constants/SemanticGroupNames.constants';
+export const Container = styled.div`
+ padding: 50px 24px 0 24px;
+ min-width: 1000px;
+`;
-export const Container = styled.div<{$showMatched: boolean}>`
- height: 100%;
- padding: 24px;
- padding-left: 50px;
- position: relative;
+export const Row = styled.div<{$isEven: boolean; $isMatched: boolean; $isSelected: boolean}>`
+ background-color: ${({theme, $isEven}) => ($isEven ? theme.color.background : theme.color.white)};
+ display: grid;
+ grid-template-columns: 300px 1fr;
+ grid-template-rows: 32px;
+ padding: 0px 16px;
+
+ :hover {
+ background-color: ${({theme}) => theme.color.backgroundInteractive};
+ }
+
+ ${({$isMatched}) =>
+ $isMatched &&
+ css`
+ background-color: ${({theme}) => theme.color.alertYellow};
+ `};
- ${({$showMatched}) =>
- $showMatched &&
+ ${({$isSelected}) =>
+ $isSelected &&
css`
- .timeline-node-traceSpan > g:not(.matched),
- .timeline-node-testSpan > g:not(.matched):not(.selectedAsCurrent) {
- opacity: 0.5;
+ background: rgba(97, 23, 94, 0.1);
+
+ :hover {
+ background: rgba(97, 23, 94, 0.1);
}
- `}
+ `};
`;
-export const CircleArrow = styled.circle`
- fill: transparent;
+export const Col = styled.div`
+ display: grid;
+ grid-template-columns: 1fr 8px;
`;
-export const CircleCheck = styled.circle<{$passed: boolean}>`
- fill: ${({$passed, theme}) => ($passed ? theme.color.success : theme.color.error)};
+export const ColDuration = styled.div`
+ overflow: hidden;
+ position: relative;
`;
-export const CircleNumber = styled.circle`
- fill: ${({theme}) => theme.color.borderLight};
+export const Header = styled.div`
+ align-items: center;
+ display: flex;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
`;
-export const GroupCollapse = styled(Group)`
- cursor: pointer;
+export const NameContainer = styled.div`
+ overflow: hidden;
+ text-overflow: ellipsis;
`;
-export const Image = styled.image<{$width?: number; $height?: number}>`
- height: ${({$height}) => $height ?? 8}px;
- width: ${({$width}) => $width ?? 8}px;
+export const Separator = styled.div`
+ border-left: 1px solid rgb(222, 227, 236);
+ cursor: ew-resize;
+ height: 32px;
+ padding: 0px 3px;
+ width: 1px;
`;
-export const LineConnector = styled.line`
- stroke: ${({theme}) => theme.color.textLight};
+export const Title = styled(Typography.Text)`
+ color: ${({theme}) => theme.color.text};
+ font-size: ${({theme}) => theme.size.sm};
+ font-weight: 400;
`;
-export const PathArrow = styled.path`
- fill: ${({theme}) => theme.color.textLight};
- transform: scale(0.6);
+export const Connector = styled.svg`
+ flex-shrink: 0;
+ overflow: hidden;
+ overflow-clip-margin: content-box;
`;
-export const RectBadge = styled.rect<{$type: SemanticGroupNames}>`
- fill: ${({$type}) => SemanticGroupNamesToLightColor[$type]};
- height: 12px;
- width: 50px;
- pointer-events: none;
+export const SpanBar = styled.div<{$type: SemanticGroupNames}>`
+ background-color: ${({$type}) => SemanticGroupNamesToColor[$type]};
+ border-radius: 3px;
+ height: 18px;
+ min-width: 2px;
+ position: absolute;
+ top: 7px;
`;
-export const RectDuration = styled.rect<{$type: SemanticGroupNames}>`
- fill: ${({$type}) => SemanticGroupNamesToColor[$type]};
- height: 6px;
- pointer-events: none;
-`;
+export const SpanBarLabel = styled.div<{$side: 'left' | 'right'}>`
+ color: ${({theme}) => theme.color.textSecondary};
+ font-size: ${({theme}) => theme.size.xs};
+ padding: 1px 4px 0 4px;
+ position: absolute;
-export const RectDurationGuideline = styled.rect`
- fill: ${({theme}) => theme.color.borderLight};
- height: 1px;
- pointer-events: none;
- width: 100%;
+ ${({$side}) =>
+ $side === 'left'
+ ? css`
+ right: 100%;
+ `
+ : css`
+ left: 100%;
+ `};
`;
-export const RectSelectAsCurrent = styled.rect`
- cursor: pointer;
- fill: ${({theme}) => theme.color.interactive};
- height: 12px;
- width: 124px;
+export const TextConnector = styled.text<{$isActive?: boolean}>`
+ fill: ${({theme, $isActive}) => ($isActive ? theme.color.white : theme.color.text)};
+ font-size: ${({theme}) => theme.size.xs};
`;
-export const RectOutput = styled.rect`
- fill: ${({theme}) => theme.color.warningYellow};
- height: 12px;
- width: 12px;
+export const CircleDot = styled.circle`
+ fill: ${({theme}) => theme.color.textSecondary};
+ stroke-width: 2;
+ stroke: ${({theme}) => theme.color.white};
`;
-export const RectOverlay = styled.rect<{$isMatched: boolean; $isSelected: boolean}>`
- cursor: grab;
- fill: ${({$isSelected, theme}) => ($isSelected ? theme.color.backgroundInteractive : 'transparent')};
- stroke: ${({$isMatched, theme}) => $isMatched && theme.color.text};
- stroke: ${({$isSelected, theme}) => $isSelected && theme.color.interactive};
- width: 100%;
-
- :hover {
- fill: ${({theme}) => theme.color.backgroundInteractive};
- }
+export const LineBase = styled.line`
+ stroke: ${({theme}) => theme.color.borderLight};
`;
-export const TextBadge = styled.text`
- fill: ${({theme}) => theme.color.text};
- font-size: 8px;
- pointer-events: none;
- text-transform: uppercase;
+export const RectBase = styled.rect<{$isActive?: boolean}>`
+ fill: ${({theme, $isActive}) => ($isActive ? theme.color.primary : theme.color.white)};
+ stroke: ${({theme}) => theme.color.textSecondary};
`;
-export const TextDescription = styled.text`
- fill: ${({theme}) => theme.color.text};
- font-size: ${({theme}) => theme.size.xs};
- pointer-events: none;
+export const RectBaseTransparent = styled(RectBase)`
+ cursor: pointer;
+ fill: transparent;
`;
-export const TextName = styled.text`
- fill: ${({theme}) => theme.color.text};
- font-size: ${({theme}) => theme.size.sm};
- font-weight: 600;
- pointer-events: none;
+export const HeaderRow = styled.div`
+ background-color: ${({theme}) => theme.color.white};
+ display: grid;
+ grid-template-columns: 300px 1fr;
+ grid-template-rows: 32px;
+ padding: 0px 16px;
`;
-export const TextNumber = styled.text`
- fill: ${({theme}) => theme.color.textLight};
- font-size: ${({theme}) => theme.size.sm};
- pointer-events: none;
+export const HeaderContent = styled.div`
+ align-items: center;
+ display: flex;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
`;
-export const TextOutput = styled.text`
- fill: ${({theme}) => theme.color.white};
- font-size: ${({theme}) => theme.size.xs};
- font-weight: bold;
- pointer-events: none;
+export const HeaderTitle = styled(Typography.Title)`
+ && {
+ margin: 0;
+ }
`;
diff --git a/web/src/components/Visualization/components/Timeline/Timeline.tsx b/web/src/components/Visualization/components/Timeline/Timeline.tsx
index da80cd16cf..b3c72c9078 100644
--- a/web/src/components/Visualization/components/Timeline/Timeline.tsx
+++ b/web/src/components/Visualization/components/Timeline/Timeline.tsx
@@ -1,31 +1,36 @@
-import {ParentSize} from '@visx/responsive';
import {NodeTypesEnum} from 'constants/Visualization.constants';
import Span from 'models/Span.model';
-import * as S from './Timeline.styled';
-import Visualization from './Visualization';
-import Navigation from '../Navigation';
+import {useRef} from 'react';
+import {FixedSizeList as List} from 'react-window';
+import NavigationWrapper from './NavigationWrapper';
+import TimelineProvider from './Timeline.provider';
+import ListWrapper from './ListWrapper';
export interface IProps {
- isMatchedMode: boolean;
- matchedSpans: string[];
nodeType: NodeTypesEnum;
- onNavigateToSpan(spanId: string): void;
- onNodeClick(spanId: string): void;
- selectedSpan: string;
spans: Span[];
- width?: number;
+ onNavigate(spanId: string): void;
+ onClick(spanId: string): void;
+ matchedSpans: string[];
+ selectedSpan: string;
}
-const Timeline = (props: IProps) => {
- const {isMatchedMode, matchedSpans, onNavigateToSpan, selectedSpan} = props;
+const Timeline = ({nodeType, spans, onClick, onNavigate, matchedSpans, selectedSpan}: IProps) => {
+ const listRef = useRef(null);
return (
-
-
-
- {({width}) => }
-
-
+
+
+
+
);
};
diff --git a/web/src/components/Visualization/components/Timeline/TimelineV2.styled.ts b/web/src/components/Visualization/components/Timeline/TimelineV2.styled.ts
deleted file mode 100644
index 827d7b88a3..0000000000
--- a/web/src/components/Visualization/components/Timeline/TimelineV2.styled.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-import {Typography} from 'antd';
-import {SemanticGroupNames, SemanticGroupNamesToColor} from 'constants/SemanticGroupNames.constants';
-import styled, {css} from 'styled-components';
-
-export const Container = styled.div`
- padding: 50px 24px 0 24px;
-`;
-
-export const Row = styled.div<{$isEven: boolean; $isMatched: boolean; $isSelected: boolean}>`
- background-color: ${({theme, $isEven}) => ($isEven ? theme.color.background : theme.color.white)};
- display: grid;
- grid-template-columns: 300px 1fr;
- grid-template-rows: 32px;
- padding: 0px 16px;
-
- :hover {
- background-color: ${({theme}) => theme.color.backgroundInteractive};
- }
-
- ${({$isMatched}) =>
- $isMatched &&
- css`
- background-color: ${({theme}) => theme.color.alertYellow};
- `};
-
- ${({$isSelected}) =>
- $isSelected &&
- css`
- background: rgba(97, 23, 94, 0.1);
-
- :hover {
- background: rgba(97, 23, 94, 0.1);
- }
- `};
-`;
-
-export const Col = styled.div`
- display: grid;
- grid-template-columns: 1fr 8px;
-`;
-
-export const ColDuration = styled.div`
- overflow: hidden;
- position: relative;
-`;
-
-export const Header = styled.div`
- align-items: center;
- display: flex;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-`;
-
-export const NameContainer = styled.div`
- overflow: hidden;
- text-overflow: ellipsis;
-`;
-
-export const Separator = styled.div`
- border-left: 1px solid rgb(222, 227, 236);
- cursor: ew-resize;
- height: 32px;
- padding: 0px 3px;
- width: 1px;
-`;
-
-export const Title = styled(Typography.Text)`
- color: ${({theme}) => theme.color.text};
- font-size: ${({theme}) => theme.size.sm};
- font-weight: 400;
-`;
-
-export const Connector = styled.svg`
- flex-shrink: 0;
- overflow: hidden;
- overflow-clip-margin: content-box;
-`;
-
-export const SpanBar = styled.div<{$type: SemanticGroupNames}>`
- background-color: ${({$type}) => SemanticGroupNamesToColor[$type]};
- border-radius: 3px;
- height: 18px;
- min-width: 2px;
- position: absolute;
- top: 7px;
-`;
-
-export const SpanBarLabel = styled.div<{$side: 'left' | 'right'}>`
- color: ${({theme}) => theme.color.textSecondary};
- font-size: ${({theme}) => theme.size.xs};
- padding: 1px 4px 0 4px;
- position: absolute;
-
- ${({$side}) =>
- $side === 'left'
- ? css`
- right: 100%;
- `
- : css`
- left: 100%;
- `};
-`;
-
-export const TextConnector = styled.text<{$isActive?: boolean}>`
- fill: ${({theme, $isActive}) => ($isActive ? theme.color.white : theme.color.text)};
- font-size: ${({theme}) => theme.size.xs};
-`;
-
-export const CircleDot = styled.circle`
- fill: ${({theme}) => theme.color.textSecondary};
- stroke-width: 2;
- stroke: ${({theme}) => theme.color.white};
-`;
-
-export const LineBase = styled.line`
- stroke: ${({theme}) => theme.color.borderLight};
-`;
-
-export const RectBase = styled.rect<{$isActive?: boolean}>`
- fill: ${({theme, $isActive}) => ($isActive ? theme.color.primary : theme.color.white)};
- stroke: ${({theme}) => theme.color.textSecondary};
-`;
-
-export const RectBaseTransparent = styled(RectBase)`
- cursor: pointer;
- fill: transparent;
-`;
-
-export const HeaderRow = styled.div`
- background-color: ${({theme}) => theme.color.white};
- display: grid;
- grid-template-columns: 300px 1fr;
- grid-template-rows: 32px;
- padding: 0px 16px;
-`;
-
-export const HeaderContent = styled.div`
- align-items: center;
- display: flex;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-`;
-
-export const HeaderTitle = styled(Typography.Title)`
- && {
- margin: 0;
- }
-`;
diff --git a/web/src/components/Visualization/components/Timeline/TimelineV2.tsx b/web/src/components/Visualization/components/Timeline/TimelineV2.tsx
deleted file mode 100644
index b3c72c9078..0000000000
--- a/web/src/components/Visualization/components/Timeline/TimelineV2.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import {NodeTypesEnum} from 'constants/Visualization.constants';
-import Span from 'models/Span.model';
-import {useRef} from 'react';
-import {FixedSizeList as List} from 'react-window';
-import NavigationWrapper from './NavigationWrapper';
-import TimelineProvider from './Timeline.provider';
-import ListWrapper from './ListWrapper';
-
-export interface IProps {
- nodeType: NodeTypesEnum;
- spans: Span[];
- onNavigate(spanId: string): void;
- onClick(spanId: string): void;
- matchedSpans: string[];
- selectedSpan: string;
-}
-
-const Timeline = ({nodeType, spans, onClick, onNavigate, matchedSpans, selectedSpan}: IProps) => {
- const listRef = useRef(null);
-
- return (
-
-
-
-
- );
-};
-
-export default Timeline;
diff --git a/web/src/components/Visualization/components/Timeline/TraceSpanNode/Header.tsx b/web/src/components/Visualization/components/Timeline/TraceSpanNode/Header.tsx
deleted file mode 100644
index 39ab0384d5..0000000000
--- a/web/src/components/Visualization/components/Timeline/TraceSpanNode/Header.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import errorIcon from 'assets/error.svg';
-import * as S from '../Timeline.styled';
-
-interface IProps {
- hasAnalyzerErrors: boolean;
-}
-
-const Header = ({hasAnalyzerErrors}: IProps) => {
- if (!hasAnalyzerErrors) return null;
-
- return (
- <>
-
-
- Analyzer errors
-
- >
- );
-};
-
-export default Header;
diff --git a/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNode.tsx b/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNode.tsx
index 2ac57bf17d..e8bde17f1f 100644
--- a/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNode.tsx
+++ b/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNode.tsx
@@ -1,20 +1,12 @@
import useSpanData from 'hooks/useSpanData';
-import Header from './Header';
import BaseSpanNode from '../BaseSpanNode/BaseSpanNode';
import {IPropsComponent} from '../SpanNodeFactory';
const TraceSpanNode = (props: IPropsComponent) => {
- const {isMatched, node} = props;
- const {span, analyzerErrors} = useSpanData(node.data.id);
+ const {node} = props;
+ const {span} = useSpanData(node.data.id);
- return (
- }
- span={span}
- />
- );
+ return ;
};
export default TraceSpanNode;
diff --git a/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNodeV2.tsx b/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNodeV2.tsx
deleted file mode 100644
index 539eda5ae2..0000000000
--- a/web/src/components/Visualization/components/Timeline/TraceSpanNode/TraceSpanNodeV2.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import useSpanData from 'hooks/useSpanData';
-// import Header from './Header';
-import BaseSpanNode from '../BaseSpanNode/BaseSpanNodeV2';
-import {IPropsComponent} from '../SpanNodeFactoryV2';
-
-const TraceSpanNode = (props: IPropsComponent) => {
- const {node} = props;
- const {span} = useSpanData(node.data.id);
-
- return (
- }
- span={span}
- />
- );
-};
-
-export default TraceSpanNode;
diff --git a/web/src/components/Visualization/components/Timeline/Visualization.tsx b/web/src/components/Visualization/components/Timeline/Visualization.tsx
deleted file mode 100644
index ef54e513ba..0000000000
--- a/web/src/components/Visualization/components/Timeline/Visualization.tsx
+++ /dev/null
@@ -1,87 +0,0 @@
-import {Axis, Orientation} from '@visx/axis';
-import {Group} from '@visx/group';
-import {scaleLinear} from '@visx/scale';
-import without from 'lodash/without';
-import {useCallback, useMemo, useState} from 'react';
-import {useTheme} from 'styled-components';
-
-import {AxisHeight, AxisOffset, NodeHeight} from 'constants/Timeline.constants';
-import TimelineModel from 'models/Timeline.model';
-import TimelineService from 'services/Timeline.service';
-import SpanNodeFactory from './SpanNodeFactory';
-import {IProps} from './Timeline';
-
-function tickLabelProps() {
- return {
- fill: '#687492',
- fontSize: 12,
- textAnchor: 'middle',
- } as const;
-}
-
-const Visualization = ({matchedSpans, nodeType, onNodeClick, selectedSpan, spans, width = 600}: IProps) => {
- const theme = useTheme();
- const [collapsed, setCollapsed] = useState([]);
-
- const nodes = useMemo(() => TimelineModel(spans, nodeType), [spans, nodeType]);
- const filteredNodes = useMemo(() => TimelineService.getFilteredNodes(nodes, collapsed), [collapsed, nodes]);
- const [min, max] = useMemo(() => TimelineService.getMinMax(nodes), [nodes]);
-
- const xScale = scaleLinear({
- domain: [0, max - min],
- range: [0, width - AxisOffset],
- });
-
- const handleOnCollapse = useCallback((id: string) => {
- setCollapsed(prevCollapsed => {
- if (prevCollapsed.includes(id)) {
- return without(prevCollapsed, id);
- }
- return [...prevCollapsed, id];
- });
- }, []);
-
- return width < AxisOffset ? null : (
-
- );
-};
-
-export default Visualization;