Отладка css

This commit is contained in:
Maxim
2026-05-01 09:00:11 +03:00
parent e2fb7409e4
commit 049572a2d5
5 changed files with 270 additions and 125 deletions

View File

@@ -51,12 +51,22 @@ func (a *API) HandleLatest(w http.ResponseWriter, r *http.Request) {
})
}
func (a *API) HandleHistory(w http.ResponseWriter, r *http.Request) {
raw := a.buf.GetLast(100)
out := make([]int, len(raw))
for i, v := range raw {
out[i] = int(v)
}
json.NewEncoder(w).Encode(map[string]interface{}{
"bytes": a.buf.GetLast(100),
"bytes": out,
})
}
// === FIFO READER ===
func startPipeReader(ctx context.Context, buf *adapter.RingBuffer, path string) {
go func() {
@@ -119,19 +129,23 @@ func main() {
buf: buf,
startTime: time.Now(),
}
fs := http.FileServer(http.Dir("/home/user/temp/golang/web"))
http.Handle("/api/", http.StripPrefix("/api", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/latest":
cors(api.HandleLatest)(w, r)
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/latest":
cors(api.HandleLatest)(w, r)
case "/history":
cors(api.HandleHistory)(w, r)
case "/health":
cors(api.HandleHealth)(w, r)
}
default:
http.Error(w, "not found", 404)
}
})))
http.Handle("/", fs)
http.Handle("/", http.FileServer(http.Dir("/home/user/temp/golang/web")))
log.Println("server :8080")
log.Fatal(http.ListenAndServe(":8080", nil))

151
web/css/style.css Normal file
View File

@@ -0,0 +1,151 @@
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: monospace;
background: #050805;
color: #00ff88;
padding: 12px;
}
h1 {
text-align: center;
font-size: 22px;
margin: 0 0 15px;
}
/* ===== GRID ===== */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
}
/* Desktop */
@media (min-width: 900px) {
.grid {
grid-template-columns: 1fr 1fr;
}
.wide {
grid-column: span 2;
}
}
/* ===== CARD ===== */
.card {
border: 1px solid #00ff88;
border-radius: 10px;
padding: 14px;
background: rgba(0,255,136,0.05);
overflow: hidden;
}
.card h3 {
margin: 0 0 10px;
font-size: 18px;
}
/* ===== STATUS ===== */
#status {
font-size: 28px;
font-weight: bold;
margin-bottom: 8px;
}
#meta {
font-size: 14px;
opacity: 0.8;
word-break: break-word;
}
/* ===== LATEST ===== */
#latest {
font-size: 36px;
font-weight: bold;
margin-bottom: 12px;
}
/* ===== BITS ===== */
#bits {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.bit {
height: 52px;
border: 1px solid #00ff88;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
font-size: 22px;
font-weight: bold;
}
.bit.on {
background: #00ff88;
color: #000;
}
/* Tablet/Desktop */
@media (min-width: 700px) {
#bits {
grid-template-columns: repeat(8, 1fr);
}
}
/* ===== HISTORY ===== */
#history {
font-size: 13px;
line-height: 1.35;
max-height: 420px;
overflow-y: auto;
white-space: nowrap;
padding-right: 4px;
}
/* Desktop */
@media (min-width: 900px) {
#history {
font-size: 12px;
max-height: 520px;
}
}
/* ===== PHONE ===== */
@media (max-width: 500px) {
h1 {
font-size: 18px;
}
#status {
font-size: 22px;
}
#latest {
font-size: 30px;
}
.bit {
height: 44px;
font-size: 18px;
}
#history {
font-size: 16px;
line-height: 1.5;
max-height: 55vh;
}
}

38
web/dashboard.html Normal file
View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GPIO Dashboard</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1>GPIO REALTIME DASHBOARD</h1>
<div class="grid">
<div class="card">
<h3>STATUS</h3>
<div id="status">...</div>
<div id="meta"></div>
</div>
<div class="card">
<h3>LATEST SIGNAL</h3>
<div id="latest">--</div>
<div id="bits"></div>
</div>
<div class="card wide">
<h3>LIVE STREAM (last 32)</h3>
<div id="history"></div>
</div>
</div>
<script src="/js/app.js"></script>
</body>
</html>

