Files
micalis.net/index.html
T
2026-07-26 13:37:20 +02:00

406 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MicalLab - HomeLab Server</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%);
min-height: 100vh;
color: #e4e4e7;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
/* Header */
.header {
text-align: center;
padding: 3rem 0;
margin-bottom: 2rem;
}
.logo {
font-size: 3.5rem;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.5rem;
text-shadow: 0 0 40px rgba(102, 126, 234, 0.3);
}
.subtitle {
font-size: 1.2rem;
color: #94a3b8;
font-weight: 300;
letter-spacing: 2px;
text-transform: uppercase;
}
/* Status indicator */
.status {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
margin-top: 1.5rem;
}
.status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
animation: pulse 2s infinite;
}
.status-dot.loading {
background: #f59e0b;
box-shadow: 0 0 10px #f59e0b;
}
.status-dot.online {
background: #22c55e;
box-shadow: 0 0 10px #22c55e;
}
.status-dot.offline {
background: #ef4444;
box-shadow: 0 0 10px #ef4444;
}
.status-dot.partial {
background: #f59e0b;
box-shadow: 0 0 10px #f59e0b;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.status-text {
font-size: 0.9rem;
font-weight: 500;
}
.status-text.loading { color: #f59e0b; }
.status-text.online { color: #22c55e; }
.status-text.offline { color: #ef4444; }
.status-text.partial { color: #f59e0b; }
/* Services Grid */
.services-title {
text-align: center;
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 2rem;
color: #cbd5e1;
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 3rem;
}
.service-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px;
padding: 2rem;
text-decoration: none;
color: inherit;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.service-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--card-accent);
opacity: 0;
transition: opacity 0.3s ease;
}
.service-card:hover {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.15);
transform: translateY(-4px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
.service-card:hover::before {
opacity: 1;
}
.service-icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.service-name {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #f1f5f9;
display: flex;
align-items: center;
gap: 0.5rem;
}
.service-desc {
font-size: 0.9rem;
color: #94a3b8;
line-height: 1.6;
}
.service-tag {
display: inline-block;
margin-top: 1rem;
padding: 0.25rem 0.75rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 20px;
font-size: 0.75rem;
color: #64748b;
text-transform: uppercase;
letter-spacing: 1px;
}
/* Service status indicator */
.service-status {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.2rem 0.5rem;
border-radius: 12px;
font-size: 0.7rem;
font-weight: 500;
text-transform: uppercase;
}
.service-status.online {
background: rgba(34, 197, 94, 0.15);
color: #22c55e;
}
.service-status.offline {
background: rgba(239, 68, 68, 0.15);
color: #ef4444;
}
.service-status.checking {
background: rgba(245, 158, 11, 0.15);
color: #f59e0b;
}
.service-status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
animation: pulse 2s infinite;
}
.service-status.online .service-status-dot { background: #22c55e; }
.service-status.offline .service-status-dot { background: #ef4444; }
.service-status.checking .service-status-dot { background: #f59e0b; }
/* Card accent colors */
.service-card.gitea { --card-accent: linear-gradient(90deg, #609930, #79b930); }
.service-card.nextcloud { --card-accent: linear-gradient(90deg, #0082c9, #1d4c6c); }
.service-card.aichat { --card-accent: linear-gradient(90deg, #8b5cf6, #d946ef); }
.service-card.jellyfin { --card-accent: linear-gradient(90deg, #00a4dc, #aa5cc3); }
.service-card.amp { --card-accent: linear-gradient(90deg, #f59e0b, #ef4444); }
/* Footer */
.footer {
text-align: center;
padding: 2rem 0;
border-top: 1px solid rgba(255, 255, 255, 0.05);
color: #64748b;
font-size: 0.85rem;
}
.footer a {
color: #667eea;
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
/* Responsive */
@media (max-width: 768px) {
.logo {
font-size: 2.5rem;
}
.container {
padding: 1rem;
}
.services-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<header class="header">
<h1 class="logo">MicalLab</h1>
<p class="subtitle">Personal HomeLab Server</p>
<div class="status">
<span class="status-dot loading" id="statusDot"></span>
<span class="status-text loading" id="statusText">Kontroluji stav služeb...</span>
</div>
</header>
<h2 class="services-title">🏠 Služby</h2>
<div class="services-grid">
<a href="https://gitea.micalis.cloud/" class="service-card gitea" data-service="gitea">
<div class="service-icon">🔨</div>
<h3 class="service-name">
Gitea
<span class="service-status checking" id="status-gitea"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Self-hosted Git služba pro správu repozitářů a verzování projektů.</p>
<span class="service-tag">Git & Code</span>
</a>
<a href="https://nextcloud.micalis.cloud/" class="service-card nextcloud" data-service="nextcloud">
<div class="service-icon">☁️</div>
<h3 class="service-name">
Nextcloud
<span class="service-status checking" id="status-nextcloud"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Osobní cloud pro ukládání souborů, sdílení dat a kolaboraci.</p>
<span class="service-tag">Cloud Storage</span>
</a>
<a href="https://ai.micalis.cloud/" class="service-card aichat" data-service="aichat">
<div class="service-icon">🤖</div>
<h3 class="service-name">
AI Chat
<span class="service-status checking" id="status-aichat"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Lokální AI asistent pro konverzace a generování obsahu.</p>
<span class="service-tag">Artificial Intelligence</span>
</a>
<a href="https://jellyfin.micalis.cloud/" class="service-card jellyfin" data-service="jellyfin">
<div class="service-icon">🎬</div>
<h3 class="service-name">
Jellyfin
<span class="service-status checking" id="status-jellyfin"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Mediální server pro streamování filmů, seriálů a hudby.</p>
<span class="service-tag">Media Streaming</span>
</a>
<a href="https://amp.micalis.cloud/" class="service-card amp" data-service="amp">
<div class="service-icon">🎮</div>
<h3 class="service-name">
AMP Game Panel
<span class="service-status checking" id="status-amp"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Správa herních serverů a aplikací přehledným panel.</p>
<span class="service-tag">Game Servers</span>
</a>
<a href="https://grafana.micalis.cloud/" class="service-card grafana" data-service="grafana">
<div class="service-icon">✉️</div>
<h3 class="service-name">
Grafana
<span class="service-status checking" id="status-grafana"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Monitorovací služba interních serverů.</p>
<span class="service-tag">Infrastructure</span>
</a>
<a href="https://matrix.micalis.cloud/" class="service-card matrix" data-service="matrix">
<div class="service-icon">💬</div>
<h3 class="service-name">
Matrix
<span class="service-status checking" id="status-matrix"><span class="service-status-dot"></span> kontrola</span>
</h3>
<p class="service-desc">Backend pro chatování a volání.</p>
<span class="service-tag">Social Media</span>
</a>
</div>
<footer class="footer">
<p>© 2026 MicalLab Selfhosted infrastructure </p>
</footer>
</div>
<script>
// Načti status ze serveru
async function loadStatus() {
const statusDot = document.getElementById('statusDot');
const statusText = document.getElementById('statusText');
try {
const response = await fetch('status.php');
const data = await response.json();
// Aktualizuj celkový status
const overall = data.overall;
statusDot.className = 'status-dot ' + (overall.status === 'all_online' ? 'online' : overall.status);
statusText.className = 'status-text ' + (overall.status === 'all_online' ? 'online' : overall.status);
if (overall.status === 'all_online') {
statusText.textContent = `Všechny služby běží (${overall.online}/${overall.total})`;
} else if (overall.status === 'partial') {
statusText.textContent = `Částečně dostupné (${overall.online}/${overall.total})`;
} else {
statusText.textContent = `Služby nedostupné (${overall.online}/${overall.total})`;
}
// Aktualizuj jednotlivé služby
data.services.forEach(service => {
const el = document.getElementById('status-' + service.id);
if (el) {
el.className = 'service-status ' + service.status;
el.innerHTML = `<span class="service-status-dot"></span> ${service.status === 'online' ? 'online' : 'offline'}`;
}
});
} catch (error) {
console.error('Chyba při načítání statusu:', error);
statusDot.className = 'status-dot offline';
statusText.className = 'status-text offline';
statusText.textContent = 'Nepodařilo se zjistit stav služeb';
}
}
// Načti status při startu
loadStatus();
// Obnov každých 60 sekund
setInterval(loadStatus, 60000);
</script>
</body>
</html>