Initial commit

This commit is contained in:
elijah 2024-10-27 13:46:56 +01:00
commit 1a1d318d74
3 changed files with 725 additions and 0 deletions

380
assets/index.css Normal file
View File

@ -0,0 +1,380 @@
html {
scroll-snap-type: y mandatory;
scroll-behavior: smooth;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
body {
background: #0a0a0a;
color: #c5e5e5;
font-family: "Courier New", monospace;
margin: 0;
padding: 0;
min-height: 100vh;
}
.terminal {
margin-left: 80px;
padding: 20px;
max-width: 800px;
}
.sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 80px;
background: #0a0a0a;
border-right: 1px solid #2a5a5a;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 20px;
z-index: 1000;
}
.nav-icon {
color: rgba(255, 255, 255, 0.4);
cursor: pointer;
margin: 20px 0;
font-size: 24px;
transition: color 0.3s ease;
text-decoration: none;
}
.nav-icon:hover {
color: rgba(255, 255, 255, 0.85);
}
.nav-icon.active {
color: rgba(255, 255, 255, 1);
}
/* Section Styles */
.section {
height: 100vh;
padding: 20px 0;
scroll-snap-align: start;
scroll-snap-stop: always;
position: relative;
overflow-y: auto;
}
#contact {
height: auto;
min-height: 100vh;
}
/* Header Styles */
.header {
border-bottom: 1px solid #2a5a5a;
padding-bottom: 10px;
margin-bottom: 20px;
}
.timestamp {
font-size: 0.9em;
color: #88aaaa;
}
.location {
margin-top: 4px;
color: #88aaaa;
}
.section-title {
color: #88aaaa;
margin-bottom: 20px;
font-size: 1.2em;
display: flex;
align-items: center;
}
.section-title::before {
content: "◈";
margin-right: 10px;
font-size: 1.1em;
}
.project-item {
border: 1px solid #2a5a5a;
padding: 15px;
margin: 15px 0;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
background: rgba(42, 90, 90, 0.05);
}
.project-item:hover {
border-color: #c5e5e5;
background: rgba(42, 90, 90, 0.1);
}
.project-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.project-header .entry::before {
content: "⎔";
color: #88aaaa;
}
.expand-icon {
color: #88aaaa;
transition: transform 0.3s ease;
}
.project-item.expanded .expand-icon {
transform: rotate(45deg);
}
.project-content {
max-height: 0;
overflow: hidden;
transition:
max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s ease,
transform 0.3s ease;
margin-top: 10px;
opacity: 0;
transform: translateY(-10px);
}
.project-content.expanded {
max-height: 500px;
opacity: 1;
transform: translateY(0);
}
.status-item {
margin: 10px 0;
transition: all 0.3s ease;
}
.status-indicator {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 10px;
transition: transform 0.3s ease;
}
.status-item:hover .status-indicator {
transform: scale(1.2);
}
.status-online {
background-color: #4caf50;
box-shadow: 0 0 10px rgba(76, 175, 80, 0.3);
}
.status-offline {
background-color: #f44336;
box-shadow: 0 0 10px rgba(244, 67, 54, 0.3);
}
.status-warning {
background-color: #ff9800;
box-shadow: 0 0 10px rgba(255, 152, 0, 0.3);
}
.status-details {
margin-left: 18px;
color: #88aaaa;
font-size: 0.9em;
max-height: 0;
overflow: hidden;
opacity: 0;
transform: translateY(-10px);
transition:
max-height 0.3s ease-out,
opacity 0.3s ease,
transform 0.3s ease;
}
.status-details.expanded {
max-height: 500px;
opacity: 1;
transform: translateY(0);
margin-top: 5px;
}
.status-metric {
margin: 4px 0;
padding-left: 15px;
position: relative;
}
.status-metric::before {
content: "";
position: absolute;
left: 0;
color: #88aaaa;
}
.loading-indicator {
color: #88aaaa;
text-align: center;
padding: 20px;
}
.error-message {
color: #f44336;
text-align: center;
padding: 20px;
}
.refresh-button {
color: #88aaaa;
border: 1px solid #2a5a5a;
background: none;
padding: 8px 16px;
cursor: pointer;
margin-bottom: 20px;
transition: all 0.3s ease;
display: flex;
align-items: center;
}
.refresh-button::before {
content: "⟳";
margin-right: 8px;
}
.refresh-button:hover {
border-color: #c5e5e5;
color: #c5e5e5;
transform: scale(1.02);
}
/* Entry and Link Styles */
.entry-list {
margin-top: 10px;
}
.nested-entries {
margin-left: 20px;
margin-top: 5px;
}
.entry {
margin: 10px 0;
padding-left: 20px;
position: relative;
}
.entry::before {
content: "▹";
color: #88aaaa;
position: absolute;
left: 0;
margin-right: 10px;
}
.entry-link {
color: inherit;
text-decoration: none;
transition: color 0.3s ease;
}
.entry-link:hover {
color: #c5e5e5;
}
/* Contact Styles */
.contact-links {
display: flex;
flex-direction: column;
gap: 20px;
margin-top: 20px;
}
.contact-link {
display: flex;
align-items: center;
color: #c5e5e5;
text-decoration: none;
padding: 15px;
border: 1px solid #2a5a5a;
transition: all 0.3s ease;
background: rgba(42, 90, 90, 0.05);
}
.contact-link:hover {
border-color: #c5e5e5;
background: rgba(42, 90, 90, 0.1);
transform: translateX(5px);
}
.contact-icon {
margin-right: 15px;
font-size: 24px;
}
.nested-entries {
margin-left: 20px;
margin-top: 5px;
}
.nested-entries .entry {
color: #88aaaa;
font-size: 0.95em;
}
.entry {
margin: 10px 0;
padding-left: 20px;
position: relative;
}
.entry::before {
content: "▹";
color: #88aaaa;
position: absolute;
left: 0;
margin-right: 10px;
}
.entry-link {
color: inherit;
text-decoration: none;
transition: color 0.3s ease;
}
.entry-link:hover {
color: #c5e5e5;
}
.nested-entries .entry {
color: #88aaaa;
}
.nested-entries .entry:hover {
color: #c5e5e5;
}
.entry {
margin: 10px 0;
padding-left: 20px;
position: relative;
}
.entry::before {
content: "▹";
color: #88aaaa;
position: absolute;
left: 0;
margin-right: 10px;
}
.nested-entries .entry:hover::before {
color: #c5e5e5;
}

