71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
// sql console — run ad-hoc queries against archive or intelligence db
|
|
// depends on: app.js
|
|
|
|
async function runSql() {
|
|
const sql = document.getElementById("sql-input").value.trim();
|
|
if (!sql) return;
|
|
|
|
const database = document.getElementById("sql-db").value;
|
|
const errEl = document.getElementById("sql-error");
|
|
const resultsEl = document.getElementById("sql-results");
|
|
const elapsedEl = document.getElementById("sql-elapsed");
|
|
|
|
errEl.style.display = "none";
|
|
resultsEl.innerHTML = "";
|
|
elapsedEl.textContent = "";
|
|
|
|
try {
|
|
const data = await fetch("/admin/api/sql", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ sql, database }),
|
|
}).then(r => r.json());
|
|
|
|
if (data.error) {
|
|
errEl.textContent = data.error;
|
|
errEl.style.display = "";
|
|
return;
|
|
}
|
|
|
|
elapsedEl.textContent = `${data.elapsed}ms`;
|
|
|
|
const blocks = [];
|
|
for (const r of (data.results || [])) {
|
|
if (r.error) {
|
|
blocks.push(`<div style="color:#fca5a5; font-size:13px; margin-bottom:12px"><span style="color:var(--muted-dark); font-size:11px; display:block; margin-bottom:4px; font-family:'SF Mono','Fira Code',monospace">${escapeHtml(r.sql.slice(0, 120))}</span>${escapeHtml(r.error)}</div>`);
|
|
} else if (r.rows && r.rows.length > 0) {
|
|
const cols = Object.keys(r.rows[0]);
|
|
blocks.push(`
|
|
<div style="margin-bottom:16px">
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead><tr>${cols.map(c => `<th>${escapeHtml(c)}</th>`).join("")}</tr></thead>
|
|
<tbody>${r.rows.map(row =>
|
|
`<tr>${cols.map(c => `<td><span class="truncate" style="max-width:300px" title="${escapeHtml(String(row[c] ?? ""))}">${row[c] == null ? '<span style="color:var(--muted-dark)">NULL</span>' : escapeHtml(row[c])}</span></td>`).join("")}</tr>`
|
|
).join("")}</tbody>
|
|
</table>
|
|
</div>
|
|
<div style="color:var(--muted-dark); font-size:12px; margin-top:6px">${r.rows.length} row${r.rows.length !== 1 ? "s" : ""}</div>
|
|
</div>
|
|
`);
|
|
} else if (r.rows) {
|
|
blocks.push(`<div style="color:var(--muted); font-size:13px; margin-bottom:12px">No rows returned.</div>`);
|
|
} else {
|
|
blocks.push(`<div style="color:#86efac; font-size:13px; margin-bottom:12px">${r.changes} row${r.changes !== 1 ? "s" : ""} affected.</div>`);
|
|
}
|
|
}
|
|
resultsEl.innerHTML = blocks.join("");
|
|
} catch (e) {
|
|
errEl.textContent = e.message;
|
|
errEl.style.display = "";
|
|
}
|
|
}
|
|
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
document.getElementById("sql-run-btn").onclick = runSql;
|
|
|
|
document.getElementById("sql-input").addEventListener("keydown", e => {
|
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) runSql();
|
|
});
|
|
});
|