diff --git a/src/input.css b/src/input.css index a781826..eb5e11e 100644 --- a/src/input.css +++ b/src/input.css @@ -1,5 +1,11 @@ @import "tailwindcss"; +.ubuntu-regular { + font-family: "Ubuntu", serif; + font-weight: 400; + font-style: normal; +} + .ubuntu-mono-regular { font-family: "Ubuntu Mono", serif; font-weight: 400; @@ -11,4 +17,18 @@ font-optical-sizing: auto; font-weight: 400; font-style: normal; +} + +body { + position: relative; + + /* Create the dots */ + background-image: + radial-gradient(circle at 1px 1px, #33333366 1px, transparent 0), + linear-gradient(to right, #33333366 1px, transparent 1px), + linear-gradient(to bottom, #33333366 1px, transparent 1px); + + background-size: 20px 20px; + background-position: 0 0, 0 0, 0 0; + background-attachment: fixed; } \ No newline at end of file diff --git a/src/static/css/tailwind.css b/src/static/css/tailwind.css index 29e16d1..40b6283 100644 --- a/src/static/css/tailwind.css +++ b/src/static/css/tailwind.css @@ -518,6 +518,9 @@ } } @layer utilities { + .invisible { + visibility: hidden; + } .absolute { position: absolute; } @@ -530,6 +533,12 @@ .inset-0 { inset: calc(var(--spacing) * 0); } + .top-0 { + top: calc(var(--spacing) * 0); + } + .left-0 { + left: calc(var(--spacing) * 0); + } .-z-10 { z-index: calc(10 * -1); } @@ -584,6 +593,9 @@ .mx-auto { margin-inline: auto; } + .ml-1 { + margin-left: calc(var(--spacing) * 1); + } .ml-auto { margin-left: auto; } @@ -596,12 +608,21 @@ .grid { display: grid; } + .inline { + display: inline; + } .aspect-square { aspect-ratio: 1 / 1; } .aspect-video { aspect-ratio: var(--aspect-video); } + .h-4 { + height: calc(var(--spacing) * 4); + } + .h-6 { + height: calc(var(--spacing) * 6); + } .h-8 { height: calc(var(--spacing) * 8); } @@ -620,6 +641,12 @@ .min-h-\[438px\] { min-height: 438px; } + .w-4 { + width: calc(var(--spacing) * 4); + } + .w-6 { + width: calc(var(--spacing) * 6); + } .w-\[114px\] { width: 114px; } @@ -641,6 +668,18 @@ .flex-shrink-0 { flex-shrink: 0; } + .scale-80 { + --tw-scale-x: 80%; + --tw-scale-y: 80%; + --tw-scale-z: 80%; + scale: var(--tw-scale-x) var(--tw-scale-y); + } + .scale-90 { + --tw-scale-x: 90%; + --tw-scale-y: 90%; + --tw-scale-z: 90%; + scale: var(--tw-scale-x) var(--tw-scale-y); + } .scale-140 { --tw-scale-x: 140%; --tw-scale-y: 140%; @@ -653,6 +692,9 @@ --tw-scale-z: 150%; scale: var(--tw-scale-x) var(--tw-scale-y); } + .animate-ping { + animation: var(--animate-ping); + } .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -671,12 +713,18 @@ .flex-col-reverse { flex-direction: column-reverse; } + .flex-row { + flex-direction: row; + } .items-center { align-items: center; } .items-end { align-items: flex-end; } + .items-start { + align-items: flex-start; + } .justify-center { justify-content: center; } @@ -689,6 +737,9 @@ .gap-2 { gap: calc(var(--spacing) * 2); } + .gap-3 { + gap: calc(var(--spacing) * 3); + } .gap-4 { gap: calc(var(--spacing) * 4); } @@ -701,6 +752,9 @@ .overflow-x-hidden { overflow-x: hidden; } + .rounded-full { + border-radius: calc(infinity * 1px); + } .rounded-xl { border-radius: var(--radius-xl); } @@ -714,12 +768,18 @@ .bg-\[\#1A0F05\] { background-color: #1A0F05; } - .bg-\[\#3B0D25\] { - background-color: #3B0D25; + .bg-\[\#3b0d25\] { + background-color: #3b0d25; } .bg-\[var\(--color\)\] { background-color: var(--color); } + .bg-\[var\(--ping-color\)\] { + background-color: var(--ping-color); + } + .bg-white { + background-color: var(--color-white); + } .bg-gradient-to-r { --tw-gradient-position: to right in oklab; background-image: linear-gradient(var(--tw-gradient-stops)); @@ -738,6 +798,9 @@ .to-\[75\%\] { --tw-gradient-to-position: 75%; } + .object-contain { + object-fit: contain; + } .object-cover { object-fit: cover; } @@ -792,11 +855,24 @@ .text-white { color: var(--color-white); } + .transition { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } .transition-colors { transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-duration: var(--tw-duration, var(--default-transition-duration)); } + .duration-400 { + --tw-duration: 400ms; + transition-duration: 400ms; + } + .ease-in { + --tw-ease: var(--ease-in); + transition-timing-function: var(--ease-in); + } .hover\:border-\[\#FF851A\] { &:hover { @media (hover: hover) { @@ -883,6 +959,11 @@ } } } +.ubuntu-regular { + font-family: "Ubuntu", serif; + font-weight: 400; + font-style: normal; +} .ubuntu-mono-regular { font-family: "Ubuntu Mono", serif; font-weight: 400; @@ -894,6 +975,13 @@ font-weight: 400; font-style: normal; } +body { + position: relative; + background-image: radial-gradient(circle at 1px 1px, #33333366 1px, transparent 0), linear-gradient(to right, #33333366 1px, transparent 1px), linear-gradient(to bottom, #33333366 1px, transparent 1px); + background-size: 20px 20px; + background-position: 0 0, 0 0, 0 0; + background-attachment: fixed; +} @keyframes spin { to { transform: rotate(360deg); @@ -990,3 +1078,11 @@ syntax: "*"; inherits: false; } +@property --tw-duration { + syntax: "*"; + inherits: false; +} +@property --tw-ease { + syntax: "*"; + inherits: false; +} diff --git a/src/static/images/GitHub_Invertocat_Dark.png b/src/static/images/GitHub_Invertocat_Dark.png new file mode 100644 index 0000000..10b895f Binary files /dev/null and b/src/static/images/GitHub_Invertocat_Dark.png differ diff --git a/src/static/images/Unsplash_Symbol.png b/src/static/images/Unsplash_Symbol.png new file mode 100644 index 0000000..d9e8333 Binary files /dev/null and b/src/static/images/Unsplash_Symbol.png differ diff --git a/src/static/images/avatar_48.jpg b/src/static/images/avatar_48.jpg new file mode 100644 index 0000000..d4aeeb0 Binary files /dev/null and b/src/static/images/avatar_48.jpg differ diff --git a/src/static/js/checkstatus.js b/src/static/js/checkstatus.js new file mode 100644 index 0000000..a1072ca --- /dev/null +++ b/src/static/js/checkstatus.js @@ -0,0 +1,75 @@ +let statusIcon = null; +let statusIconPing = null; +let statusText = null; + +const serviceUp = { + color: "#05df72", + text: "All Services Operational", +}; +const serviceDegraded = { + color: "#fcc800", + text: "Degraded Services", +}; +const serviceDown = { + color: "#c10007", + text: "All Services Down", +}; +const serviceUnknown = { + color: "#6a7282", + text: "Unknown", +}; + +async function getServicesHealth() { + try { + 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 + ); + } + const count = lastHeartbeats.reduce((partialSum, a) => partialSum + a, 0); + + switch (count) { + case lastHeartbeats.length: { + statusIcon.style.setProperty("--ping-color", serviceUp.color); + statusIconPing.classList.remove("invisible"); + statusText.textContent = serviceUp.text; + break; + } + case 0: { + statusIcon.style.setProperty("--ping-color", serviceDown.color); + statusIconPing.classList.add("invisible"); + statusText.textContent = serviceDown.text; + break; + } + default: { + statusIcon.style.setProperty("--ping-color", serviceDegraded.color); + statusIconPing.classList.remove("invisible"); + statusText.textContent = serviceDegraded.text; + break; + } + } + } catch (error) { + statusIcon.style.setProperty("--ping-color", serviceUnknown.color); + statusIconPing.classList.add("invisible"); + statusText.textContent = serviceUnknown.text; + console.log("Failed to fetch services status: " + error); + return; + } +} + +window.onload = () => { + statusIcon = document.getElementById("status-icon"); + statusIconPing = document.getElementById("status-icon-ping"); + statusText = document.getElementById("status-text"); + + getServicesHealth(); + setInterval(getServicesHealth, 600000); +}; diff --git a/src/templates/Base.tsx b/src/templates/Base.tsx index 9cc55f0..813685d 100644 --- a/src/templates/Base.tsx +++ b/src/templates/Base.tsx @@ -17,6 +17,7 @@ export default function Base({ children, isDev }: BaseProps) { />
...
+ +