Refine dark theme readability and chart visibility across dashboard pages
This commit is contained in:
1 parent
b9da742b3d
commit
0475bf5aa5
20 files changed
+929
-320
No files matched your search
+54
-60
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import './App.css';
|
||||
import './CommandCenterPages.css';
|
||||
|
||||
function SLA() {
|
||||
const [slaData, setSlaData] = useState([]);
|
||||
@@ -66,22 +67,15 @@ function SLA() {
|
||||
} : null;
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="container cc-page">
|
||||
{limitedByRetention && (
|
||||
<div style={{
|
||||
padding: '1rem',
|
||||
marginBottom: '1rem',
|
||||
backgroundColor: '#fff3cd',
|
||||
border: '1px solid #ffc107',
|
||||
borderRadius: '4px',
|
||||
color: '#856404'
|
||||
}}>
|
||||
<div className="cc-alert">
|
||||
⚠️ SLA data limited to {effectiveDays} days (server retention setting). Requested {days} days.
|
||||
</div>
|
||||
)}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '2rem', flexWrap: 'wrap', gap: '1rem' }}>
|
||||
<h2>SLA Dashboard</h2>
|
||||
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
||||
<div className="cc-page-header">
|
||||
<h2 className="cc-page-title">SLA Dashboard</h2>
|
||||
<div className="cc-controls">
|
||||
{[7, 14, 30, 90].map((d) => (
|
||||
<button
|
||||
key={d}
|
||||
@@ -95,33 +89,33 @@ function SLA() {
|
||||
))}
|
||||
</div>
|
||||
{limitedByRetention && (
|
||||
<div style={{ background: '#FFF8E1', color: '#8D6E63', padding: '0.5rem 0.75rem', borderRadius: '6px', border: '1px solid #FFECB3' }}>
|
||||
<div className="cc-alert" style={{ marginBottom: 0 }}>
|
||||
Limited by data retention ({effectiveDays} days). Increase Retention in Settings to view longer periods.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{overallStats && (
|
||||
<div className="stats-grid" style={{ marginBottom: '2rem', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
|
||||
<div className="stat" style={{ background: '#f5f5f5', padding: '1.5rem', borderRadius: '8px' }}>
|
||||
<p className="stat-value" style={{ color: '#667eea', fontSize: '2.5rem' }}>{overallStats.totalResources}</p>
|
||||
<p className="stat-label">Total Resources</p>
|
||||
<div className="cc-kpi-grid" style={{ marginBottom: '1rem' }}>
|
||||
<div className="cc-kpi">
|
||||
<p className="cc-kpi-label">Total Resources</p>
|
||||
<p className="cc-kpi-value" style={{ color: '#60a5fa' }}>{overallStats.totalResources}</p>
|
||||
</div>
|
||||
<div className="stat" style={{ background: '#f5f5f5', padding: '1.5rem', borderRadius: '8px' }}>
|
||||
<p className="stat-value" style={{ color: '#4caf50', fontSize: '2.5rem' }}>{overallStats.meetingTarget}/{overallStats.totalResources}</p>
|
||||
<p className="stat-label">Meeting SLA Target</p>
|
||||
<div className="cc-kpi">
|
||||
<p className="cc-kpi-label">Meeting SLA Target</p>
|
||||
<p className="cc-kpi-value" style={{ color: '#22c55e' }}>{overallStats.meetingTarget}/{overallStats.totalResources}</p>
|
||||
</div>
|
||||
<div className="stat" style={{ background: '#f5f5f5', padding: '1.5rem', borderRadius: '8px' }}>
|
||||
<p className="stat-value" style={{ color: '#667eea', fontSize: '2.5rem' }}>{overallStats.avgUptime}%</p>
|
||||
<p className="stat-label">Average Uptime</p>
|
||||
<div className="cc-kpi">
|
||||
<p className="cc-kpi-label">Average Uptime</p>
|
||||
<p className="cc-kpi-value" style={{ color: '#a78bfa' }}>{overallStats.avgUptime}%</p>
|
||||
</div>
|
||||
<div className="stat" style={{ background: '#f5f5f5', padding: '1.5rem', borderRadius: '8px' }}>
|
||||
<p className="stat-value" style={{ color: '#ff9800', fontSize: '2.5rem' }}>{overallStats.totalIncidents}</p>
|
||||
<p className="stat-label">Total Incidents</p>
|
||||
<div className="cc-kpi">
|
||||
<p className="cc-kpi-label">Total Incidents</p>
|
||||
<p className="cc-kpi-value" style={{ color: '#f59e0b' }}>{overallStats.totalIncidents}</p>
|
||||
</div>
|
||||
<div className="stat" style={{ background: '#f5f5f5', padding: '1.5rem', borderRadius: '8px' }}>
|
||||
<p className="stat-value" style={{ color: '#f44336', fontSize: '2.5rem' }}>{Math.round(overallStats.totalDowntime)}m</p>
|
||||
<p className="stat-label">Total Downtime</p>
|
||||
<div className="cc-kpi">
|
||||
<p className="cc-kpi-label">Total Downtime</p>
|
||||
<p className="cc-kpi-value" style={{ color: '#ef4444' }}>{Math.round(overallStats.totalDowntime)}m</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -132,46 +126,46 @@ function SLA() {
|
||||
<p>Add resources to start tracking SLA metrics</p>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ overflowX: 'auto' }}>
|
||||
<table style={{ width: '100%', borderCollapse: 'collapse', background: '#fff', borderRadius: '8px', overflow: 'hidden', boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }}>
|
||||
<div className="cc-table-wrap">
|
||||
<table className="cc-table">
|
||||
<thead>
|
||||
<tr style={{ background: '#667eea', color: 'white' }}>
|
||||
<th style={{ padding: '1rem', textAlign: 'left' }}>Resource</th>
|
||||
<th style={{ padding: '1rem', textAlign: 'center' }}>Target</th>
|
||||
<th style={{ padding: '1rem', textAlign: 'center' }}>Actual</th>
|
||||
<th style={{ padding: '1rem', textAlign: 'center' }}>Status</th>
|
||||
<th style={{ padding: '1rem', textAlign: 'center' }}>Checks</th>
|
||||
<th style={{ padding: '1rem', textAlign: 'center' }}>Incidents</th>
|
||||
<th style={{ padding: '1rem', textAlign: 'center' }}>Downtime</th>
|
||||
<tr>
|
||||
<th>Resource</th>
|
||||
<th style={{ textAlign: 'center' }}>Target</th>
|
||||
<th style={{ textAlign: 'center' }}>Actual</th>
|
||||
<th style={{ textAlign: 'center' }}>Status</th>
|
||||
<th style={{ textAlign: 'center' }}>Checks</th>
|
||||
<th style={{ textAlign: 'center' }}>Incidents</th>
|
||||
<th style={{ textAlign: 'center' }}>Downtime</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{slaData.map((item, idx) => (
|
||||
<tr key={item.resource_id} style={{ borderBottom: '1px solid #eee', background: idx % 2 === 0 ? '#fafafa' : '#fff' }}>
|
||||
<td style={{ padding: '1rem', fontWeight: 'bold' }}>{item.resource_name}</td>
|
||||
<td style={{ padding: '1rem', textAlign: 'center' }}>{item.sla_target}%</td>
|
||||
<td style={{ padding: '1rem', textAlign: 'center', fontWeight: 'bold', color: item.meets_target ? '#4caf50' : '#f44336' }}>
|
||||
<tr key={item.resource_id} style={{ background: idx % 2 === 0 ? '#0b1325' : '#0f172a' }}>
|
||||
<td style={{ fontWeight: 'bold' }}>{item.resource_name}</td>
|
||||
<td style={{ textAlign: 'center' }}>{item.sla_target}%</td>
|
||||
<td style={{ textAlign: 'center', fontWeight: 'bold', color: item.meets_target ? '#22c55e' : '#ef4444' }}>
|
||||
{item.actual_uptime}%
|
||||
</td>
|
||||
<td style={{ padding: '1rem', textAlign: 'center' }}>
|
||||
<td style={{ textAlign: 'center' }}>
|
||||
<span style={{
|
||||
padding: '0.25rem 0.75rem',
|
||||
borderRadius: '12px',
|
||||
background: item.meets_target ? '#e8f5e9' : '#ffebee',
|
||||
color: item.meets_target ? '#2e7d32' : '#c62828',
|
||||
background: item.meets_target ? '#052e16' : '#3f1d1d',
|
||||
color: item.meets_target ? '#4ade80' : '#fda4af',
|
||||
fontSize: '0.875rem',
|
||||
fontWeight: 'bold'
|
||||
}}>
|
||||
{item.meets_target ? '✓ PASS' : '✗ FAIL'}
|
||||
</span>
|
||||
</td>
|
||||
<td style={{ padding: '1rem', textAlign: 'center' }}>
|
||||
<td style={{ textAlign: 'center' }}>
|
||||
{item.successful_checks}/{item.total_checks}
|
||||
</td>
|
||||
<td style={{ padding: '1rem', textAlign: 'center', color: item.incidents > 0 ? '#ff9800' : '#666' }}>
|
||||
<td style={{ textAlign: 'center', color: item.incidents > 0 ? '#f59e0b' : '#94a3b8' }}>
|
||||
{item.incidents}
|
||||
</td>
|
||||
<td style={{ padding: '1rem', textAlign: 'center' }}>
|
||||
<td style={{ textAlign: 'center' }}>
|
||||
{item.downtime_minutes > 0 ? `${item.downtime_minutes}m` : '-'}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -180,7 +174,7 @@ function SLA() {
|
||||
</table>
|
||||
|
||||
{totalItems > pageSize && (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '1rem', marginTop: '2rem', padding: '1.5rem', background: '#f5f5f5', borderRadius: '8px' }}>
|
||||
<div className="cc-pagination" style={{ marginTop: '1rem' }}>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}
|
||||
@@ -188,8 +182,8 @@ function SLA() {
|
||||
>
|
||||
← Previous
|
||||
</button>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<span style={{ color: '#666', fontSize: '0.9rem' }}>Page</span>
|
||||
<div className="cc-controls">
|
||||
<span>Page</span>
|
||||
<input
|
||||
type="number"
|
||||
value={currentPage}
|
||||
@@ -197,14 +191,14 @@ function SLA() {
|
||||
const page = Math.max(1, Math.min(Math.ceil(totalItems / pageSize), parseInt(e.target.value) || 1));
|
||||
setCurrentPage(page);
|
||||
}}
|
||||
style={{ width: '50px', padding: '0.5rem', border: '1px solid #ddd', borderRadius: '4px', textAlign: 'center' }}
|
||||
className="cc-input-sm"
|
||||
/>
|
||||
<span style={{ color: '#666', fontSize: '0.9rem' }}>of {Math.ceil(totalItems / pageSize)}</span>
|
||||
<span>of {Math.ceil(totalItems / pageSize)}</span>
|
||||
</div>
|
||||
<select
|
||||
value={pageSize}
|
||||
onChange={(e) => { setPageSize(parseInt(e.target.value)); setCurrentPage(1); }}
|
||||
style={{ padding: '0.5rem', border: '1px solid #ddd', borderRadius: '4px', background: '#fff' }}
|
||||
className="cc-select-sm"
|
||||
>
|
||||
<option value={5}>5 per page</option>
|
||||
<option value={10}>10 per page</option>
|
||||
@@ -223,13 +217,13 @@ function SLA() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: '2rem', padding: '1.5rem', background: '#f5f5f5', borderRadius: '8px' }}>
|
||||
<h3 style={{ marginTop: 0, color: '#667eea' }}>SLA Report Summary</h3>
|
||||
<p style={{ color: '#666', lineHeight: '1.6' }}>
|
||||
<div className="cc-surface" style={{ marginTop: '1rem' }}>
|
||||
<h3 className="history-resource-title">SLA Report Summary</h3>
|
||||
<p style={{ color: '#cbd5e1', lineHeight: '1.6' }}>
|
||||
This report shows the Service Level Agreement (SLA) performance for all monitored resources over the last <strong>{effectiveDays} days</strong>.
|
||||
Resources meeting their target uptime are marked as <strong style={{ color: '#4caf50' }}>PASS</strong>, while those below target are marked as <strong style={{ color: '#f44336' }}>FAIL</strong>.
|
||||
Resources meeting their target uptime are marked as <strong style={{ color: '#22c55e' }}>PASS</strong>, while those below target are marked as <strong style={{ color: '#ef4444' }}>FAIL</strong>.
|
||||
</p>
|
||||
<p style={{ color: '#666', lineHeight: '1.6', marginBottom: 0 }}>
|
||||
<p style={{ color: '#cbd5e1', lineHeight: '1.6', marginBottom: 0 }}>
|
||||
Overall performance: <strong>{overallStats?.meetingTarget || 0}</strong> out of <strong>{overallStats?.totalResources || 0}</strong> resources ({overallStats ? Math.round((overallStats.meetingTarget / overallStats.totalResources) * 100) : 0}%) are meeting their SLA targets.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user