171
assets/index.js Normal file
View File

@ -0,0 +1,171 @@
function updateTime() {
const now = new Date();
const timeString = now
.toLocaleString("en-US", {
month: "2-digit",
day: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
fractionalSecondDigits: 3,
hour12: true,
})
.toUpperCase();
document.getElementById("current-time").textContent = timeString;
}
updateTime();
setInterval(updateTime, 1);
// projects
const projectItems = document.querySelectorAll(".project-item");
projectItems.forEach((item) => {
item.addEventListener("click", function () {
const content = this.querySelector(".project-content");
const icon = this.querySelector(".expand-icon");
// close other expanded items
projectItems.forEach((otherItem) => {
if (otherItem !== item) {
otherItem
.querySelector(".project-content")
.classList.remove("expanded");
otherItem.querySelector(".expand-icon").textContent = "+";
}
});
content.classList.toggle("expanded");
icon.textContent = content.classList.contains("expanded") ? "" : "+";
});
});
// status updater
function formatLatency(latency) {
return (Math.round((latency / 1000) * 10) / 10).toFixed(1);
}
function formatUptime(uptime) {
return uptime.toFixed(2);
}
function getStatusClass(service) {
if (!service.online) return "status-offline";
if (service.latency > 500000) return "status-warning";
return "status-online";
}
function getGroupName(groupId) {
const groupNames = {
4: "INFRASTRUCTURE",
5: "SERVICES",
6: "API",
};
return groupNames[groupId] || `GROUP ${groupId}`;
}
function createStatusHTML(services) {
// Group services by group_id
const groups = services.reduce((acc, service) => {
const groupId = service.group_id;
if (!acc[groupId]) acc[groupId] = [];
acc[groupId].push(service);
return acc;
}, {});
return Object.entries(groups)
.map(
([groupId, groupServices]) => `
<div class="status-group">
<div class="subsection-title">${getGroupName(parseInt(groupId))}</div>
${groupServices
.map(
(service) => `
<div class="status-item">
<div class="entry" data-service="${service.permalink}">
<span class="status-indicator ${getStatusClass(service)}"></span>
<span class="service-name">${service.name.toUpperCase()}</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>
`,
)
.join("")}
</div>
`,
)
.join("");
}
function updateStatus() {
const statusContainer = document.getElementById("status-container");
fetch("https://status.elia.network/api/services")
.then((response) => response.json())
.then((data) => {
statusContainer.innerHTML = createStatusHTML(data);
document.querySelectorAll(".status-item .entry").forEach((item) => {
item.addEventListener("click", function () {
const details = this.nextElementSibling;
details.classList.toggle("expanded");
});
});
})
.catch((error) => {
statusContainer.innerHTML = `
<div class="error-message">
UNABLE TO FETCH STATUS DATA
<div style="font-size: 0.8em; margin-top: 5px;">
${error.message}
</div>
</div>
`;
});
}
// initial update
updateStatus();
// update every minute
setInterval(updateStatus, 60000);
// status details toggle
document.querySelectorAll(".status-item .entry").forEach((item) => {
const details = item.nextElementSibling;
if (details && details.classList.contains("status-details")) {
item.addEventListener("click", function () {
details.classList.toggle("expanded");
});
}
});
// navigation
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
document.querySelector(this.getAttribute("href")).scrollIntoView({
behavior: "smooth",
});
});
});
// update active nav icon
window.addEventListener("scroll", () => {
let current = "";
document.querySelectorAll("section").forEach((section) => {
const sectionTop = section.offsetTop;
if (scrollY >= sectionTop - 60) {
current = section.getAttribute("id");
}
});
document.querySelectorAll(".nav-icon").forEach((icon) => {
icon.classList.remove("active");
if (icon.getAttribute("href") === `#${current}`) {
icon.classList.add("active");
}
});
});

