Skip to content

Commit 6e2af0a

Browse files
committed
Add Timestamp column to ViewEventList and fix formatting
1 parent 8a70117 commit 6e2af0a

File tree

1 file changed

+91
-64
lines changed

1 file changed

+91
-64
lines changed

src/components/view/view-event-list.tsx

Lines changed: 91 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import AutoSizer from 'react-virtualized-auto-sizer';
77
import { FixedSizeList as List, ListChildComponentProps } from 'react-window';
88

99
import { styled } from '../../styles'
10+
import { css } from "styled-components";
1011
import { ArrowIcon, Icon, PhosphorIcon, WarningIcon } from '../../icons';
1112

1213
import {
@@ -86,14 +87,18 @@ const ListContainer = styled.div<{ role: 'table' }>`
8687
}
8788
`;
8889

89-
const Column = styled.div<{ role: 'cell' | 'columnheader' }>`
90+
const columnStyles = css`
9091
display: block;
9192
overflow: hidden;
9293
text-overflow: ellipsis;
9394
white-space: nowrap;
9495
padding: 3px 0;
9596
`;
9697

98+
const Column = styled.div<{ role: 'cell' | 'columnheader' }>`
99+
${columnStyles}
100+
`;
101+
97102
const RowPin = styled(
98103
filterProps(Icon, 'pinned')
99104
).attrs((p: { pinned: boolean }) => ({
@@ -147,6 +152,26 @@ const MarkerHeader = styled.div<{ role: 'columnheader' }>`
147152
flex-shrink: 0;
148153
`;
149154

155+
const BaseTimestamp = ({ timestamp, role = 'cell', className, children }: {
156+
timestamp?: number,
157+
role?: 'columnheader' | 'cell',
158+
className?: string,
159+
children?: React.ReactNode
160+
}) => {
161+
return (
162+
<div role={role} className={className}>
163+
{timestamp != null ? (new Date(timestamp).toLocaleTimeString()) : (children ?? '-')}
164+
</div>
165+
);
166+
};
167+
168+
const Timestamp = styled(BaseTimestamp)`
169+
${columnStyles};
170+
transition: flex-basis 0.1s;
171+
flex-shrink: 0;
172+
flex-grow: 0;
173+
`;
174+
150175
const Method = styled(Column)`
151176
transition: flex-basis 0.1s;
152177
${(p: { pinned?: boolean }) =>
@@ -434,30 +459,31 @@ const ExchangeRow = inject('uiStore')(observer(({
434459
className={isSelected ? 'selected' : ''}
435460
style={style}
436461
>
437-
<RowPin aria-label={pinned ? 'Pinned' : undefined} pinned={pinned}/>
462+
<RowPin aria-label={pinned ? 'Pinned' : undefined} pinned={pinned} />
438463
<RowMarker role='cell' category={category} title={describeEventCategory(category)} />
439-
<Method role='cell' pinned={pinned}>{ request.method }</Method>
464+
<Timestamp role='cell' timestamp={request.timingEvents.startTime} />
465+
<Method role='cell' pinned={pinned}>{request.method}</Method>
440466
<Status role='cell'>
441467
{
442468
response === 'aborted'
443469
? <StatusCode status={'aborted'} />
444-
: exchange.downstream.isBreakpointed
445-
? <WarningIcon title='Breakpointed, waiting to be resumed' />
446-
: exchange.isWebSocket() && response?.statusCode === 101
447-
? <StatusCode // Special UI for accepted WebSockets
448-
status={exchange.closeState
449-
? 'WS:closed'
450-
: 'WS:open'
451-
}
452-
message={`${exchange.closeState
453-
? 'A closed'
454-
: 'An open'
455-
} WebSocket connection`}
456-
/>
457-
: <StatusCode
458-
status={response?.statusCode}
459-
message={response?.statusMessage}
460-
/>
470+
: exchange.downstream.isBreakpointed
471+
? <WarningIcon title='Breakpointed, waiting to be resumed' />
472+
: exchange.isWebSocket() && response?.statusCode === 101
473+
? <StatusCode // Special UI for accepted WebSockets
474+
status={exchange.closeState
475+
? 'WS:closed'
476+
: 'WS:open'
477+
}
478+
message={`${exchange.closeState
479+
? 'A closed'
480+
: 'An open'
481+
} WebSocket connection`}
482+
/>
483+
: <StatusCode
484+
status={response?.statusCode}
485+
message={response?.statusMessage}
486+
/>
461487
}
462488
</Status>
463489
<Source role='cell'>
@@ -473,21 +499,21 @@ const ExchangeRow = inject('uiStore')(observer(({
473499
) &&
474500
<PhosphorIcon
475501
icon='Pencil'
476-
alt={`Handled by ${
477-
exchange.matchedRule.stepTypes.length === 1
478-
? nameStepClass(exchange.matchedRule.stepTypes[0])
479-
: 'multi-step'
480-
} rule`}
502+
alt={`Handled by
503+
${exchange.matchedRule.stepTypes.length === 1 ?
504+
nameStepClass(exchange.matchedRule.stepTypes[0])
505+
: 'multi-step'
506+
} rule`}
481507
size='20px'
482508
color={getSummaryColor('mutative')}
483509
/>
484510
}
485511
</Source>
486-
<Host role='cell' title={ request.parsedUrl.host }>
487-
{ request.parsedUrl.host }
512+
<Host role='cell' title={request.parsedUrl.host}>
513+
{request.parsedUrl.host}
488514
</Host>
489-
<PathAndQuery role='cell' title={ request.parsedUrl.pathname + request.parsedUrl.search }>
490-
{ request.parsedUrl.pathname + request.parsedUrl.search }
515+
<PathAndQuery role='cell' title={request.parsedUrl.pathname + request.parsedUrl.search}>
516+
{request.parsedUrl.pathname + request.parsedUrl.search}
491517
</PathAndQuery>
492518
</TrafficEventListRow>;
493519
}));
@@ -801,6 +827,7 @@ export class ViewEventList extends React.Component<ViewEventListProps> {
801827
return <ListContainer role="table">
802828
<TableHeaderRow role="row">
803829
<MarkerHeader role="columnheader" aria-label="Category" />
830+
<Timestamp role="columnheader">Timestamp</Timestamp>}
804831
<Method role="columnheader">Method</Method>
805832
<Status role="columnheader">Status</Status>
806833
<Source role="columnheader">Source</Source>
@@ -810,41 +837,41 @@ export class ViewEventList extends React.Component<ViewEventListProps> {
810837

811838
{
812839
events.length === 0
813-
? (isPaused
814-
? <EmptyStateOverlay icon='Pause'>
815-
Interception is paused, resume it to collect intercepted requests
816-
</EmptyStateOverlay>
817-
: <EmptyStateOverlay icon='Plug'>
818-
Connect a client and intercept some requests, and they'll appear here
819-
</EmptyStateOverlay>
820-
)
821-
822-
: filteredEvents.length === 0
823-
? <EmptyStateOverlay icon='QuestionMark'>
824-
No requests match this search filter{
825-
isPaused ? ' and interception is paused' : ''
826-
}
827-
</EmptyStateOverlay>
828-
829-
: <AutoSizer>{({ height, width }) =>
830-
<Observer>{() =>
831-
<List
832-
innerRef={this.setListBodyRef}
833-
outerElementType={this.KeyBoundListWindow}
834-
ref={this.listRef}
835-
836-
height={height - HEADER_FOOTER_HEIGHT}
837-
width={width}
838-
itemCount={filteredEvents.length}
839-
itemSize={32}
840-
itemData={this.listItemData}
841-
842-
onScroll={this.updateScrolledState}
843-
>
844-
{ EventRow }
845-
</List>
846-
}</Observer>
847-
}</AutoSizer>
840+
? (isPaused
841+
? <EmptyStateOverlay icon='Pause'>
842+
Interception is paused, resume it to collect intercepted requests
843+
</EmptyStateOverlay>
844+
: <EmptyStateOverlay icon='Plug'>
845+
Connect a client and intercept some requests, and they'll appear here
846+
</EmptyStateOverlay>
847+
)
848+
849+
: filteredEvents.length === 0
850+
? <EmptyStateOverlay icon='QuestionMark'>
851+
No requests match this search filter{
852+
isPaused ? ' and interception is paused' : ''
853+
}
854+
</EmptyStateOverlay>
855+
856+
: <AutoSizer>{({ height, width }) =>
857+
<Observer>{() =>
858+
<List
859+
innerRef={this.setListBodyRef}
860+
outerElementType={this.KeyBoundListWindow}
861+
ref={this.listRef}
862+
863+
height={height - HEADER_FOOTER_HEIGHT}
864+
width={width}
865+
itemCount={filteredEvents.length}
866+
itemSize={32}
867+
itemData={this.listItemData}
868+
869+
onScroll={this.updateScrolledState}
870+
>
871+
{EventRow}
872+
</List>
873+
}</Observer>
874+
}</AutoSizer>
848875
}
849876
</ListContainer>;
850877
}

0 commit comments

Comments
 (0)