Complete Task 5: Mithal monitoring dashboard

هذا الالتزام موجود في:
2026-07-28 18:57:31 +03:00
الأصل fbcb4e997c
التزام 3a5d1dece0
15 ملفات معدلة مع 800 إضافات و0 حذوفات

عرض الملف

@@ -0,0 +1,120 @@
async function loadData() {
try {
const response = await fetch("data.json?t=" + Date.now());
const data = await response.json();
if (data.length === 0) {
return;
}
const latest = data[data.length - 1];
const upCount = data.filter(item => item.uptime === "UP").length;
const uptimePercentage = ((upCount / data.length) * 100).toFixed(1);
document.getElementById("uptime").innerText =
uptimePercentage + "%";
document.getElementById("latency").innerText =
(latest.latency_ms ?? "-") + " ms";
document.getElementById("dns").innerText =
(latest.dns_ms ?? "-") + " ms";
if (latest.ssl && latest.ssl.valid) {
document.getElementById("ssl").innerHTML = `
<strong style="color:green;">Valid</strong><br>
<small>${latest.ssl.expires}</small>
`;
} else {
document.getElementById("ssl").innerHTML = `
<strong style="color:red;">Invalid</strong>
`;
}
const table = document.getElementById("historyTable");
table.innerHTML = "";
data
.slice()
.reverse()
.forEach(item => {
table.innerHTML += `
<tr>
<td>${item.timestamp}</td>
<td>${item.uptime}</td>
<td>${item.latency_ms ?? "-"}</td>
<td>${item.dns_ms ?? "-"}</td>
<td>${item.ssl && item.ssl.valid ? "Valid" : "Invalid"}</td>
</tr>
`;
});
const labels = data.map(item => item.timestamp);
const latency = data.map(item => item.latency_ms);
if (!window.latencyChart) {
window.latencyChart = new Chart(
document.getElementById("latencyChart"),
{
type: "line",
data: {
labels: labels,
datasets: [{
label: "Latency (ms)",
data: latency,
borderColor: "#0b7dda",
backgroundColor: "rgba(11,125,218,0.15)",
fill: true,
tension: 0.3
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: true
}
},
scales: {
y: {
beginAtZero: false
}
}
}
}
);
} else {
window.latencyChart.data.labels = labels;
window.latencyChart.data.datasets[0].data = latency;
window.latencyChart.update();
}
}
catch (error) {
console.error(error);
}
}
loadData();
setInterval(loadData, 60000);

عرض الملف

@@ -0,0 +1,62 @@
[
{
"timestamp": "2026-07-28 17:50:54",
"status_code": 200,
"uptime": "UP",
"latency_ms": 994.55,
"dns_ms": 39.1,
"search_response_ms": 1170.81,
"ssl": {
"valid": true,
"expires": "Sep 15 13:10:47 2026 GMT"
}
},
{
"timestamp": "2026-07-28 17:50:58",
"status_code": 200,
"uptime": "UP",
"latency_ms": 986.42,
"dns_ms": 40.91,
"search_response_ms": 1130.27,
"ssl": {
"valid": true,
"expires": "Sep 15 13:10:47 2026 GMT"
}
},
{
"timestamp": "2026-07-28 17:51:01",
"status_code": 200,
"uptime": "UP",
"latency_ms": 980.57,
"dns_ms": 51.6,
"search_response_ms": 1168.75,
"ssl": {
"valid": true,
"expires": "Sep 15 13:10:47 2026 GMT"
}
},
{
"timestamp": "2026-07-28 17:51:04",
"status_code": 200,
"uptime": "UP",
"latency_ms": 969.79,
"dns_ms": 40.75,
"search_response_ms": 1209.84,
"ssl": {
"valid": true,
"expires": "Sep 15 13:10:47 2026 GMT"
}
},
{
"timestamp": "2026-07-28 17:51:07",
"status_code": 200,
"uptime": "UP",
"latency_ms": 976.47,
"dns_ms": 42.13,
"search_response_ms": 1147.52,
"ssl": {
"valid": true,
"expires": "Sep 15 13:10:47 2026 GMT"
}
}
]

عرض الملف

@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mithal Monitoring Dashboard</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div class="container">
<h1>Mithal Monitoring Dashboard</h1>
<p class="subtitle">
Website Monitoring Dashboard for mithal.space
</p>
<div class="cards">
<div class="card">
<h2>Uptime</h2>
<p id="uptime">--</p>
</div>
<div class="card">
<h2>Latency</h2>
<p id="latency">--</p>
</div>
<div class="card">
<h2>DNS Time</h2>
<p id="dns">--</p>
</div>
<div class="card">
<h2>SSL</h2>
<p id="ssl">--</p>
</div>
</div>
<div class="chart-card">
<h2>Latency History</h2>
<canvas id="latencyChart"></canvas>
</div>
<div class="table-card">
<h2>Last 10 Checks</h2>
<table>
<thead>
<tr>
<th>Time</th>
<th>Status</th>
<th>Latency (ms)</th>
<th>DNS (ms)</th>
<th>SSL</th>
</tr>
</thead>
<tbody id="historyTable">
</tbody>
</table>
</div>
</div>
<script src="app.js"></script>
</body>
</html>

عرض الملف

@@ -0,0 +1,122 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, Helvetica, sans-serif;
background: #f4f7fb;
color: #333;
}
.container {
width: 95%;
max-width: 1300px;
margin: 40px auto;
}
h1 {
text-align: center;
margin-bottom: 10px;
color: #2c3e50;
}
.subtitle {
text-align: center;
margin-bottom: 35px;
color: gray;
}
.cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 35px;
}
.card {
background: white;
border-radius: 10px;
padding: 25px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,.08);
}
.card h2 {
margin-bottom: 15px;
color: #555;
font-size: 20px;
}
.card p {
font-size: 30px;
font-weight: bold;
color: #0b7dda;
}
.chart-card,
.table-card {
background: white;
border-radius: 10px;
padding: 25px;
margin-top: 30px;
box-shadow: 0 2px 8px rgba(0,0,0,.08);
}
.chart-card h2,
.table-card h2 {
margin-bottom: 20px;
}
table {
width: 100%;
border-collapse: collapse;
}
thead {
background: #0b7dda;
color: white;
}
th,
td {
padding: 12px;
text-align: center;
border-bottom: 1px solid #ddd;
}
tbody tr:hover {
background: #f5f5f5;
}
canvas {
width: 100% !important;
max-height: 350px;
}
@media (max-width:900px){
.cards{
grid-template-columns:repeat(2,1fr);
}
}
@media (max-width:600px){
.cards{
grid-template-columns:1fr;
}
table{
font-size:12px;
}
}