Files
spore-ui/public/deploy-button-test.html
2025-08-28 10:21:14 +02:00

344 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Deploy Button Test - Isolated</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #1a202c;
color: white;
}
.test-section {
background: rgba(255, 255, 255, 0.05);
padding: 20px;
margin: 20px 0;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.firmware-actions {
background: rgba(0, 0, 0, 0.3);
padding: 20px;
border-radius: 8px;
}
.target-options {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.target-option {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
}
.file-input-wrapper {
margin: 20px 0;
}
.deploy-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
color: white;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
}
.deploy-btn:disabled {
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.4);
cursor: not-allowed;
}
.node-select {
background: #2d3748;
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 5px 10px;
border-radius: 4px;
margin-left: 10px;
}
.cluster-members {
background: rgba(0, 0, 0, 0.2);
padding: 15px;
border-radius: 6px;
margin: 20px 0;
}
.member-card {
background: rgba(255, 255, 255, 0.05);
padding: 10px;
margin: 10px 0;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.debug-info {
background: rgba(0, 0, 0, 0.5);
padding: 15px;
border-radius: 6px;
margin: 20px 0;
font-family: monospace;
font-size: 12px;
}
</style>
</head>
<body>
<h1>🚀 Deploy Button Test - Isolated</h1>
<div class="test-section">
<h2>Test Scenario: Deploy Button State</h2>
<p>This test isolates the deploy button functionality to debug the issue.</p>
</div>
<div class="firmware-actions">
<h3>🚀 Firmware Update</h3>
<div class="target-options">
<label class="target-option">
<input type="radio" name="target-type" value="all" checked>
<span>All Nodes</span>
</label>
<label class="target-option">
<input type="radio" name="target-type" value="specific">
<span>Specific Node</span>
<select id="specific-node-select" class="node-select" style="visibility: hidden; opacity: 0;">
<option value="">Select a node...</option>
</select>
</label>
</div>
<div class="file-input-wrapper">
<input type="file" id="global-firmware-file" accept=".bin,.hex" style="display: none;">
<button onclick="document.getElementById('global-firmware-file').click()">
📁 Choose File
</button>
<span id="file-info">No file selected</span>
</div>
<button class="deploy-btn" id="deploy-btn" disabled>
🚀 Deploy Firmware
</button>
</div>
<div class="cluster-members">
<h3>Cluster Members</h3>
<div id="cluster-members-container">
<div class="loading">Loading cluster members...</div>
</div>
<button onclick="addTestNode()">Add Test Node</button>
<button onclick="removeAllNodes()">Remove All Nodes</button>
</div>
<div class="debug-info">
<h3>Debug Information</h3>
<div id="debug-output">Waiting for actions...</div>
</div>
<script>
// Simulate the cluster members functionality
let testNodes = [];
function addTestNode() {
const nodeCount = testNodes.length + 1;
const newNode = {
ip: `192.168.1.${100 + nodeCount}`,
hostname: `TestNode${nodeCount}`,
status: 'active',
latency: Math.floor(Math.random() * 50) + 10
};
testNodes.push(newNode);
displayClusterMembers();
populateNodeSelect();
updateDeployButton();
updateDebugInfo();
}
function removeAllNodes() {
testNodes = [];
displayClusterMembers();
populateNodeSelect();
updateDeployButton();
updateDebugInfo();
}
function displayClusterMembers() {
const container = document.getElementById('cluster-members-container');
if (testNodes.length === 0) {
container.innerHTML = '<div class="loading">No cluster members found</div>';
return;
}
const membersHTML = testNodes.map(node => {
const statusClass = node.status === 'active' ? 'status-online' : 'status-offline';
const statusText = node.status === 'active' ? 'Online' : 'Offline';
const statusIcon = node.status === 'active' ? '🟢' : '🔴';
return `
<div class="member-card" data-member-ip="${node.ip}">
<div class="member-name">${node.hostname}</div>
<div class="member-ip">${node.ip}</div>
<div class="member-status ${statusClass}">
${statusIcon} ${statusText}
</div>
<div class="member-latency">Latency: ${node.latency}ms</div>
</div>
`;
}).join('');
container.innerHTML = membersHTML;
}
function populateNodeSelect() {
const select = document.getElementById('specific-node-select');
if (!select) return;
select.innerHTML = '<option value="">Select a node...</option>';
if (testNodes.length === 0) {
const option = document.createElement('option');
option.value = "";
option.textContent = "No nodes available";
option.disabled = true;
select.appendChild(option);
return;
}
testNodes.forEach(node => {
const option = document.createElement('option');
option.value = node.ip;
option.textContent = `${node.hostname} (${node.ip})`;
select.appendChild(option);
});
}
function updateDeployButton() {
const deployBtn = document.getElementById('deploy-btn');
const fileInput = document.getElementById('global-firmware-file');
const targetType = document.querySelector('input[name="target-type"]:checked');
const specificNodeSelect = document.getElementById('specific-node-select');
if (!deployBtn || !fileInput) return;
const hasFile = fileInput.files && fileInput.files.length > 0;
const hasAvailableNodes = testNodes.length > 0;
let isValidTarget = false;
if (targetType.value === 'all') {
isValidTarget = hasAvailableNodes;
} else if (targetType.value === 'specific') {
isValidTarget = hasAvailableNodes && specificNodeSelect.value && specificNodeSelect.value !== "";
}
// Debug logging
const debugInfo = {
hasFile,
targetType: targetType?.value,
hasAvailableNodes,
specificNodeValue: specificNodeSelect?.value,
isValidTarget,
memberCardsCount: testNodes.length
};
console.log('updateDeployButton debug:', debugInfo);
deployBtn.disabled = !hasFile || !isValidTarget;
// Update button text to provide better feedback
if (!hasAvailableNodes) {
deployBtn.textContent = '🚀 Deploy (No nodes available)';
deployBtn.title = 'No cluster nodes are currently available for deployment';
} else if (!hasFile) {
deployBtn.textContent = '🚀 Deploy Firmware';
deployBtn.title = 'Please select a firmware file to deploy';
} else if (!isValidTarget) {
deployBtn.textContent = '🚀 Deploy Firmware';
deployBtn.title = 'Please select a valid target for deployment';
} else {
deployBtn.textContent = '🚀 Deploy Firmware';
deployBtn.title = 'Ready to deploy firmware';
}
updateDebugInfo();
}
function updateDebugInfo() {
const debugOutput = document.getElementById('debug-output');
const deployBtn = document.getElementById('deploy-btn');
const fileInput = document.getElementById('global-firmware-file');
const targetType = document.querySelector('input[name="target-type"]:checked');
const specificNodeSelect = document.getElementById('specific-node-select');
const debugInfo = {
hasFile: fileInput.files && fileInput.files.length > 0,
targetType: targetType?.value,
hasAvailableNodes: testNodes.length > 0,
specificNodeValue: specificNodeSelect?.value,
deployButtonDisabled: deployBtn.disabled,
deployButtonText: deployBtn.textContent,
testNodesCount: testNodes.length
};
debugOutput.innerHTML = `<pre>${JSON.stringify(debugInfo, null, 2)}</pre>`;
}
// Setup event listeners
document.addEventListener('DOMContentLoaded', function() {
// Setup target selection
const targetRadios = document.querySelectorAll('input[name="target-type"]');
const specificNodeSelect = document.getElementById('specific-node-select');
targetRadios.forEach(radio => {
radio.addEventListener('change', () => {
console.log('Target radio changed to:', radio.value);
if (radio.value === 'specific') {
specificNodeSelect.style.visibility = 'visible';
specificNodeSelect.style.opacity = '1';
populateNodeSelect();
} else {
specificNodeSelect.style.visibility = 'hidden';
specificNodeSelect.style.opacity = '0';
}
console.log('Calling updateDeployButton after target change');
updateDeployButton();
});
});
// Setup specific node select change handler
if (specificNodeSelect) {
specificNodeSelect.addEventListener('change', (event) => {
console.log('Specific node select changed to:', event.target.value);
updateDeployButton();
});
}
// Setup file input change handler
const fileInput = document.getElementById('global-firmware-file');
if (fileInput) {
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
const fileInfo = document.getElementById('file-info');
if (file) {
fileInfo.textContent = `${file.name} (${(file.size / 1024).toFixed(1)}KB)`;
} else {
fileInfo.textContent = 'No file selected';
}
updateDeployButton();
});
}
// Initial setup
displayClusterMembers();
populateNodeSelect();
updateDeployButton();
});
</script>
</body>
</html>