Fixed the edge case typing animation fail.
All checks were successful
Deploy / deploy (push) Successful in 17s
All checks were successful
Deploy / deploy (push) Successful in 17s
This commit is contained in:
parent
2746f73cff
commit
be069419ce
136
assets/index.js
136
assets/index.js
@ -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);",
|
||||||
|
Loading…
Reference in New Issue
Block a user