🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
{% extends "base.html" %}{% block title %}PaganOS – {{ t('status_title') }}{% endblock %}
{% block content %}
<div class="section-title"><span class="icon"></span> {{ t('status_title') }}</div>
<div class="stats" id="live-stats">
<div class="stat"><div class="stat-val" id="s-total">{{ data.total }}</div><div class="stat-label">{{ t('status_builds') }}</div></div>
<div class="stat"><div class="stat-val" id="s-ok" style="color:#3fb950">{{ data.ok }}</div><div class="stat-label">✅ {{ t('status_ok') }}</div></div>
<div class="stat"><div class="stat-val" id="s-fail" style="color:var(--red)">{{ data.fail }}</div><div class="stat-label">❌ {{ t('status_fail') }}</div></div>
<div class="stat"><div class="stat-val" id="s-current">{% if data.current %}{% else %}-{% endif %}</div><div class="stat-label">{{ t('status_current') }}</div></div>
</div>
{% if data.current %}
<div class="card" style="border-color:var(--accent);margin-bottom:1rem">
<div class="card-header"><h2> {{ data.current.name }}-{{ data.current.version }}</h2><span class="badge badge-info">{{ data.current.category }} · {{ data.current.get('progress','') }}</span></div>
<p class="text-muted">{{ data.current.get('step_text','') }}</p>
</div>
{% endif %}
<div class="card" style="margin-bottom:1rem">
<div class="card-header"><h2>Serwer i usługi</h2><span class="badge badge-info" id="svc-live" style="font-weight:400;text-transform:none">live · odświeżanie 15 s</span></div>
<div class="stats" style="grid-template-columns:repeat(auto-fit,minmax(150px,1fr));margin-bottom:1rem">
<div class="stat"><div class="stat-val" id="sv-uptime" style="font-size:1.35rem">…</div><div class="stat-label">Uptime</div></div>
<div class="stat"><div class="stat-val" id="sv-load" style="font-size:1.05rem">…</div><div class="stat-label">Load 1/5/15</div></div>
<div class="stat"><div class="stat-val" id="sv-ram" style="font-size:1.05rem">…</div><div class="stat-label">RAM</div></div>
<div class="stat"><div class="stat-val" id="sv-disk" style="font-size:1.05rem">…</div><div class="stat-label">Dysk</div></div>
</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1.25rem">
<div>
<h3 style="font-size:0.78rem;text-transform:uppercase;letter-spacing:0.06em;color:var(--muted);margin:0 0 0.6rem">Usługi</h3>
<div id="svc-box" style="display:flex;flex-wrap:wrap;gap:0.4rem"><span class="text-muted">sprawdzam…</span></div>
</div>
<div>
<h3 style="font-size:0.78rem;text-transform:uppercase;letter-spacing:0.06em;color:var(--muted);margin:0 0 0.6rem">Dostępność serwisów</h3>
<div id="chk-box" style="font-size:0.82rem"><span class="text-muted">sprawdzam…</span></div>
</div>
</div>
</div>
<div class="card">
<div class="card-header"><h2> {{ t('status_changes') }}</h2></div>
{% if data.changes %}
<table class="table"><thead><tr><th>Opis</th><th>Autor</th><th>Kiedy</th></tr></thead><tbody>
{% for c in data.changes %}
<tr>
<td><a href="https://git.paganlinux.eu/recipes.git" style="color:inherit;text-decoration:none"><strong>{{ c.subject[:80] }}</strong></a></td>
<td>{{ c.author }}</td>
<td style="white-space:nowrap;color:var(--muted);font-size:0.8rem">{{ c.when }}</td>
</tr>
{% endfor %}
</tbody></table>
{% else %}
<p class="text-muted" style="padding:1rem;text-align:center">{{ t('status_no_changes') }}</p>
{% endif %}
</div>
<p class="text-muted" style="text-align:center;padding:1rem 0 0;font-size:0.8rem">{{ t('status_auto') }}</p>
<script>
(function(){
function refresh(){
fetch('/api/status-live')
.then(function(r){return r.json();})
.then(function(d){
var set=function(id,v){var el=document.getElementById(id); if(el) el.textContent=v;};
set('s-total', d.total); set('s-ok', d.ok); set('s-fail', d.fail);
set('s-current', d.current? '' : '-');
})
.catch(function(){});
}
function refreshServer(){
fetch('/api/server-status')
.then(function(r){return r.json();})
.then(function(d){
var set=function(id,v){var el=document.getElementById(id); if(el) el.textContent=v;};
var s=d.server||{};
set('sv-uptime', s.uptime||'?');
set('sv-load', (s.load||['?']).join(' / '));
set('sv-ram', s.ram_pct!=null ? s.ram_pct+'% ('+s.ram_total_gb+' GB)' : '?');
set('sv-disk', s.disk_pct!=null ? s.disk_pct+'% (wolne '+s.disk_free_gb+' GB)' : '?');
var svc=document.getElementById('svc-box');
if(svc){
svc.innerHTML=(s.services||[]).map(function(x){
return '<span class="chip '+(x.ok?'chip-ok':'chip-err')+'" title="'+(x.ok?'działa':'nieaktywna')+'">'+x.name+'</span>';
}).join('') || '<span class="text-muted">brak danych</span>';
}
var cb=document.getElementById('chk-box');
if(cb){
var rows=(d.checks||[]).map(function(c){
var badge=c.ok? '<span class="badge badge-ok">OK</span>' : '<span class="badge badge-fail">FAIL</span>';
return '<div style="display:flex;gap:0.7rem;align-items:center;padding:0.3rem 0;border-bottom:1px solid var(--border)">'
+'<span style="flex:1">'+c.name+'</span>'+badge
+'<span class="text-muted" style="width:2.6rem;text-align:right">'+(c.code||'—')+'</span>'
+'<span class="text-muted" style="width:4.5rem;text-align:right">'+c.ms+' ms</span></div>';
}).join('');
cb.innerHTML= rows || '<span class="text-muted">brak danych</span>';
}
})
.catch(function(){ var b=document.getElementById('svc-live'); if(b) b.textContent='błąd odczytu'; });
}
setInterval(refresh, 10000);
refreshServer();
setInterval(refreshServer, 15000);
})();
</script>
{% endblock %}