174
index.html Normal file
View File

@ -0,0 +1,174 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="assets/index.css" />
<meta charset="UTF-8" />
</head>
<body>
<nav class="sidebar">
<a href="#about" class="nav-icon"></a>
<a href="#projects" class="nav-icon"></a>
<a href="#status" class="nav-icon"></a>
<a href="#contact" class="nav-icon"></a>
</nav>
<div class="terminal">
<section id="about" class="section">
<div class="header">
<div class="timestamp" id="current-time"></div>
<div class="location">ZÜRICH, SWITZERLAND</div>
</div>
<div class="section-title">ELIA.NETWORK</div>
<div class="entry-list">
<div class="entry">
WHAT WE DO
<div class="nested-entries">
<div class="entry">
<a
href="https://status.elia.network"
class="entry-link"
>NETWORK INFRASTRUCTURE</a
>
</div>
<div class="entry">
<a
href="https://huggingface.co/informatiker"
class="entry-link"
>RESEARCH</a
>
</div>
</div>
</div>
<div class="entry">
SERVICES
<div class="nested-entries">
<div class="entry">
<a
href="https://media.elia.services"
class="entry-link"
>MEDIA</a
>
</div>
<div class="entry">
<a
href="https://docs.elia.network"
class="entry-link"
>DOCS</a
>
</div>
<div class="entry">
<a
href="https://chat.elia.services"
class="entry-link"
>CHAT</a
>
</div>
</div>
</div>
</div>
</section>
<section id="projects" class="section">
<div class="section-title">PROJECTS</div>
<div class="project-item" onclick="toggleProject(this)">
<div class="project-header">
<div class="entry">CAS</div>
<span class="expand-icon">+</span>
</div>
<div class="project-content">
<p>
Open-Source Language Model interface for use in web
browsers. If ykyk.
</p>
<div class="project-links">
<a
href="https://git.elia.network/elia/cas/"
class="project-link"
>⎔ GIT →</a
>
</div>
</div>
</div>
<div class="project-item" onclick="toggleProject(this)">
<div class="project-header">
<div class="entry">NETWORK</div>
<span class="expand-icon">+</span>
</div>
<div class="project-content">
<p>Infrastructure and networking solutions.</p>
<div class="project-links">
<a href="#" class="project-link">⎮ DOCS →</a>
<a href="#" class="project-link">⎔ STATUS →</a>
</div>
</div>
</div>
</section>
<section id="status" class="section">
<div class="section-title">SYSTEM STATUS</div>
<div id="status-container" class="status-grid">
<div class="status-group">
<div class="status-item" onclick="toggleStatus(this)">
<span class="status-indicator status-online"></span>
<span class="service-name">MEDIA SERVER</span>
<div class="status-details">
<div class="status-metric">Uptime: 99.99%</div>
<div class="status-metric">
Response Time: 120ms
</div>
<div class="status-metric">Load: Normal</div>
</div>
</div>
<div class="status-item" onclick="toggleStatus(this)">
<span
class="status-indicator status-warning"
></span>
<span class="service-name">CHAT SERVICE</span>
<div class="status-details">
<div class="status-metric">Uptime: 98.5%</div>
<div class="status-metric">
Response Time: 350ms
</div>
<div class="status-metric">Load: High</div>
</div>
</div>
<div class="status-item" onclick="toggleStatus(this)">
<span class="status-indicator status-online"></span>
<span class="service-name">DOCUMENTATION</span>
<div class="status-details">
<div class="status-metric">Uptime: 100%</div>
<div class="status-metric">
Response Time: 89ms
</div>
<div class="status-metric">Load: Low</div>
</div>
</div>
</div>
</div>
</section>
<section id="contact" class="section">
<div class="section-title">CONTACT</div>
<div class="contact-links">
<a href="mailto:contact@elia.network" class="contact-link">
<span class="contact-icon"></span>
admin@elia.network
</a>
<a
href="https://github.com/informaticker"
class="contact-link"
>
<span class="contact-icon"></span>
github.com/informaticker
</a>
</div>
</section>
</div>
<script src="assets/index.js"></script>
</body>
</html>