191 lines
6.4 KiB
HTML
191 lines
6.4 KiB
HTML
<!doctype html>
|
|
<html lang="pl">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Podgląd WebSocket - gastro_serwer</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 20px; background:#f6f7fb; color:#222; }
|
|
h1 { margin: 0 0 8px; }
|
|
.muted { color:#666; font-size: 14px; }
|
|
.card { background:#fff; border:1px solid #ddd; border-radius:10px; padding:14px; margin-top:14px; }
|
|
.ok { color: #0a7a2f; font-weight: bold; }
|
|
.bad { color: #a11; font-weight: bold; }
|
|
table { width: 100%; border-collapse: collapse; margin-top: 8px; }
|
|
th, td { border: 1px solid #ddd; padding: 6px; font-size: 13px; text-align: left; }
|
|
th { background:#f1f4ff; }
|
|
pre { background:#111; color:#d7ffd7; border-radius:8px; padding:10px; max-height:280px; overflow:auto; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Podgląd danych z <code>gastro_serwer</code></h1>
|
|
<div class="muted">Strona łączy się z lokalnym serwerem (<code>/ws</code>), który pobiera dane z <code>wss://api.serwer.magico.pl/gastro_serwer</code>.</div>
|
|
|
|
<div class="card">
|
|
<div>Status połączenia: <span id="status" class="bad">rozłączono</span></div>
|
|
<div class="muted" id="lastEvent">Brak danych.</div>
|
|
<button id="refreshBtn" style="margin-top:10px;">Pobierz current bills (ręcznie)</button>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Ostatnia paczka <code>Type = "bills"</code></h3>
|
|
<div id="billsInfo" class="muted">Jeszcze nie odebrano danych.</div>
|
|
<table id="billsTable" style="display:none;">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Description</th>
|
|
<th>kierunek</th>
|
|
<th>type</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Ostatnia surowa wiadomość</h3>
|
|
<pre id="raw">(czekam...)</pre>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Debug: wyślij własny JSON do upstream</h3>
|
|
<div class="muted">Wklej dokładnie ramkę wysyłaną przez oryginalną aplikację (Network → WS → Messages).</div>
|
|
<textarea id="customPayload" style="width:100%;min-height:90px;margin-top:8px;">{"Type":"bills","kierunek":"all","type":"current"}</textarea>
|
|
<div style="margin-top:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
|
|
<button id="sendCustomBtn">Wyślij JSON</button>
|
|
<label><input type="checkbox" id="autoRefresh" /> auto co 5s</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Historia in/out (ostatnie 20)</h3>
|
|
<pre id="history">(brak)</pre>
|
|
</div>
|
|
|
|
<script>
|
|
const statusEl = document.getElementById("status");
|
|
const lastEventEl = document.getElementById("lastEvent");
|
|
const billsInfoEl = document.getElementById("billsInfo");
|
|
const billsTable = document.getElementById("billsTable");
|
|
const tbody = billsTable.querySelector("tbody");
|
|
const rawEl = document.getElementById("raw");
|
|
const refreshBtn = document.getElementById("refreshBtn");
|
|
const customPayloadEl = document.getElementById("customPayload");
|
|
const sendCustomBtn = document.getElementById("sendCustomBtn");
|
|
const autoRefreshEl = document.getElementById("autoRefresh");
|
|
const historyEl = document.getElementById("history");
|
|
|
|
const history = [];
|
|
let autoTimer = null;
|
|
|
|
function pushHistory(direction, payload) {
|
|
const line = `[${new Date().toLocaleTimeString()}] ${direction}: ${typeof payload === "string" ? payload : JSON.stringify(payload)}`;
|
|
history.unshift(line);
|
|
if (history.length > 20) history.length = 20;
|
|
historyEl.textContent = history.join("\n");
|
|
}
|
|
|
|
function sendToUpstream(payload) {
|
|
if (ws.readyState !== WebSocket.OPEN) return;
|
|
ws.send(JSON.stringify({
|
|
action: "sendUpstream",
|
|
payload
|
|
}));
|
|
pushHistory("OUT", payload);
|
|
}
|
|
|
|
const proto = location.protocol === "https:" ? "wss" : "ws";
|
|
const ws = new WebSocket(`${proto}://${location.host}/ws`);
|
|
|
|
ws.onopen = () => {
|
|
statusEl.textContent = "połączono z lokalnym podglądem";
|
|
statusEl.className = "ok";
|
|
};
|
|
|
|
ws.onclose = () => {
|
|
statusEl.textContent = "rozłączono";
|
|
statusEl.className = "bad";
|
|
};
|
|
|
|
ws.onerror = () => {
|
|
statusEl.textContent = "błąd połączenia";
|
|
statusEl.className = "bad";
|
|
};
|
|
|
|
ws.onmessage = (evt) => {
|
|
let data;
|
|
try {
|
|
data = JSON.parse(evt.data);
|
|
} catch {
|
|
return;
|
|
}
|
|
|
|
lastEventEl.textContent = `Zdarzenie: ${data.event || "?"} | ${new Date(data.ts || Date.now()).toLocaleTimeString()}`;
|
|
|
|
if (data.event === "status") {
|
|
const connected = !!data.connected;
|
|
statusEl.textContent = connected ? "upstream: połączono" : "upstream: rozłączono";
|
|
statusEl.className = connected ? "ok" : "bad";
|
|
return;
|
|
}
|
|
|
|
if (data.event === "sent") {
|
|
lastEventEl.textContent = `Wysłano do upstream: ${JSON.stringify(data.payload)} | ${new Date(data.ts || Date.now()).toLocaleTimeString()}`;
|
|
return;
|
|
}
|
|
|
|
if (data.event !== "message") return;
|
|
|
|
rawEl.textContent = data.raw || "(pusto)";
|
|
if (data.raw) pushHistory("IN", data.raw);
|
|
|
|
const msg = data.parsed;
|
|
if (!msg || msg.Type !== "bills" || !Array.isArray(msg.Bills)) {
|
|
return;
|
|
}
|
|
|
|
billsInfoEl.textContent = `Odebrano ${msg.Bills.length} rekordów bills.`;
|
|
billsTable.style.display = "table";
|
|
tbody.innerHTML = "";
|
|
|
|
for (const bill of msg.Bills) {
|
|
const tr = document.createElement("tr");
|
|
tr.innerHTML = `
|
|
<td>${bill.ID || ""}</td>
|
|
<td>${bill.Description || ""}</td>
|
|
<td>${msg.kierunek || ""}</td>
|
|
<td>${msg.type || ""}</td>
|
|
`;
|
|
tbody.appendChild(tr);
|
|
}
|
|
};
|
|
|
|
refreshBtn.addEventListener("click", () => {
|
|
sendToUpstream({ Type: "bills", kierunek: "all", type: "current" });
|
|
});
|
|
|
|
sendCustomBtn.addEventListener("click", () => {
|
|
const text = customPayloadEl.value.trim();
|
|
if (!text) return;
|
|
|
|
try {
|
|
const parsed = JSON.parse(text);
|
|
sendToUpstream(parsed);
|
|
} catch {
|
|
alert("Niepoprawny JSON.");
|
|
}
|
|
});
|
|
|
|
autoRefreshEl.addEventListener("change", () => {
|
|
clearInterval(autoTimer);
|
|
autoTimer = null;
|
|
if (!autoRefreshEl.checked) return;
|
|
autoTimer = setInterval(() => {
|
|
sendToUpstream({ Type: "bills", kierunek: "all", type: "current" });
|
|
}, 5000);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|