nvline / index.html
drbh's picture
drbh HF staff
Upload index.html
95dab94 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nvline</title>
<style>
body {
background-color: #121212;
color: #ffffff;
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
h1 {
margin-bottom: 10px;
font-size: 24px;
}
#chart-container {
width: 90%;
height: 80%;
}
#chart {
width: 100%;
height: 100%;
}
.axis-label {
fill: #ffffff;
}
.tooltip {
position: absolute;
background: rgba(0, 0, 0, 0.7);
color: #fff;
padding: 5px;
border-radius: 3px;
pointer-events: none;
font-size: 12px;
}
.grid line {
stroke: #444;
}
.grid path {
stroke: none;
}
input[type="file"] {
display: none;
}
.custom-file-upload {
border: 1px solid #ccc;
display: inline-block;
padding: 6px 12px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Import nvline JSONL File and Display Memory Usage</h1>
<label for="fileInput" class="custom-file-upload">
Add nvline JSONL File
</label>
<input type="file" id="fileInput" accept=".jsonl">
<div id="chart-container">
<svg id="chart"></svg>
</div>
<div id="tooltip" class="tooltip" style="display: none;"></div>
<script>
document.getElementById('fileInput').addEventListener('change', handleFile, false);
function handleFile(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function (event) {
const lines = event.target.result.split('\n').filter(line => line.trim() !== '');
const data = lines.map(line => JSON.parse(line));
drawChart(data);
};
reader.readAsText(file);
}
function drawChart(data) {
const svg = document.getElementById('chart');
svg.innerHTML = '';
const width = svg.clientWidth;
const height = svg.clientHeight;
const padding = 30;
const xScale = width / (data.length - 1);
const yMax = Math.max(...data.map(d => d.memory_total));
const yScale = (height - padding * 2) / yMax;
const line = (points) => points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p[0]},${p[1]}`).join(' ');
const memoryUsedPoints = data.map((d, i) => [i * xScale, height - padding - d.memory_used * yScale]);
const memoryFreePoints = data.map((d, i) => [i * xScale, height - padding - d.memory_free * yScale]);
const memoryTotalPoints = data.map((d, i) => [i * xScale, height - padding - d.memory_total * yScale]);
const gridX = document.createElementNS('http://www.w3.org/2000/svg', 'g');
const gridY = document.createElementNS('http://www.w3.org/2000/svg', 'g');
for (let i = 0; i < data.length; i++) {
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i * xScale);
line.setAttribute('y1', height - padding);
line.setAttribute('x2', i * xScale);
line.setAttribute('y2', padding);
line.setAttribute('class', 'grid');
line.setAttribute('stroke', '#444');
gridX.appendChild(line);
}
for (let i = 0; i <= yMax; i += yMax / 10) {
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', 0);
line.setAttribute('y1', height - padding - i * yScale);
line.setAttribute('x2', width);
line.setAttribute('y2', height - padding - i * yScale);
line.setAttribute('class', 'grid');
line.setAttribute('stroke', '#444');
gridY.appendChild(line);
}
svg.appendChild(gridX);
svg.appendChild(gridY);
const pathUsed = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathUsed.setAttribute('d', line(memoryUsedPoints));
pathUsed.setAttribute('stroke', 'red');
pathUsed.setAttribute('fill', 'none');
svg.appendChild(pathUsed);
const pathFree = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathFree.setAttribute('d', line(memoryFreePoints));
pathFree.setAttribute('stroke', 'green');
pathFree.setAttribute('fill', 'none');
svg.appendChild(pathFree);
const pathTotal = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathTotal.setAttribute('d', line(memoryTotalPoints));
pathTotal.setAttribute('stroke', 'blue');
pathTotal.setAttribute('fill', 'none');
svg.appendChild(pathTotal);
memoryUsedPoints.forEach((point, i) => {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', point[0]);
circle.setAttribute('cy', point[1]);
circle.setAttribute('r', 3);
circle.setAttribute('fill', 'red');
circle.setAttribute('class', 'dot dot-used');
circle.setAttribute('data-index', i);
svg.appendChild(circle);
});
memoryFreePoints.forEach((point, i) => {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', point[0]);
circle.setAttribute('cy', point[1]);
circle.setAttribute('r', 3);
circle.setAttribute('fill', 'green');
circle.setAttribute('class', 'dot dot-free');
circle.setAttribute('data-index', i);
svg.appendChild(circle);
});
memoryTotalPoints.forEach((point, i) => {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', point[0]);
circle.setAttribute('cy', point[1]);
circle.setAttribute('r', 3);
circle.setAttribute('fill', 'blue');
circle.setAttribute('class', 'dot dot-total');
circle.setAttribute('data-index', i);
svg.appendChild(circle);
});
const xAxisLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
xAxisLabel.setAttribute('x', width / 2);
xAxisLabel.setAttribute('y', height - 10);
xAxisLabel.setAttribute('class', 'axis-label');
xAxisLabel.setAttribute('text-anchor', 'middle');
xAxisLabel.textContent = 'Data Points';
svg.appendChild(xAxisLabel);
const yAxisLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
yAxisLabel.setAttribute('x', -height / 2);
yAxisLabel.setAttribute('y', 20);
yAxisLabel.setAttribute('class', 'axis-label');
yAxisLabel.setAttribute('text-anchor', 'middle');
yAxisLabel.setAttribute('transform', 'rotate(-90)');
yAxisLabel.textContent = 'Memory Usage';
svg.appendChild(yAxisLabel);
const tooltip = document.getElementById('tooltip');
svg.addEventListener('mousemove', (event) => {
const rect = svg.getBoundingClientRect();
const x = event.clientX - rect.left;
const index = Math.round(x / xScale);
document.querySelectorAll('.dot').forEach(dot => dot.style.display = 'none');
if (index >= 0 && index < data.length) {
const memoryUsed = data[index].memory_used;
const memoryFree = data[index].memory_free;
const memoryTotal = data[index].memory_total;
const timestamp = new Date(1000 * data[index].timestamp).toISOString();
tooltip.style.display = 'block';
tooltip.style.left = event.pageX + 10 + 'px';
tooltip.style.top = event.pageY - 10 + 'px';
tooltip.innerHTML = `Total: ${memoryTotal} Used: ${memoryUsed}<br>Free: ${memoryFree}<br> Timestamp: ${timestamp}`;
document.querySelector(`.dot-used[data-index='${index}']`).style.display = 'block';
document.querySelector(`.dot-free[data-index='${index}']`).style.display = 'block';
document.querySelector(`.dot-total[data-index='${index}']`).style.display = 'block';
} else {
tooltip.style.display = 'none';
}
});
svg.addEventListener('mouseout', () => {
tooltip.style.display = 'none';
document.querySelectorAll('.dot').forEach(dot => dot.style.display = 'none');
});
}
</script>
</body>
</html>