diff --git a/app/static/index.html b/app/static/index.html index fd8196b..e4f769e 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -732,6 +732,127 @@ background-color: rgba(255, 255, 255, 0.02); } + /* Workload Accordion Styles */ + .workloads-accordion { + margin-top: 16px; + } + + .workload-accordion-item { + border: 1px solid var(--pf-global--BorderColor--200); + border-radius: 8px; + margin-bottom: 12px; + background-color: var(--pf-global--BackgroundColor--100); + overflow: hidden; + } + + .workload-accordion-header { + padding: 16px 20px; + background-color: var(--pf-global--BackgroundColor--200); + cursor: pointer; + display: flex; + justify-content: space-between; + align-items: center; + transition: background-color 0.2s ease; + } + + .workload-accordion-header:hover { + background-color: var(--pf-global--BackgroundColor--300); + } + + .workload-accordion-title { + display: flex; + align-items: center; + gap: 12px; + } + + .workload-accordion-icon { + transition: transform 0.2s ease; + color: var(--pf-global--Color--400); + } + + .workload-accordion-stats { + display: flex; + align-items: center; + gap: 16px; + } + + .workload-stat { + display: flex; + align-items: center; + gap: 6px; + color: var(--pf-global--Color--300); + font-size: 14px; + } + + .workload-stat i { + color: var(--pf-global--Color--400); + } + + .workload-accordion-content { + background-color: var(--pf-global--BackgroundColor--100); + border-top: 1px solid var(--pf-global--BorderColor--200); + } + + .workload-issues-container { + padding: 20px; + } + + .workload-issues-list { + display: flex; + flex-direction: column; + gap: 12px; + } + + .workload-issue-item { + background-color: var(--pf-global--BackgroundColor--200); + border: 1px solid var(--pf-global--BorderColor--200); + border-radius: 6px; + padding: 16px; + } + + .workload-issue-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 8px; + } + + .workload-issue-title { + font-weight: 600; + color: var(--pf-global--Color--100); + flex: 1; + } + + .workload-issue-pod { + color: var(--pf-global--Color--300); + font-size: 14px; + background-color: var(--pf-global--BackgroundColor--300); + padding: 4px 8px; + border-radius: 4px; + } + + .workload-issue-content { + margin-top: 8px; + } + + .workload-issue-message { + color: var(--pf-global--Color--200); + margin: 0 0 8px 0; + line-height: 1.5; + } + + .workload-issue-recommendation { + background-color: var(--pf-global--BackgroundColor--300); + border-left: 3px solid var(--pf-global--info-color--100); + padding: 12px; + border-radius: 4px; + margin-top: 8px; + } + + .workload-issue-recommendation strong { + color: var(--pf-global--info-color--100); + } + /* Modal Styles */ .modal { display: block; @@ -1591,15 +1712,133 @@ currentData = { validations: validationsData }; - // Update workloads table + // Update workloads accordion updateWorkloadsTable(validationsData); + // Pre-load all workload details + await preloadAllWorkloadDetails(); + } catch (error) { console.error('Error loading requests & limits data:', error); showError('workloads-table-container', 'Failed to load workload data'); } } + async function preloadAllWorkloadDetails() { + if (!window.workloadsData) return; + + // Load details for all namespaces in parallel + const loadPromises = window.workloadsData.map(async (namespace, index) => { + try { + const response = await fetch(`/api/v1/validations/namespace/${namespace.namespace}`); + const data = await response.json(); + + // Store the data for when accordion is opened + window.workloadDetails = window.workloadDetails || {}; + window.workloadDetails[namespace.namespace] = data; + + } catch (error) { + console.error(`Error loading details for namespace ${namespace.namespace}:`, error); + window.workloadDetails = window.workloadDetails || {}; + window.workloadDetails[namespace.namespace] = { error: 'Failed to load details' }; + } + }); + + await Promise.all(loadPromises); + } + + function toggleWorkloadIssues(index) { + const content = document.getElementById(`workload-content-${index}`); + const icon = document.getElementById(`workload-icon-${index}`); + + if (content.style.display === 'none') { + // Expand accordion + content.style.display = 'block'; + icon.classList.remove('fa-chevron-right'); + icon.classList.add('fa-chevron-down'); + + // Load issues if not already loaded + loadWorkloadIssues(index); + } else { + // Collapse accordion + content.style.display = 'none'; + icon.classList.remove('fa-chevron-down'); + icon.classList.add('fa-chevron-right'); + } + } + + function loadWorkloadIssues(index) { + const namespace = window.workloadsData[index]; + const container = document.getElementById(`workload-issues-${index}`); + + if (!namespace) return; + + // Check if we already have the data + if (window.workloadDetails && window.workloadDetails[namespace.namespace]) { + const data = window.workloadDetails[namespace.namespace]; + + if (data.error) { + container.innerHTML = ` +
+ `; + return; + } + + // Display the issues + displayWorkloadIssues(container, data, namespace); + return; + } + + // If data not available, show loading + container.innerHTML = ` +No issues found for this namespace
+All workloads are properly configured
- - `; + + `; return; } - const tableHTML = ` -| Namespace | -Pods | -Issues | -Status | -Actions | -
|---|---|---|---|---|
|
+ // Create accordion HTML
+ const accordionHTML = `
+
+ ${namespaces.map((namespace, index) => `
+
+
+
+
${namespace.namespace}
- |
- ${namespace.pods.size} | -${namespace.validations.length} | -
+
+
+
+
+ ${namespace.pods.size} pods
+
+
+
+ ${namespace.validations.length} issues
+
${getSeverityText(namespace)}
- |
- - - | -
Image: ${container.image}
-${validation.validation_type || validation.title || 'Issue'}: ${validation.message || validation.description}
-Recommendation: ${validation.recommendation || validation.action_required || 'No specific recommendation available'}
-✅ No issues found for this pod.
`; - } - - content += ` -