mirror of
https://github.com/DeNNiiInc/Web-Page-Performance-Test.git
synced 2026-04-17 20:05:58 +00:00
Waterfall Phase 1.1 - Add request numbering, status colors, inline metrics
This commit is contained in:
@@ -21,31 +21,84 @@
|
|||||||
background: var(--color-bg-tertiary);
|
background: var(--color-bg-tertiary);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waterfall-timescale {
|
||||||
|
height: 25px;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 370px;
|
||||||
|
border-bottom: 2px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-marker {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.waterfall-row {
|
.waterfall-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 25px;
|
height: 28px;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 1px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.2s ease;
|
transition: background 0.2s ease;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.waterfall-row:hover {
|
.waterfall-row:hover {
|
||||||
background: rgba(114, 9, 183, 0.2);
|
background: rgba(114, 9, 183, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.request-number {
|
||||||
|
width: 35px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge {
|
||||||
|
width: 40px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.request-label {
|
.request-label {
|
||||||
width: 300px;
|
width: 250px;
|
||||||
padding: 0 10px;
|
padding: 0 8px;
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
color: var(--color-text-primary);
|
color: var(--color-text-primary);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.request-size {
|
||||||
|
width: 65px;
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-time {
|
||||||
|
width: 60px;
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.timeline {
|
.timeline {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
25
waterfall.js
25
waterfall.js
@@ -50,14 +50,29 @@ function renderWaterfall() {
|
|||||||
|
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
|
// Add time scale header
|
||||||
|
html += '<div class="waterfall-timescale">';
|
||||||
|
for (let sec = 0; sec <= Math.ceil(maxTime); sec++) {
|
||||||
|
const pos = sec * scale;
|
||||||
|
html += `<div class="time-marker" style="left: ${300 + pos}px">${sec}s</div>`;
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
filteredEntries.forEach((entry, index) => {
|
filteredEntries.forEach((entry, index) => {
|
||||||
const label = truncateUrl(entry.url, 50);
|
const label = truncateUrl(entry.url, 35);
|
||||||
const timingBars = renderTimingBars(entry.timing, scale);
|
const timingBars = renderTimingBars(entry.timing, scale);
|
||||||
|
const statusColor = getStatusColor(entry.status);
|
||||||
|
const sizeKB = (entry.size.transferSize / 1024).toFixed(1);
|
||||||
|
const timeMS = entry.timing.total.toFixed(0);
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="waterfall-row" data-request-id="${entry.requestId}">
|
<div class="waterfall-row" data-request-id="${entry.requestId}">
|
||||||
|
<div class="request-number">${entry.requestId}</div>
|
||||||
|
<div class="status-badge" style="background: ${statusColor}">${entry.status}</div>
|
||||||
<div class="request-label" title="${entry.url}">${label}</div>
|
<div class="request-label" title="${entry.url}">${label}</div>
|
||||||
<div class="timeline">${timingBars}</div>
|
<div class="timeline">${timingBars}</div>
|
||||||
|
<div class="request-size">${sizeKB} KB</div>
|
||||||
|
<div class="request-time">${timeMS} ms</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
@@ -73,6 +88,14 @@ function renderWaterfall() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getStatusColor(status) {
|
||||||
|
if (status >= 200 && status < 300) return '#4CAF50'; // Green
|
||||||
|
if (status >= 300 && status < 400) return '#FF9800'; // Orange
|
||||||
|
if (status >= 400 && status < 500) return '#F44336'; // Red
|
||||||
|
if (status >= 500) return '#B71C1C'; // Dark Red
|
||||||
|
return '#9E9E9E'; // Grey for others
|
||||||
|
}
|
||||||
|
|
||||||
function renderTimingBars(timing, scale) {
|
function renderTimingBars(timing, scale) {
|
||||||
let html = '';
|
let html = '';
|
||||||
let currentOffset = timing.startTime * scale;
|
let currentOffset = timing.startTime * scale;
|
||||||
|
|||||||
Reference in New Issue
Block a user