diff --git a/app/static/index.html b/app/static/index.html
index f64c56a..417274d 100644
--- a/app/static/index.html
+++ b/app/static/index.html
@@ -543,6 +543,102 @@
.workload-row:hover {
background-color: rgba(255, 255, 255, 0.02);
}
+
+ /* Modal Styles */
+ .modal {
+ display: none;
+ position: fixed;
+ z-index: 1000;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.8);
+ overflow-y: auto;
+ }
+
+ .modal-content {
+ background-color: var(--pf-global--BackgroundColor--100);
+ margin: 2% auto;
+ padding: 0;
+ border-radius: 8px;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
+ animation: modalSlideIn 0.3s ease-out;
+ }
+
+ @keyframes modalSlideIn {
+ from {
+ opacity: 0;
+ transform: translateY(-50px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ .modal-header {
+ background: linear-gradient(135deg, #2B2B2B 0%, #1E1E1E 100%);
+ color: var(--pf-global--Color--100);
+ padding: 20px 24px;
+ border-bottom: 1px solid #404040;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-radius: 8px 8px 0 0;
+ }
+
+ .modal-header h2 {
+ margin: 0;
+ font-size: 20px;
+ font-weight: 600;
+ }
+
+ .close {
+ color: var(--pf-global--Color--300);
+ font-size: 28px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: color 0.2s ease;
+ }
+
+ .close:hover {
+ color: var(--pf-global--Color--100);
+ }
+
+ .modal-body {
+ padding: 24px;
+ max-height: 70vh;
+ overflow-y: auto;
+ }
+
+ .status-indicator {
+ padding: 4px 8px;
+ border-radius: 4px;
+ font-size: 12px;
+ font-weight: 600;
+ text-transform: uppercase;
+ }
+
+ .status-indicator.danger {
+ background-color: var(--pf-global--danger-color--100);
+ color: white;
+ }
+
+ .status-indicator.warning {
+ background-color: var(--pf-global--warning-color--100);
+ color: black;
+ }
+
+ .status-indicator.info {
+ background-color: var(--pf-global--info-color--100);
+ color: white;
+ }
+
+ .status-indicator.success {
+ background-color: var(--pf-global--success-color--100);
+ color: white;
+ }
@@ -897,20 +993,20 @@
${namespace.namespace}
|
- ${Object.keys(namespace.pods || {}).length} |
- ${namespace.total_validations || 0} |
+ ${Object.keys(namespace.pods || {}).length} |
+ ${namespace.total_validations || 0} |
${getSeverityText(namespace)}
|
- |
-
+
+
`).join('')}
@@ -1203,9 +1299,147 @@
`;
}
- function analyzeWorkload(namespace) {
- console.log('Analyzing workload:', namespace);
- // TODO: Implement workload analysis
+ function analyzeNamespace(namespaceName) {
+ if (!currentData || !currentData.validations || !currentData.validations.namespaces) return;
+
+ const namespace = currentData.validations.namespaces.find(ns => ns.namespace === namespaceName);
+ if (!namespace) return;
+
+ // Show details in modal
+ showNamespaceDetails(namespaceName);
+ }
+
+ function showNamespaceDetails(namespaceName) {
+ // Create modal if it doesn't exist
+ let modal = document.getElementById('namespaceModal');
+ if (!modal) {
+ modal = document.createElement('div');
+ modal.id = 'namespaceModal';
+ modal.className = 'modal';
+ modal.innerHTML = `
+
+ `;
+ document.body.appendChild(modal);
+
+ // Add close functionality
+ modal.querySelector('.close').onclick = () => modal.style.display = 'none';
+ modal.onclick = (e) => {
+ if (e.target === modal) modal.style.display = 'none';
+ };
+ }
+
+ // Create detailed content
+ const namespace = currentData.validations.namespaces.find(ns => ns.namespace === namespaceName);
+ if (!namespace) return;
+
+ let content = `
+
+
+
📊 Summary
+
+
+ Pods: ${Object.keys(namespace.pods || {}).length}
+
+
+ Total Issues: ${namespace.total_validations || 0}
+
+
+ Errors: ${namespace.severity_breakdown?.error || 0}
+
+
+ Warnings: ${namespace.severity_breakdown?.warning || 0}
+
+
+
+
+
🔍 Pod Analysis
+ `;
+
+ // Add details for each pod
+ Object.values(namespace.pods || {}).forEach(pod => {
+ content += `
+
+
📦 ${pod.pod_name}
+
+
Status: ${pod.phase}
+
Node: ${pod.node_name}
+
+
+
Containers:
+ `;
+
+ pod.containers.forEach(container => {
+ const hasRequests = Object.keys(container.resources?.requests || {}).length > 0;
+ const hasLimits = Object.keys(container.resources?.limits || {}).length > 0;
+
+ content += `
+
+
${container.name}
+
Image: ${container.image}
+
+
+ Requests:
+ ${hasRequests ?
+ `${JSON.stringify(container.resources.requests)}` :
+ '❌ Not defined'
+ }
+
+
+ Limits:
+ ${hasLimits ?
+ `${JSON.stringify(container.resources.limits)}` :
+ '❌ Not defined'
+ }
+
+
+
+ `;
+ });
+
+ content += `
+
+
+
Issues Found:
+ `;
+
+ if (pod.validations && pod.validations.length > 0) {
+ pod.validations.forEach(validation => {
+ const severityClass = validation.severity === 'error' ? 'danger' :
+ validation.severity === 'warning' ? 'warning' : 'info';
+ const severityColor = validation.severity === 'error' ? 'var(--pf-global--danger-color--100)' :
+ validation.severity === 'warning' ? 'var(--pf-global--warning-color--100)' : 'var(--pf-global--info-color--100)';
+
+ content += `
+
+
${validation.rule_name}: ${validation.message}
+
Recommendation: ${validation.recommendation}
+
+ `;
+ });
+ } else {
+ content += `
✅ No issues found for this pod.
`;
+ }
+
+ content += `
+
+
+ `;
+ });
+
+ content += `
+
+
+ `;
+
+ // Populate and show modal
+ document.getElementById('modalBody').innerHTML = content;
+ modal.style.display = 'block';
}
function getSeverityClass(namespace) {