Skip to content

Commit

Permalink
refactor: js into more modules
Browse files Browse the repository at this point in the history
  • Loading branch information
provos committed Dec 15, 2024
1 parent dc8ff8d commit 9e9640c
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 161 deletions.
4 changes: 4 additions & 0 deletions src/planai/static/js/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { setupEventSource } from './core.js';
import { initTaskListeners } from './tasks.js';
import { initTraceListeners } from './trace.js';
import { initWorkerStatsListeners } from './workers.js';
import { initTheme } from './theme.js';

setupEventSource();
initTaskListeners();
initTraceListeners();
initWorkerStatsListeners();
initTheme();

// Quit button functionality
Expand Down
161 changes: 0 additions & 161 deletions src/planai/static/js/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { formatTime, renderObject } from './utils.js';

export function initTaskListeners() {
window.addEventListener('tasksUpdated', (e) => updateTaskLists(e.detail));
window.addEventListener('traceUpdated', (e) => updateTraceVisualization(e.detail));
window.addEventListener('statsUpdated', (e) => updateWorkerStats(e.detail));
window.addEventListener('userRequestsUpdated', (e) => updateUserRequests(e.detail));
}

Expand Down Expand Up @@ -109,165 +107,6 @@ function toggleProvenance(taskId) {
}


function updateTraceVisualization(traceData) {
const traceElement = document.getElementById('trace-visualization');
const expandedPrefixes = new Set();

// Store currently expanded prefixes
traceElement.querySelectorAll('.trace-prefix.expanded').forEach(el => {
expandedPrefixes.add(el.querySelector('h4').textContent.trim());
});

traceElement.innerHTML = '';

for (const [prefixStr, entries] of Object.entries(traceData)) {
const prefixElement = document.createElement('div');
prefixElement.className = 'trace-prefix';

const prefix = prefixStr.split('_').join(', ');

const headerElement = document.createElement('h4');
headerElement.textContent = `Prefix: (${prefix})`;
headerElement.onclick = function () {
this.parentElement.classList.toggle('expanded');
};

prefixElement.appendChild(headerElement);

const tableWrapper = document.createElement('div');
tableWrapper.className = 'table-wrapper';

const table = document.createElement('table');
table.className = 'trace-table';

// Create table header
const headerRow = table.insertRow();
['Worker', 'Action', 'Task', 'Count', 'Status'].forEach(header => {
const th = document.createElement('th');
th.textContent = header;
headerRow.appendChild(th);
});

// Populate table with entry data
entries.forEach(entry => {
const row = table.insertRow();
row.className = entry.action;
if (entry.count === 0) row.classList.add('zero-count');
if (entry.status.includes('Notifying:')) row.classList.add('notification-row');

['worker', 'action', 'task', 'count'].forEach(key => {
const cell = row.insertCell();
cell.textContent = entry[key];
});

// Handle status separately to allow for wrapping
const statusCell = row.insertCell();
statusCell.className = 'status-cell';
statusCell.textContent = entry.status;
});

tableWrapper.appendChild(table);
prefixElement.appendChild(tableWrapper);
traceElement.appendChild(prefixElement);

// Restore expanded state if it was previously expanded
if (expandedPrefixes.has(headerElement.textContent.trim())) {
prefixElement.classList.add('expanded');
}
}
}

// Execution statistics chart
let workerChart;

function updateWorkerStats(workerStats) {
const workerStatsElement = document.getElementById('worker-stats');

if (!workerChart) {
// Create the chart if it doesn't exist
const canvas = document.createElement('canvas');
canvas.id = 'workerStatsChart';
workerStatsElement.appendChild(canvas);
const ctx = canvas.getContext('2d');

workerChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [
{
label: 'Min',
data: [],
backgroundColor: 'rgba(75, 192, 192, 0.6)',
},
{
label: 'Median',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.6)',
},
{
label: 'Max',
data: [],
backgroundColor: 'rgba(255, 99, 132, 0.6)',
},
{
label: 'Std Dev',
data: [],
backgroundColor: 'rgba(255, 206, 86, 0.6)',
}
]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Execution Time (seconds)'
}
}
},
plugins: {
title: {
display: true,
text: 'Worker Execution Statistics'
},
tooltip: {
callbacks: {
label: function (context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += context.parsed.y.toFixed(2) + ' seconds';
}
return label;
}
}
}
}
}
});
}

// Update chart data
const labels = Object.keys(workerStats);
const minData = labels.map(worker => workerStats[worker].min);
const medianData = labels.map(worker => workerStats[worker].median);
const maxData = labels.map(worker => workerStats[worker].max);
const stdDevData = labels.map(worker => workerStats[worker].stdDev);

