-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(frontend): implement virtual list for timeline view (#3617)
* feat(frontend): implement virtual list for timeline view * remove prop * add header and collapse
- Loading branch information
Showing
18 changed files
with
698 additions
and
22 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
web/src/components/Visualization/components/Timeline/BaseSpanNode/BaseSpanNodeV2.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
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'; | ||
|
||
const BaseLeftPadding = 16; // TODO: Move to Timeline.constants | ||
|
||
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 { | ||
header?: React.ReactNode; | ||
span: Span; | ||
} | ||
|
||
const BaseSpanNode = ({header, 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); | ||
const leftPadding = node.depth * BaseLeftPadding; | ||
|
||
return ( | ||
<div style={style}> | ||
<S.Row | ||
onClick={() => onSpanClick(node.data.id)} | ||
$isEven={index % 2 === 0} | ||
$isMatched={isMatched} | ||
$isSelected={isSelected} | ||
> | ||
<S.Col> | ||
<S.Header> | ||
<Connector | ||
hasParent={!!node.data.parentId} | ||
id={node.data.id} | ||
isCollapsed={isCollapsed} | ||
leftPadding={leftPadding} | ||
onCollapse={onSpanCollapse} | ||
totalChildren={node.children} | ||
/> | ||
<S.NameContainer> | ||
<S.Title>{span.name}</S.Title> | ||
</S.NameContainer> | ||
</S.Header> | ||
<S.Separator /> | ||
</S.Col> | ||
|
||
<S.ColDuration> | ||
<S.SpanBar $type={span.type} style={{left: toPercent(viewStart), width: toPercent(viewEnd - viewStart)}}> | ||
<S.SpanBarLabel $side={hintSide}>{span.duration}</S.SpanBarLabel> | ||
</S.SpanBar> | ||
</S.ColDuration> | ||
</S.Row> | ||
</div> | ||
); | ||
}; | ||
|
||
export default BaseSpanNode; |
47 changes: 47 additions & 0 deletions
47
web/src/components/Visualization/components/Timeline/BaseSpanNode/ConnectorV2.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import * as S from '../TimelineV2.styled'; | ||
|
||
interface IProps { | ||
hasParent: boolean; | ||
id: string; | ||
isCollapsed: boolean; | ||
leftPadding: number; | ||
onCollapse(id: string): void; | ||
totalChildren: number; | ||
} | ||
|
||
const Connector = ({hasParent, id, isCollapsed, leftPadding, onCollapse, totalChildren}: IProps) => ( | ||
<S.Connector height="100%" width={leftPadding + 30}> | ||
{hasParent && ( | ||
<> | ||
<S.LineBase x1={leftPadding - 3} x2={leftPadding + 12} y1="16" y2="16" /> | ||
<S.LineBase x1={leftPadding - 4} x2={leftPadding - 4} y1="0" y2="16.5" /> | ||
</> | ||
)} | ||
|
||
{totalChildren > 0 ? ( | ||
<> | ||
{!isCollapsed && <S.LineBase x1={leftPadding + 12} x2={leftPadding + 12} y1="16" y2="32" />} | ||
<S.RectBase x={leftPadding + 2} y="8" width="20" height="16" rx="3px" ry="3px" $isActive={isCollapsed} /> | ||
<S.TextConnector x={leftPadding + 12} y="20" textAnchor="middle" $isActive={isCollapsed}> | ||
{totalChildren} | ||
</S.TextConnector> | ||
<S.RectBaseTransparent | ||
x={leftPadding + 2} | ||
y="8" | ||
width="20" | ||
height="16" | ||
rx="3px" | ||
ry="3px" | ||
onClick={event => { | ||
event.stopPropagation(); | ||
onCollapse(id); | ||
}} | ||
/> | ||
</> | ||
) : ( | ||
<S.CircleDot cx={leftPadding + 12} cy="16" r="3" /> | ||
)} | ||
</S.Connector> | ||
); | ||
|
||
export default Connector; |
22 changes: 22 additions & 0 deletions
22
web/src/components/Visualization/components/Timeline/Header.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import Ticks from './Ticks/Ticks'; | ||
import * as S from './TimelineV2.styled'; | ||
|
||
const NUM_TICKS = 5; | ||
|
||
interface IProps { | ||
duration: number; | ||
} | ||
|
||
const Header = ({duration}: IProps) => ( | ||
<S.HeaderRow> | ||
<S.Col> | ||
<S.HeaderContent> | ||
<S.HeaderTitle level={3}>Span</S.HeaderTitle> | ||
</S.HeaderContent> | ||
<S.Separator /> | ||
</S.Col> | ||
<Ticks numTicks={NUM_TICKS} startTime={0} endTime={duration} /> | ||
</S.HeaderRow> | ||
); | ||
|
||
export default Header; |
33 changes: 33 additions & 0 deletions
33
web/src/components/Visualization/components/Timeline/ListWrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import {FixedSizeList as List} from 'react-window'; | ||
import Header from './Header'; | ||
import SpanNodeFactory from './SpanNodeFactoryV2'; | ||
import * as S from './TimelineV2.styled'; | ||
import {useTimeline} from './Timeline.provider'; | ||
|
||
const HEADER_HEIGHT = 242; | ||
|
||
interface IProps { | ||
listRef: React.RefObject<List>; | ||
} | ||
|
||
const ListWrapper = ({listRef}: IProps) => { | ||
const {spans, viewEnd, viewStart} = useTimeline(); | ||
|
||
return ( | ||
<S.Container> | ||
<Header duration={viewEnd - viewStart} /> | ||
<List | ||
height={window.innerHeight - HEADER_HEIGHT} | ||
itemCount={spans.length} | ||
itemData={spans} | ||
itemSize={32} | ||
ref={listRef} | ||
width="100%" | ||
> | ||
{SpanNodeFactory} | ||
</List> | ||
</S.Container> | ||
); | ||
}; | ||
|
||
export default ListWrapper; |
10 changes: 10 additions & 0 deletions
10
web/src/components/Visualization/components/Timeline/NavigationWrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Navigation from '../Navigation'; | ||
import {useTimeline} from './Timeline.provider'; | ||
|
||
const NavigationWrapper = () => { | ||
const {matchedSpans, onSpanNavigation, selectedSpan} = useTimeline(); | ||
|
||
return <Navigation matchedSpans={matchedSpans} onNavigateToSpan={onSpanNavigation} selectedSpan={selectedSpan} />; | ||
}; | ||
|
||
export default NavigationWrapper; |
30 changes: 30 additions & 0 deletions
30
web/src/components/Visualization/components/Timeline/SpanNodeFactoryV2.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
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<NodeTypesEnum, (props: IPropsComponent) => 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 <Component {...props} node={node} />; | ||
}; | ||
|
||
export default SpanNodeFactory; |
37 changes: 37 additions & 0 deletions
37
web/src/components/Visualization/components/Timeline/Ticks/Ticks.styled.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import {Typography} from 'antd'; | ||
import styled, {css} from 'styled-components'; | ||
|
||
export const Ticks = styled.div` | ||
pointer-events: none; | ||
position: relative; | ||
`; | ||
|
||
export const Tick = styled.div` | ||
align-items: center; | ||
background: ${({theme}) => theme.color.borderLight}; | ||
display: flex; | ||
height: 100%; | ||
position: absolute; | ||
width: 1px; | ||
:first-child, | ||
:last-child { | ||
width: 0; | ||
} | ||
`; | ||
|
||
export const TickLabel = styled(Typography.Text)<{$isEndAnchor: boolean}>` | ||
color: ${({theme}) => theme.color.text}; | ||
font-size: ${({theme}) => theme.size.sm}; | ||
font-weight: 400; | ||
left: 0.25rem; | ||
position: absolute; | ||
white-space: nowrap; | ||
${({$isEndAnchor}) => | ||
$isEndAnchor && | ||
css` | ||
left: initial; | ||
right: 0.25rem; | ||
`}; | ||
`; |
Oops, something went wrong.