cleanup add training bell

This commit is contained in:
2025-12-08 12:26:34 +01:00
parent 036f3b178a
commit ccfb40a2b3
3070 changed files with 671040 additions and 68602 deletions

124
project-details.html Normal file → Executable file
View File

@@ -32,6 +32,14 @@
style="cursor: pointer;" src="./media/logo.png" alt="Logo"></icon>
<label id="project-title-label" style="display: block; text-align: left; font-weight: bold; font-size: x-large;">title</label>
<div class="button-row">
<!-- Training Notification Bell -->
<button id="training-bell" onclick="toggleTrainingModal()" class="button" title="Training Status"
style="padding: 8px 16px; margin-right: 10px; position: relative; background: #999;">
🔔
<span id="bell-badge" style="display: none; position: absolute; top: -5px; right: -5px; background: #ff4d4f;
color: white; border-radius: 50%; width: 20px; height: 20px; font-size: 12px; line-height: 20px;
text-align: center; font-weight: bold;">0</span>
</button>
<button id="Add Training Project" onclick="window.location.href='/add-project.html'"
class="button-red">Add Training Project</button>
<button id="seed-db-btn" class="button">
@@ -177,7 +185,123 @@
</div>
</div>
<!-- Training Status Modal -->
<div id="training-status-modal" class="modal" style="display: none;">
<div class="modal-content" style="max-width: 700px; max-height: 90vh; overflow-y: auto;">
<div class="modal-header">
<h2>Training Status</h2>
<button class="close-btn" onclick="toggleTrainingModal()">&times;</button>
</div>
<div class="modal-body">
<div class="settings-section" id="current-training-section" style="display: none;">
<h3 style="color: #009eac;">Current Training</h3>
<div id="current-training-info" style="background: #eaf7fa; padding: 16px; border-radius: 8px; margin-bottom: 16px;">
</div>
</div>
<div class="settings-section" id="queue-section" style="display: none;">
<h3 style="color: #666;">Queue (<span id="queue-count">0</span>)</h3>
<div id="queue-list" style="display: flex; flex-direction: column; gap: 12px;">
</div>
</div>
<div id="no-trainings-msg" style="text-align: center; padding: 32px; color: #666;">
No trainings running or queued.
</div>
</div>
</div>
</div>
<script src="js/settings.js"></script>
<script>
let trainingStatusPoller = null;
function toggleTrainingModal() {
const modal = document.getElementById('training-status-modal');
if (modal.style.display === 'none') {
modal.style.display = 'flex';
updateTrainingStatus();
} else {
modal.style.display = 'none';
}
}
function updateTrainingStatus() {
fetch('/api/training-status')
.then(res => res.json())
.then(data => {
const bell = document.getElementById('training-bell');
const badge = document.getElementById('bell-badge');
const currentSection = document.getElementById('current-training-section');
const queueSection = document.getElementById('queue-section');
const noTrainingsMsg = document.getElementById('no-trainings-msg');
const totalCount = (data.current ? 1 : 0) + data.queue.length;
if (totalCount > 0) {
bell.style.background = '#009eac';
badge.style.display = 'block';
badge.textContent = totalCount;
} else {
bell.style.background = '#999';
badge.style.display = 'none';
}
if (data.current) {
currentSection.style.display = 'block';
noTrainingsMsg.style.display = 'none';
const percentage = Math.round((data.current.iteration / data.current.max_epoch) * 100);
document.getElementById('current-training-info').innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<strong>${data.current.name || 'Training'}</strong>
<span style="font-weight: bold; color: #009eac;">${percentage}%</span>
</div>
<div style="background: #ddd; border-radius: 4px; height: 24px; overflow: hidden; margin-bottom: 8px;">
<div style="background: #009eac; height: 100%; width: ${percentage}%; transition: width 0.3s;"></div>
</div>
<div style="font-size: 14px; color: #666;">
Epoch ${data.current.iteration} / ${data.current.max_epoch}
</div>
`;
} else {
currentSection.style.display = 'none';
}
if (data.queue.length > 0) {
queueSection.style.display = 'block';
noTrainingsMsg.style.display = 'none';
document.getElementById('queue-count').textContent = data.queue.length;
document.getElementById('queue-list').innerHTML = data.queue.map((t, idx) => `
<div style="background: #f5f5f5; padding: 12px; border-radius: 8px; border-left: 4px solid #009eac;">
<strong>#${idx + 1}: ${t.name || 'Training'}</strong>
<div style="font-size: 13px; color: #666; margin-top: 4px;">
${t.max_epoch} epochs • Waiting...
</div>
</div>
`).join('');
} else {
queueSection.style.display = 'none';
}
if (totalCount === 0) {
noTrainingsMsg.style.display = 'block';
}
})
.catch(err => console.error('Failed to fetch training status:', err));
}
window.addEventListener('DOMContentLoaded', function() {
updateTrainingStatus();
trainingStatusPoller = setInterval(updateTrainingStatus, 5000);
});
window.addEventListener('beforeunload', function() {
if (trainingStatusPoller) clearInterval(trainingStatusPoller);
});
</script>
</body>
</html>