feat: add fw tab

This commit is contained in:
2025-08-25 10:00:49 +02:00
parent 9514bf7ac5
commit 381dde1b97
3 changed files with 578 additions and 11 deletions

View File

@@ -529,8 +529,157 @@ function displayClusterMembers(members, expandedCards = new Map()) {
// Load cluster members when page loads
document.addEventListener('DOMContentLoaded', function() {
refreshClusterMembers();
setupNavigation();
setupFirmwareView();
});
// Auto-refresh every 30 seconds
// FIXME not working properly: scroll position is not preserved, if there is an upload happening, this mus also be handled
//setInterval(refreshClusterMembers, 30000);
//setInterval(refreshClusterMembers, 30000);
// Setup navigation menu
function setupNavigation() {
const navTabs = document.querySelectorAll('.nav-tab');
const viewContents = document.querySelectorAll('.view-content');
navTabs.forEach(tab => {
tab.addEventListener('click', () => {
const targetView = tab.dataset.view;
// Update active tab
navTabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// Update active view
viewContents.forEach(view => view.classList.remove('active'));
const targetViewElement = document.getElementById(`${targetView}-view`);
if (targetViewElement) {
targetViewElement.classList.add('active');
}
// Refresh the active view
if (targetView === 'cluster') {
refreshClusterMembers();
} else if (targetView === 'firmware') {
refreshFirmwareView();
}
});
});
}
// Setup firmware view
function setupFirmwareView() {
// Setup global firmware file input
const globalFirmwareFile = document.getElementById('global-firmware-file');
if (globalFirmwareFile) {
globalFirmwareFile.addEventListener('change', handleGlobalFirmwareUpload);
}
// Setup target selection
const targetRadios = document.querySelectorAll('input[name="target-type"]');
const specificNodeSelect = document.getElementById('specific-node-select');
targetRadios.forEach(radio => {
radio.addEventListener('change', () => {
if (radio.value === 'specific') {
specificNodeSelect.style.display = 'block';
populateNodeSelect();
} else {
specificNodeSelect.style.display = 'none';
}
});
});
}
// Handle global firmware upload
async function handleGlobalFirmwareUpload(event) {
const file = event.target.files[0];
if (!file) return;
const targetType = document.querySelector('input[name="target-type"]:checked').value;
const specificNode = document.getElementById('specific-node-select').value;
if (targetType === 'specific' && !specificNode) {
alert('Please select a specific node to update.');
return;
}
try {
if (targetType === 'all') {
await uploadFirmwareToAllNodes(file);
} else {
await uploadFirmwareToSpecificNode(file, specificNode);
}
} catch (error) {
console.error('Global firmware upload failed:', error);
alert(`Upload failed: ${error.message}`);
}
// Clear file input
event.target.value = '';
}
// Upload firmware to all nodes
async function uploadFirmwareToAllNodes(file) {
const response = await client.getClusterMembers();
const nodes = response.members || [];
if (nodes.length === 0) {
alert('No nodes available for firmware update.');
return;
}
const confirmed = confirm(`Upload firmware to all ${nodes.length} nodes? This will update: ${nodes.map(n => n.hostname || n.ip).join(', ')}`);
if (!confirmed) return;
// TODO: Implement batch upload logic
alert(`Firmware upload to all ${nodes.length} nodes initiated. This feature is coming soon!`);
}
// Upload firmware to specific node
async function uploadFirmwareToSpecificNode(file, nodeIp) {
const confirmed = confirm(`Upload firmware to node ${nodeIp}?`);
if (!confirmed) return;
// TODO: Implement single node upload logic
alert(`Firmware upload to node ${nodeIp} initiated. This feature is coming soon!`);
}
// Populate node select dropdown
function populateNodeSelect() {
const select = document.getElementById('specific-node-select');
if (!select) return;
// Clear existing options
select.innerHTML = '<option value="">Select a node...</option>';
// Get current cluster members and populate
const container = document.getElementById('cluster-members-container');
const memberCards = container.querySelectorAll('.member-card');
memberCards.forEach(card => {
const memberIp = card.dataset.memberIp;
const hostname = card.querySelector('.member-name')?.textContent || memberIp;
const option = document.createElement('option');
option.value = memberIp;
option.textContent = `${hostname} (${memberIp})`;
select.appendChild(option);
});
}
// Refresh firmware view
function refreshFirmwareView() {
updateFirmwareStats();
populateNodeSelect();
}
// Update firmware statistics
function updateFirmwareStats() {
const container = document.getElementById('cluster-members-container');
const memberCards = container.querySelectorAll('.member-card');
document.getElementById('total-nodes').textContent = memberCards.length;
document.getElementById('available-updates').textContent = '0'; // TODO: Implement update checking
document.getElementById('last-update').textContent = 'Never'; // TODO: Implement last update tracking
}