improve flow indication in table
This commit is contained in:
@@ -152,6 +152,8 @@ type PacketTableRow = PacketRow & {
|
||||
key: string;
|
||||
__kind: 'packet' | 'flow';
|
||||
flow_packet_count?: number;
|
||||
flow_packet_index?: number;
|
||||
flow_has_siblings?: boolean;
|
||||
children?: PacketTableRow[];
|
||||
};
|
||||
|
||||
@@ -1103,11 +1105,14 @@ export default function PacketViewer(): ReactElement {
|
||||
}
|
||||
|
||||
const latestPacket = [...flowPackets].sort(sortPacketsByTimestampDesc)[0];
|
||||
const children = sortedPackets.map((packet) => ({
|
||||
const children = sortedPackets.map((packet, index) => ({
|
||||
...packet,
|
||||
flow_id: flowId,
|
||||
key: packetKey(packet),
|
||||
__kind: 'packet' as const,
|
||||
flow_packet_count: sortedPackets.length,
|
||||
flow_packet_index: index + 1,
|
||||
flow_has_siblings: sortedPackets.length > 1,
|
||||
}));
|
||||
flowRows.push({
|
||||
...latestPacket,
|
||||
@@ -1127,21 +1132,45 @@ export default function PacketViewer(): ReactElement {
|
||||
{
|
||||
title: 'Group',
|
||||
key: 'group',
|
||||
width: 130,
|
||||
width: 180,
|
||||
render: (_: any, rec: PacketTableRow) =>
|
||||
rec.__kind === 'flow' ? (
|
||||
<Space direction="vertical" size={0}>
|
||||
<Tag color="blue" style={{ width: 'fit-content', marginInlineEnd: 0 }}>
|
||||
Flow
|
||||
</Tag>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{rec.flow_packet_count ?? 0} packets
|
||||
<div className="packet-group-cell packet-group-cell-flow">
|
||||
<div className="packet-group-title">
|
||||
<Tag color="blue" style={{ marginInlineEnd: 0 }}>
|
||||
Flow
|
||||
</Tag>
|
||||
<span className="packet-group-count">{rec.flow_packet_count ?? 0} packets</span>
|
||||
</div>
|
||||
<Text type="secondary" className="packet-group-subtitle">
|
||||
{rec.flow_id ?? 'Grouped flow'}
|
||||
</Text>
|
||||
</Space>
|
||||
</div>
|
||||
) : (
|
||||
<Text type="secondary" style={{ paddingLeft: 18 }}>
|
||||
Packet
|
||||
</Text>
|
||||
<div className={`packet-group-cell ${rec.flow_has_siblings ? 'packet-group-cell-child' : 'packet-group-cell-single'}`}>
|
||||
{rec.flow_has_siblings ? (
|
||||
<>
|
||||
<div className="packet-child-rail" aria-hidden="true" />
|
||||
<div className="packet-child-content">
|
||||
<Tag color="default" style={{ marginInlineEnd: 0 }}>
|
||||
Packet {rec.flow_packet_index ?? 1}/{rec.flow_packet_count ?? 1}
|
||||
</Tag>
|
||||
<Text type="secondary" className="packet-group-subtitle">
|
||||
In expanded flow
|
||||
</Text>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Tag color="default" style={{ marginInlineEnd: 0 }}>
|
||||
Single Packet
|
||||
</Tag>
|
||||
<Text type="secondary" className="packet-group-subtitle">
|
||||
Not grouped into a flow
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1332,16 +1361,21 @@ export default function PacketViewer(): ReactElement {
|
||||
{`
|
||||
.packet-viewer .ant-table-tbody > tr.packet-flow-row > td {
|
||||
background: #eef6ff;
|
||||
border-top: 1px solid #cfe2ff;
|
||||
border-bottom: 1px solid #cfe2ff;
|
||||
border-top: 1px solid #c8dbff;
|
||||
border-bottom: 1px solid #c8dbff;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), inset 0 -1px 0 rgba(165, 194, 255, 0.24);
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-tbody > tr.packet-child-row > td {
|
||||
background: #fafcff;
|
||||
background: #fbfdff;
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-tbody > tr.packet-child-row > td:first-child {
|
||||
border-left: 3px solid #d6e4ff;
|
||||
.packet-viewer .ant-table-tbody > tr.packet-standalone-row > td {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-tbody > tr.packet-child-row > td {
|
||||
border-top-color: #edf2fb;
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-row-expand-icon {
|
||||
@@ -1355,6 +1389,102 @@ export default function PacketViewer(): ReactElement {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-height: 40px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-cell-flow {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-count {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #1d4f91;
|
||||
background: rgba(214, 232, 255, 0.85);
|
||||
border: 1px solid rgba(148, 186, 242, 0.65);
|
||||
border-radius: 999px;
|
||||
padding: 1px 8px;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-subtitle {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-cell-child {
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-child-rail {
|
||||
width: 16px;
|
||||
flex: 0 0 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-child-rail::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: -12px;
|
||||
bottom: -12px;
|
||||
width: 2px;
|
||||
background: linear-gradient(180deg, #c7d9fb 0%, #dbe8ff 100%);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-child-rail::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 50%;
|
||||
width: 12px;
|
||||
height: 2px;
|
||||
transform: translateY(-50%);
|
||||
background: #c7d9fb;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-child-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-group-cell-single {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-tbody > tr.packet-flow-row:hover > td {
|
||||
background: #e7f1ff;
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-tbody > tr.packet-child-row:hover > td {
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.packet-viewer .ant-table-tbody > tr.packet-standalone-row:hover > td {
|
||||
background: #fafcff;
|
||||
}
|
||||
|
||||
.packet-viewer .packet-mode-toggle.ant-segmented {
|
||||
background: ${token.colorFillTertiary};
|
||||
}
|
||||
@@ -1464,7 +1594,13 @@ export default function PacketViewer(): ReactElement {
|
||||
<span style={{ display: 'inline-block', width: 24 }} />
|
||||
),
|
||||
}}
|
||||
rowClassName={(record: PacketTableRow) => (record.__kind === 'flow' ? 'packet-flow-row' : 'packet-child-row')}
|
||||
rowClassName={(record: PacketTableRow) =>
|
||||
record.__kind === 'flow'
|
||||
? 'packet-flow-row'
|
||||
: record.flow_has_siblings
|
||||
? 'packet-child-row'
|
||||
: 'packet-standalone-row'
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user