workerChart.data.labels = labels;
workerChart.data.datasets[0].data = minData;
workerChart.data.datasets[1].data = medianData;
workerChart.data.datasets[2].data = maxData;
workerChart.data.datasets[3].data = stdDevData;

workerChart.update();
}

// User input requests
function updateUserRequests(userRequests) {
const requestsContainer = document.getElementById('user-input-requests');
Expand Down
71 changes: 71 additions & 0 deletions src/planai/static/js/trace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
export function initTraceListeners() {
window.addEventListener('traceUpdated', (e) => updateTraceVisualization(e.detail));
}

function updateTraceVisualization(traceData) {
const traceElement = document.getElementById('trace-visualization');
const expandedPrefixes = new Set();

// Store currently expanded prefixes
traceElement.querySelectorAll('.trace-prefix.expanded').forEach(el => {
expandedPrefixes.add(el.querySelector('h4').textContent.trim());
});

traceElement.innerHTML = '';

for (const [prefixStr, entries] of Object.entries(traceData)) {
const prefixElement = document.createElement('div');
prefixElement.className = 'trace-prefix';

const prefix = prefixStr.split('_').join(', ');

const headerElement = document.createElement('h4');
headerElement.textContent = `Prefix: (${prefix})`;
headerElement.onclick = function () {
this.parentElement.classList.toggle('expanded');
};

prefixElement.appendChild(headerElement);

const tableWrapper = document.createElement('div');
tableWrapper.className = 'table-wrapper';

const table = document.createElement('table');
table.className = 'trace-table';

// Create table header
const headerRow = table.insertRow();
['Worker', 'Action', 'Task', 'Count', 'Status'].forEach(header => {
const th = document.createElement('th');
th.textContent = header;
headerRow.appendChild(th);
});

// Populate table with entry data
entries.forEach(entry => {
const row = table.insertRow();
row.className = entry.action;
if (entry.count === 0) row.classList.add('zero-count');
if (entry.status.includes('Notifying:')) row.classList.add('notification-row');

['worker', 'action', 'task', 'count'].forEach(key => {
const cell = row.insertCell();
cell.textContent = entry[key];
});

// Handle status separately to allow for wrapping
const statusCell = row.insertCell();
statusCell.className = 'status-cell';
statusCell.textContent = entry.status;
});

tableWrapper.appendChild(table);
prefixElement.appendChild(tableWrapper);
traceElement.appendChild(prefixElement);

// Restore expanded state if it was previously expanded
if (expandedPrefixes.has(headerElement.textContent.trim())) {
prefixElement.classList.add('expanded');
}
}
}
95 changes: 95 additions & 0 deletions src/planai/static/js/workers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Execution statistics chart

export function initWorkerStatsListeners() {
window.addEventListener('statsUpdated', (e) => updateWorkerStats(e.detail));
}

let workerChart;

export function updateWorkerStats(workerStats) {
const workerStatsElement = document.getElementById('worker-stats');

if (!workerChart) {
// Create the chart if it doesn't exist
const canvas = document.createElement('canvas');
canvas.id = 'workerStatsChart';
workerStatsElement.appendChild(canvas);
const ctx = canvas.getContext('2d');

workerChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [
{
label: 'Min',
data: [],
backgroundColor: 'rgba(75, 192, 192, 0.6)',
},
{
label: 'Median',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.6)',
},
{
label: 'Max',
data: [],
backgroundColor: 'rgba(255, 99, 132, 0.6)',
},
{
label: 'Std Dev',
data: [],
backgroundColor: 'rgba(255, 206, 86, 0.6)',
}
]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Execution Time (seconds)'
}
}
},
plugins: {
title: {
display: true,
text: 'Worker Execution Statistics'
},
tooltip: {
callbacks: {
label: function (context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += context.parsed.y.toFixed(2) + ' seconds';
}
return label;
}
}
}
}
}
});
}

// Update chart data
const labels = Object.keys(workerStats);
const minData = labels.map(worker => workerStats[worker].min);
const medianData = labels.map(worker => workerStats[worker].median);
const maxData = labels.map(worker => workerStats[worker].max);
const stdDevData = labels.map(worker => workerStats[worker].stdDev);

workerChart.data.labels = labels;
workerChart.data.datasets[0].data = minData;
workerChart.data.datasets[1].data = medianData;
workerChart.data.datasets[2].data = maxData;
workerChart.data.datasets[3].data = stdDevData;

workerChart.update();
}

0 comments on commit 9e9640c

Please sign in to comment.