diff --git a/index.html b/index.html index 7f17ad5..084b165 100644 --- a/index.html +++ b/index.html @@ -36,20 +36,17 @@ </head> <body class="light dark:bg-slate-900" id="body"> - <header class="sticky top-0 left-0 pt-4 pb-6 shadow-lg bg-slate-50 dark:bg-slate-800"> + <header class="top-0 left-0 pt-4 pb-6 shadow-lg bg-slate-50 dark:bg-slate-800"> <div class="flex flex-col md:flex-row gap-2 md:gap-0 items-center container max-w-[1440px] justify-between px-4"> <div class="self-start"><img src="/public/images/logo-light.svg" alt="wah.su" id="logo" /></div> <div class="self-start md:self-auto"> + <!--noformat--> <a href="https://status.wah.su" class="flex flex-row items-center gap-2" target="_blank"> - <div class="hidden w-4 h-4 bg-green-500 rounded-full dark:bg-green-400" id="status-up-icon"></div> - <div class="hidden w-4 h-4 bg-yellow-400 rounded-full dark:bg-yellow-200" id="status-degraded-icon"> - </div> - <div class="hidden w-4 h-4 bg-red-600 rounded-full dark:bg-red-500" id="status-down-icon"></div> - <p class="hidden dark:text-slate-50" id="status-up-text">All Systems Operational.</p> - <p class="hidden dark:text-slate-50" id="status-degraded-text">Degraded Services.</p> - <p class="hidden dark:text-slate-50" id="status-down-text">All Systems Down.</p> + <div class="w-4 h-4 transition ease-in bg-gray-500 rounded-full duration-400" id="status-icon"></div> + <p class="dark:text-slate-50" id="status-text">Fetching Services Status</p> </a> + <!--noformat--> </div> <div class="flex flex-row items-center self-start justify-center gap-6 -ml-4"> <label class="inline-flex items-center cursor-pointer"> diff --git a/public/js/status.js b/public/js/status.js index 3c98a1a..50b003f 100644 --- a/public/js/status.js +++ b/public/js/status.js @@ -1,63 +1,85 @@ +const statusIcon = document.getElementById("status-icon"); +const statusText = document.getElementById("status-text"); + const serviceUp = { - icon: document.getElementById("status-up-icon"), - text: document.getElementById("status-up-text"), + color: ["bg-green-500", "dark:bg-green-400"], + text: "All Services Operational", }; const serviceDegraded = { - icon: document.getElementById("status-degraded-icon"), - text: document.getElementById("status-degraded-text"), + color: ["bg-yellow-400", "dark:bg-yellow-200"], + text: "Degraded Services", }; const serviceDown = { - icon: document.getElementById("status-down-icon"), - text: document.getElementById("status-down-text"), + color: ["bg-red-600", "dark:bg-red-500"], + text: "All Services Down", +}; +const serviceUnknown = { + color: ["bg-gray-500", "dark:bg-gray-400"], + text: "Services Status Unknown", }; async function getServicesHealth() { - const serviceStatus = await fetch( - "https://status.wah.su/api/status-page/heartbeat/services" - ); - - const services = await serviceStatus.json(); - const heartbeatDict = services.heartbeatList; - let lastHeartbeats = []; - - for (const [key, value] of Object.entries(heartbeatDict)) { - lastHeartbeats.push( - heartbeatDict[key][heartbeatDict[key].length - 1].status + try { + const serviceStatus = await fetch( + "https://status.wah.su/api/status-page/heartbeat/services" ); - } - let status = "up"; - const count = lastHeartbeats.reduce((partialSum, a) => partialSum + a, 0); + const services = await serviceStatus.json(); + const heartbeatDict = services.heartbeatList; + let lastHeartbeats = []; - if (count === lastHeartbeats.length) { - status = "up"; - } else if (count === 0) { - status = "down"; - } else { - status = "degraded"; - } + for (const [key, value] of Object.entries(heartbeatDict)) { + lastHeartbeats.push( + heartbeatDict[key][heartbeatDict[key].length - 1].status + ); + } - if (status === "up") { - serviceUp.icon.classList.remove("hidden"); - serviceUp.text.classList.remove("hidden"); - serviceDegraded.icon.classList.add("hidden"); - serviceDegraded.text.classList.add("hidden"); - serviceDown.icon.classList.add("hidden"); - serviceDown.text.classList.add("hidden"); - } else if (status === "degraded") { - serviceUp.icon.classList.add("hidden"); - serviceUp.text.classList.add("hidden"); - serviceDegraded.icon.classList.remove("hidden"); - serviceDegraded.text.classList.remove("hidden"); - serviceDown.icon.classList.add("hidden"); - serviceDown.text.classList.add("hidden"); - } else if (status === "down") { - serviceUp.icon.classList.add("hidden"); - serviceUp.text.classList.add("hidden"); - serviceDegraded.icon.classList.add("hidden"); - serviceDegraded.text.classList.add("hidden"); - serviceDown.icon.classList.remove("hidden"); - serviceDown.text.classList.remove("hidden"); + let status = "up"; + const count = lastHeartbeats.reduce((partialSum, a) => partialSum + a, 0); + + if (count === lastHeartbeats.length) { + status = "up"; + } else if (count === 0) { + status = "down"; + } else { + status = "degraded"; + } + + if (status === "up") { + statusIcon.classList.add(...serviceUp.color); + statusIcon.classList.remove( + ...serviceDegraded.color, + ...serviceDown.color, + ...serviceUnknown.color + ); + statusText.textContent = serviceUp.text; + } else if (status === "degraded") { + statusIcon.classList.add(...serviceDegraded.color); + statusIcon.classList.remove( + ...serviceUp.color, + ...serviceDown.color, + ...serviceUnknown.color + ); + statusText.textContent = serviceDegraded.text; + } else if (status === "down") { + statusIcon.classList.add(...serviceDown.color); + statusIcon.classList.remove( + ...serviceUp.color, + ...serviceDegraded.color, + ...serviceUnknown.color + ); + statusText.textContent = serviceDown.text; + } + } catch (error) { + statusIcon.classList.add(...serviceUnknown.color); + statusIcon.classList.remove( + ...serviceUp.color, + ...serviceDegraded.color, + ...serviceDown.color + ); + statusText.textContent = serviceUnknown.text; + console.log("Failed to fetch services status: " + error); + return; } } diff --git a/public/output.css b/public/output.css index 5406776..1159077 100644 --- a/public/output.css +++ b/public/output.css @@ -1093,10 +1093,6 @@ input:checked + .toggle-bg { position: relative; } -.sticky { - position: sticky; -} - .inset-0 { inset: 0px; } @@ -1141,31 +1137,15 @@ input:checked + .toggle-bg { z-index: 50; } -.col-span-2 { - grid-column: span 2 / span 2; -} - -.col-span-3 { - grid-column: span 3 / span 3; -} - -.col-span-1 { - grid-column: span 1 / span 1; -} - -.row-span-1 { - grid-row: span 1 / span 1; -} - -.row-span-2 { - grid-row: span 2 / span 2; -} - .mx-auto { margin-left: auto; margin-right: auto; } +.-ml-4 { + margin-left: -1rem; +} + .mb-1 { margin-bottom: 0.25rem; } @@ -1186,8 +1166,8 @@ input:checked + .toggle-bg { margin-inline-end: 0.5rem; } -.ml-8 { - margin-left: 2rem; +.ml-2 { + margin-left: 0.5rem; } .mr-4 { @@ -1214,18 +1194,6 @@ input:checked + .toggle-bg { margin-top: 1.5rem; } -.ml-2 { - margin-left: 0.5rem; -} - -.ml-4 { - margin-left: 1rem; -} - -.-ml-4 { - margin-left: -1rem; -} - .block { display: block; } @@ -1396,10 +1364,6 @@ input:checked + .toggle-bg { grid-template-columns: repeat(7, minmax(0, 1fr)); } -.grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - .flex-row { flex-direction: row; } @@ -1452,14 +1416,6 @@ input:checked + .toggle-bg { gap: 1.5rem; } -.gap-4 { - gap: 1rem; -} - -.gap-8 { - gap: 2rem; -} - .space-x-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.5rem * var(--tw-space-x-reverse)); @@ -1555,6 +1511,11 @@ input:checked + .toggle-bg { background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } +.bg-gray-500 { + --tw-bg-opacity: 1; + background-color: rgb(107 114 128 / var(--tw-bg-opacity)); +} + .bg-gray-800 { --tw-bg-opacity: 1; background-color: rgb(31 41 55 / var(--tw-bg-opacity)); @@ -1653,21 +1614,6 @@ input:checked + .toggle-bg { padding-bottom: 1rem; } -.px-2\.5 { - padding-left: 0.625rem; - padding-right: 0.625rem; -} - -.py-1 { - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} - -.py-1\.5 { - padding-top: 0.375rem; - padding-bottom: 0.375rem; -} - .pb-6 { padding-bottom: 1.5rem; } @@ -1824,6 +1770,10 @@ input:checked + .toggle-bg { transition-duration: 150ms; } +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + .ease-out { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } @@ -2000,36 +1950,11 @@ input:checked + .toggle-bg { --tw-ring-color: rgb(164 202 254 / var(--tw-ring-opacity)); } -@media (min-width: 640px) { - .sm\:block { - display: block; - } - - .sm\:px-5 { - padding-left: 1.25rem; - padding-right: 1.25rem; - } - - .sm\:py-2 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - } - - .sm\:py-2\.5 { - padding-top: 0.625rem; - padding-bottom: 0.625rem; - } -} - @media (min-width: 768px) { .md\:ml-0 { margin-left: 0px; } - .md\:flex { - display: flex; - } - .md\:flex-row { flex-direction: row; } @@ -2101,6 +2026,11 @@ input:checked + .toggle-bg { background-color: rgb(28 100 242 / var(--tw-bg-opacity)); } +.dark\:bg-gray-400:where(.dark, .dark *) { + --tw-bg-opacity: 1; + background-color: rgb(156 163 175 / var(--tw-bg-opacity)); +} + .dark\:bg-gray-600:where(.dark, .dark *) { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); diff --git a/tailwind.config.js b/tailwind.config.js index 8390d14..0556aee 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -5,6 +5,7 @@ module.exports = { "./index.html", "./src/**/*.{html,js}", "./public/js/cards.js", + "./public/js/status.js", "./node_modules/flowbite/**/*.js", ], theme: {