Fixed the edge case typing animation fail.
All checks were successful
Deploy / deploy (push) Successful in 17s

This commit is contained in:
elijah 2024-11-04 15:58:35 +01:00
parent 2746f73cff
commit be069419ce

View File

@ -1,21 +1,21 @@
// animation speeds (ms) // animation speeds cause why not
const TYPING_SPEED = 180; const TYPING_SPEED = 60;
const ERASE_SPEED = 100; const ERASE_SPEED = 80;
const STATUS_UPDATE_INTERVAL = 60000; // 1min const STATUS_UPDATE_INTERVAL = 60000; // 1min updates
const TIME_UPDATE_INTERVAL = 1; // 1ms (still terrible) const TIME_UPDATE_INTERVAL = 1; // 1ms updates (yeah its bad)
// status thresholds // status warning stuff
const LATENCY_WARNING_THRESHOLD = 500000; const LATENCY_WARNING_THRESHOLD = 500000;
// mapping for group names because i'm lazy // lazy group name mapping
const GROUP_NAMES = { const GROUP_NAMES = {
4: "INFRASTRUCTURE", 4: "INFRASTRUCTURE",
5: "SERVICES", 5: "SERVICES",
6: "API", 6: "API",
}; };
// fancy text typing animation for nav labels // does the fancy typing animation for nav labels
// overcomplicated as fuck but whatever // its way overcomplicated but whatever
function writeoutnavlabel(label) { function writeoutnavlabel(label) {
if (label.getAttribute("data-animating") === "true") return; if (label.getAttribute("data-animating") === "true") return;
@ -44,8 +44,8 @@ function writeoutnavlabel(label) {
label.setAttribute("data-animation-interval", animationInterval); label.setAttribute("data-animation-interval", animationInterval);
} }
// erase animation for nav labels // erases the nav labels
// also terrible but consistent with the above // just as terrible as the typing but matches
function eraselabel(label) { function eraselabel(label) {
if (label.getAttribute("data-animating") === "true") { if (label.getAttribute("data-animating") === "true") {
const existingInterval = label.getAttribute("data-animation-interval"); const existingInterval = label.getAttribute("data-animation-interval");
@ -68,8 +68,8 @@ function eraselabel(label) {
label.setAttribute("data-animation-interval", eraseInterval); label.setAttribute("data-animation-interval", eraseInterval);
} }
// time display updater // updates the time display
// still updates way too frequently but whatever // probably updates too much but eh
function updateTime() { function updateTime() {
const now = new Date(); const now = new Date();
const timeString = now const timeString = now
@ -87,7 +87,7 @@ function updateTime() {
document.getElementById("current-time").textContent = timeString; document.getElementById("current-time").textContent = timeString;
} }
// status helper functions // bunch of status helper functions for formatting and stuff
function calculateAverageUptime(services) { function calculateAverageUptime(services) {
if (!services || services.length === 0) return 0; if (!services || services.length === 0) return 0;
const totalUptime = services.reduce( const totalUptime = services.reduce(
@ -115,8 +115,8 @@ function getGroupName(groupId) {
return GROUP_NAMES[groupId] || `GROUP ${groupId}`; return GROUP_NAMES[groupId] || `GROUP ${groupId}`;
} }
// creates the HTML for the status page // builds all the html for status page
// groups services by their group_id // groups everything by group_id cause organization
function createStatusHTML(services) { function createStatusHTML(services) {
const groups = services.reduce((acc, service) => { const groups = services.reduce((acc, service) => {
const groupId = service.group_id; const groupId = service.group_id;
@ -128,33 +128,34 @@ function createStatusHTML(services) {
return Object.entries(groups) return Object.entries(groups)
.map( .map(
([groupId, groupServices]) => ` ([groupId, groupServices]) => `
<div class="status-group"> <div class="status-group">
<div class="subsection-title">${getGroupName(parseInt(groupId))}</div> <div class="subsection-title">${getGroupName(parseInt(groupId))}</div>
${groupServices ${groupServices
.map( .map(
(service) => ` (service) => `
<div class="status-item"> <div class="status-item">
<div class="entry" data-service="${service.permalink}"> <div class="entry" data-service="${service.permalink}">
<span class="status-indicator ${getStatusClass(service)}"></span> <span class="status-indicator ${getStatusClass(service)}"></span>
<span class="service-name">${service.name.toUpperCase()}</span> <span class="service-name">${service.name.toUpperCase()}</span>
<span class="service-status">${service.online ? "OPERATIONAL" : "OFFLINE"}</span> <span class="service-status">${service.online ? "OPERATIONAL" : "OFFLINE"}</span>
</div>
<div class="status-details">
<div class="status-metric">Latency: ${formatLatency(service.latency)}ms</div>
<div class="status-metric">Uptime 24h: ${formatUptime(service.online_24_hours)}%</div>
<div class="status-metric">7-day Uptime: ${formatUptime(service.online_7_days)}%</div>
</div>
</div> </div>
`, <div class="status-details">
) <div class="status-metric">Latency: ${formatLatency(service.latency)}ms</div>
.join("")} <div class="status-metric">Uptime 24h: ${formatUptime(service.online_24_hours)}%</div>
</div> <div class="status-metric">7-day Uptime: ${formatUptime(service.online_7_days)}%</div>
`, </div>
</div>
`,
)
.join("")}
</div>
`,
) )
.join(""); .join("");
} }
// main status update function // main status updater
// fetches and displays all service statuses
function updateStatus() { function updateStatus() {
const statusContainer = document.getElementById("status-container"); const statusContainer = document.getElementById("status-container");
const averageUptimeElement = document.getElementById("average-uptime"); const averageUptimeElement = document.getElementById("average-uptime");
@ -176,9 +177,7 @@ function updateStatus() {
.catch((error) => { .catch((error) => {
statusContainer.innerHTML = ` statusContainer.innerHTML = `
<div class="error-message"> <div class="error-message">
a(42, 90, 90, 0.3), 0 0 40px rgba(42, 90, 90, 0.2); } to { text-shadow: 0 0 40px rgba(42, 90, 90, 0.5), 0 0 80px rgba(42, 90, 90, 0.3); } }" UNABLE TO FETCH STATUS DATA
);
}); UNABLE TO FETCH STATUS DATA
<div style="font-size: 0.8em; margin-top: 5px;"> <div style="font-size: 0.8em; margin-top: 5px;">
${error.message} ${error.message}
</div> </div>
@ -188,13 +187,13 @@ function updateStatus() {
}); });
} }
// project expansion handlers // handles expanding/collapsing project items
// closes others when opening new one
document.querySelectorAll(".project-item").forEach((item) => { document.querySelectorAll(".project-item").forEach((item) => {
item.addEventListener("click", function () { item.addEventListener("click", function () {
const content = this.querySelector(".project-content"); const content = this.querySelector(".project-content");
const icon = this.querySelector(".expand-icon"); const icon = this.querySelector(".expand-icon");
// close other expanded items
document.querySelectorAll(".project-item").forEach((otherItem) => { document.querySelectorAll(".project-item").forEach((otherItem) => {
if (otherItem !== item) { if (otherItem !== item) {
otherItem otherItem
@ -209,7 +208,8 @@ document.querySelectorAll(".project-item").forEach((item) => {
}); });
}); });
// smooth scroll navigation // smooth scrolls to sections when clicking nav
// better than jumping around
document.querySelectorAll('a[href^="#"]').forEach((anchor) => { document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener("click", function (e) { anchor.addEventListener("click", function (e) {
e.preventDefault(); e.preventDefault();
@ -219,7 +219,8 @@ document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
}); });
}); });
// active nav icon updater // handles active nav icon updates on scroll
// shows which section youre looking at
window.addEventListener("scroll", () => { window.addEventListener("scroll", () => {
let current = ""; let current = "";
document.querySelectorAll("section").forEach((section) => { document.querySelectorAll("section").forEach((section) => {
@ -234,34 +235,26 @@ window.addEventListener("scroll", () => {
const isCurrentSection = icon.getAttribute("href") === `#${current}`; const isCurrentSection = icon.getAttribute("href") === `#${current}`;
const wasActive = icon.classList.contains("active"); const wasActive = icon.classList.contains("active");
if (isCurrentSection) { if (isCurrentSection && !wasActive) {
if (!wasActive) { icon.classList.add("active");
icon.classList.add("active"); label.style.opacity = "1";
if (icon.isAnimating) { if (!icon.isAnimating && !icon.hoverAnimationDone) {
const text = label.getAttribute("data-text") || label.textContent; writeoutnavlabel(label);
label.textContent = text;
label.setAttribute("data-animating", "false");
clearInterval(
parseInt(label.getAttribute("data-animation-interval")),
);
}
if (!icon.hoverAnimationDone) {
writeoutnavlabel(label);
}
icon.hoverAnimationDone = true; icon.hoverAnimationDone = true;
} }
} else { } else if (!isCurrentSection && wasActive) {
if (wasActive) { icon.classList.remove("active");
if (!icon.isAnimating) {
eraselabel(label); eraselabel(label);
icon.classList.remove("active");
icon.hoverAnimationDone = false;
icon.isAnimating = false; icon.isAnimating = false;
icon.hoverAnimationDone = false;
} }
} }
}); });
}); });
// nav icon hover animations // nav icon hover stuff
// does the typing animation when hovering
document.querySelectorAll(".nav-icon").forEach((icon) => { document.querySelectorAll(".nav-icon").forEach((icon) => {
icon.hoverAnimationDone = false; icon.hoverAnimationDone = false;
icon.isAnimating = false; icon.isAnimating = false;
@ -285,35 +278,26 @@ document.querySelectorAll(".nav-icon").forEach((icon) => {
icon.addEventListener("click", () => { icon.addEventListener("click", () => {
const label = icon.querySelector(".nav-label"); const label = icon.querySelector(".nav-label");
if (icon.isAnimating) {
icon.hoverAnimationDone = true;
} else if (!icon.hoverAnimationDone) {
writeoutnavlabel(label);
icon.isAnimating = true;
icon.hoverAnimationDone = true;
}
label.style.opacity = "1"; label.style.opacity = "1";
}); });
}); });
// initialization // sets everything up when page loads
// starts all the intervals and stuff
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
// start time updates
updateTime(); updateTime();
setInterval(updateTime, TIME_UPDATE_INTERVAL); setInterval(updateTime, TIME_UPDATE_INTERVAL);
// start status updates
updateStatus(); updateStatus();
setInterval(updateStatus, STATUS_UPDATE_INTERVAL); setInterval(updateStatus, STATUS_UPDATE_INTERVAL);
// init active nav icon
const activeNavIcon = document.querySelector(".nav-icon.active"); const activeNavIcon = document.querySelector(".nav-icon.active");
if (activeNavIcon) { if (activeNavIcon) {
const label = activeNavIcon.querySelector(".nav-label"); const label = activeNavIcon.querySelector(".nav-label");
if (label) writeoutnavlabel(label); if (label) writeoutnavlabel(label);
} }
// fancy console log because why not // fancy console log for style points
console.log( console.log(
"%cELIA.NETWORK", "%cELIA.NETWORK",
"color: #2a5a5a; font-size: 24px; font-weight: bold; text-shadow: 2px 2px 4px rgba(42, 90, 90, 0.3);", "color: #2a5a5a; font-size: 24px; font-weight: bold; text-shadow: 2px 2px 4px rgba(42, 90, 90, 0.3);",