View File

@@ -1,125 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GPIO Monitor Dashboard</title>
<style>
body {
font-family: monospace;
background: #0b0f0c;
color: #00ff88;
padding: 20px;
}
.card {
border: 1px solid #00ff88;
padding: 12px;
margin-bottom: 12px;
border-radius: 8px;
}
.status-ok { color: #00ff88; }
.status-bad { color: #ff4444; }
.bits {
display: flex;
gap: 8px;
margin-top: 10px;
}
.bit {
width: 40px;
height: 40px;
border: 1px solid #00ff88;
display: flex;
align-items: center;
justify-content: center;
}
.bit.on {
background: #00ff88;
color: black;
}
.small {
opacity: 0.7;
font-size: 12px;
}
</style>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0; url=/dashboard.html">
</head>
<body>
<h1>GPIO Monitor</h1>
<div class="card">
<div>PIPE STATUS: <span id="pipeStatus">...</span></div>
<div>DATA FLOW: <span id="dataFlow">...</span></div>
<div class="small" id="meta"></div>
</div>
<div class="card">
<div>LATEST BYTE: <span id="latest">--</span></div>
<div class="bits" id="bits"></div>
</div>
<div class="card">
<div>HISTORY (last 16 bytes)</div>
<div id="history"></div>
</div>
<script>
function renderBits(byte) {
const bits = document.getElementById("bits");
bits.innerHTML = "";
for (let i = 7; i >= 0; i--) {
const v = (byte >> i) & 1;
const div = document.createElement("div");
div.className = "bit" + (v ? " on" : "");
div.textContent = v;
bits.appendChild(div);
}
}
async function update() {
try {
const r = await fetch("/api/health");
const h = await r.json();
const pipeStatus = document.getElementById("pipeStatus");
const dataFlow = document.getElementById("dataFlow");
pipeStatus.textContent = h.status;
pipeStatus.className = h.status === "ok" ? "status-ok" : "status-bad";
dataFlow.textContent = h.last_data_ms + " ms idle";
document.getElementById("meta").textContent =
"uptime: " + Math.round(h.uptime_sec) + "s | filled: " + h.stats.filled;
const latest = h.latest;
document.getElementById("latest").textContent = latest;
renderBits(latest);
const r2 = await fetch("/api/history");
const hist = await r2.json();
document.getElementById("history").innerHTML =
hist.bytes.map(b => "0x" + b.toString(16).padStart(2,"0")).join(" ");
} catch(e) {
document.getElementById("pipeStatus").textContent = "SERVER DOWN";
}
}
setInterval(update, 500);
update();
</script>
</body>
</html>

58
web/js/app.js Normal file
View File

@@ -0,0 +1,58 @@
function renderBits(byte) {
const bits = document.getElementById("bits");
bits.innerHTML = "";
byte = Number(byte || 0);
for (let i = 7; i >= 0; i--) {
const v = (byte >> i) & 1;
const d = document.createElement("div");
d.className = "bit" + (v ? " on" : "");
d.textContent = v;
bits.appendChild(d);
}
}
async function update() {
try {
const r1 = await fetch("/api/health");
const r2 = await fetch("/api/history");
const h = await r1.json();
const hist = await r2.json();
console.log("health:", h);
console.log("history:", hist);
document.getElementById("status").textContent = h.status || "unknown";
const filled = h.stats?.filled ?? 0;
const uptime = Math.round(h.uptime_sec || 0);
document.getElementById("meta").textContent =
"uptime: " + uptime + "s | filled: " + filled;
const latest = Number(h.latest || 0);
document.getElementById("latest").textContent = latest;
renderBits(latest);
const arr = Array.isArray(hist.bytes) ? hist.bytes : [];
document.getElementById("history").innerHTML =
arr.map((b, i) =>
"[" + i + "] " +
(Number(b) & 15).toString(2).padStart(4, "0") +
" = " + (Number(b) & 15)
).join("<br>");
} catch (e) {
console.error("UPDATE ERROR:", e);
document.getElementById("status").textContent = "SERVER DOWN";
}
}
setInterval(update, 500);
update();