Implement individual namespace historical analysis with modal UI

This commit is contained in:
2025-09-26 09:07:58 -03:00
parent 274d8a1e55
commit 3511e1cd41
3 changed files with 342 additions and 1 deletions

View File

@@ -497,6 +497,66 @@
font-size: 0.9rem;
}
/* Modal Styles */
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.modal-content {
background: white;
border-radius: 8px;
max-width: 800px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
border-bottom: 1px solid #dee2e6;
background: #f8f9fa;
}
.modal-header h2 {
margin: 0;
color: #cc0000;
}
.modal-close {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: #6c757d;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
}
.modal-close:hover {
color: #dc3545;
}
.modal-body {
padding: 1.5rem;
}
/* Filters */
.filters {
display: flex;
@@ -602,7 +662,6 @@
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
<button class="btn" onclick="loadClusterStatus()">Refresh Status</button>
<button class="btn btn-secondary" onclick="loadValidationsByNamespace()">View Analysis</button>
<button class="btn btn-secondary" onclick="loadHistoricalValidations()">Historical Analysis</button>
<button class="btn btn-secondary" onclick="loadVPARecommendations()">View VPA</button>
</div>
</div>
@@ -713,6 +772,19 @@
<!-- Success -->
<div class="success hidden" id="success"></div>
<!-- Historical Analysis Modal -->
<div class="modal hidden" id="historicalModal">
<div class="modal-content">
<div class="modal-header">
<h2 id="historicalModalTitle">Historical Analysis</h2>
<button class="modal-close" onclick="closeHistoricalModal()">&times;</button>
</div>
<div class="modal-body" id="historicalModalBody">
<!-- Content will be loaded here -->
</div>
</div>
</div>
</div>
<script>
@@ -966,6 +1038,7 @@
<div class="accordion-stat">${totalValidations} analysis</div>
<div class="accordion-stat" style="color: #dc3545;">${errorCount} errors</div>
<div class="accordion-stat" style="color: #ffc107;">${warningCount} warnings</div>
<button class="btn btn-secondary" style="padding: 0.25rem 0.5rem; font-size: 0.8rem; margin-left: 0.5rem;" onclick="event.stopPropagation(); loadNamespaceHistoricalAnalysis('${namespace.namespace}')">Historical Analysis</button>
</div>
<div class="accordion-arrow">▶</div>
</div>
@@ -1277,6 +1350,122 @@
container.innerHTML = html;
}
// Historical Analysis Modal Functions
async function loadNamespaceHistoricalAnalysis(namespace) {
showLoading();
try {
const timeRange = '24h'; // Default time range
const response = await fetch(`/api/v1/namespace/${namespace}/historical-analysis?time_range=${timeRange}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
displayNamespaceHistoricalAnalysis(data);
showHistoricalModal(namespace);
} catch (error) {
showError('Error loading historical analysis: ' + error.message);
} finally {
hideLoading();
}
}
function displayNamespaceHistoricalAnalysis(data) {
const container = document.getElementById('historicalModalBody');
if (data.analysis.error) {
container.innerHTML = `
<div class="error">
<h3>Error loading historical data</h3>
<p>${data.analysis.error}</p>
</div>
`;
return;
}
const analysis = data.analysis;
const recommendations = analysis.recommendations || [];
let html = `
<div class="historical-summary">
<h3>Namespace: ${analysis.namespace}</h3>
<p><strong>Time Range:</strong> ${analysis.time_range}</p>
<p><strong>Pods:</strong> ${analysis.pod_count}</p>
</div>
<div class="historical-stats">
<div class="historical-stat">
<h4>CPU Usage</h4>
<div class="value">${analysis.cpu_usage.toFixed(3)} cores</div>
</div>
<div class="historical-stat">
<h4>Memory Usage</h4>
<div class="value">${(analysis.memory_usage / (1024*1024*1024)).toFixed(2)} GiB</div>
</div>
<div class="historical-stat">
<h4>CPU Utilization</h4>
<div class="value" style="color: ${analysis.cpu_utilization > 80 ? '#dc3545' : analysis.cpu_utilization < 20 ? '#28a745' : '#007bff'}">${analysis.cpu_utilization.toFixed(1)}%</div>
</div>
<div class="historical-stat">
<h4>Memory Utilization</h4>
<div class="value" style="color: ${analysis.memory_utilization > 80 ? '#dc3545' : analysis.memory_utilization < 20 ? '#28a745' : '#007bff'}">${analysis.memory_utilization.toFixed(1)}%</div>
</div>
</div>
`;
if (recommendations.length > 0) {
html += `
<div class="historical-summary">
<h3>Recommendations</h3>
`;
recommendations.forEach(rec => {
const severityClass = rec.severity;
html += `
<div class="historical-validation ${severityClass}">
<div class="validation-header">
<span class="severity-badge severity-${severityClass}">${severityClass}</span>
${rec.message}
</div>
<div class="validation-recommendation">
<strong>Recommendation:</strong> ${rec.recommendation}
</div>
</div>
`;
});
html += `</div>`;
} else {
html += `
<div class="historical-summary">
<h3>Recommendations</h3>
<p>No specific recommendations at this time. Resource utilization appears to be within normal ranges.</p>
</div>
`;
}
container.innerHTML = html;
}
function showHistoricalModal(namespace) {
document.getElementById('historicalModalTitle').textContent = `Historical Analysis - ${namespace}`;
document.getElementById('historicalModal').classList.remove('hidden');
}
function closeHistoricalModal() {
document.getElementById('historicalModal').classList.add('hidden');
}
// Close modal when clicking outside
document.getElementById('historicalModal').addEventListener('click', function(e) {
if (e.target === this) {
closeHistoricalModal();
}
});
</script>
</body>
</html>