feat: move response body

This commit is contained in:
2026-03-24 17:18:35 +04:00
parent bb05dae926
commit 79b7f21591
4 changed files with 73 additions and 10 deletions
+8
View File
@@ -61,6 +61,14 @@ export async function migrate() {
await sql`CREATE INDEX IF NOT EXISTS idx_pings_monitor ON pings(monitor_id, checked_at DESC)`;
await sql`CREATE INDEX IF NOT EXISTS idx_pings_checked_at ON pings(checked_at)`;
// Response bodies stored separately to keep pings table lean
await sql`
CREATE TABLE IF NOT EXISTS ping_bodies (
ping_id BIGINT PRIMARY KEY REFERENCES pings(id) ON DELETE CASCADE,
body TEXT
)
`;
await sql`
CREATE TABLE IF NOT EXISTS api_keys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+25 -9
View File
@@ -175,10 +175,9 @@
// ── Ping detail modal ──────────────────────────────────────────
function openPingModal(ping) {
const body = document.getElementById('ping-modal-body');
const modalBody = document.getElementById('ping-modal-body');
const meta = ping.meta || {};
const headers = meta.headers || {};
const bodyPreview = meta.body_preview || null;
const time = new Date(ping.checked_at);
const scheduled = ping.scheduled_at ? new Date(ping.scheduled_at) : null;
@@ -223,17 +222,34 @@
html += '</div></div>';
}
// Body preview
if (bodyPreview) {
html += '<div>';
html += '<div class="text-xs text-gray-500 mb-1">Response Body <span class="text-gray-600">(up to 25KB)</span></div>';
html += `<pre class="bg-gray-800/50 border border-border-subtle rounded-lg px-3 py-2 text-xs font-mono text-gray-300 whitespace-pre-wrap break-all max-h-80 overflow-y-auto">${escapeHtml(bodyPreview)}</pre>`;
html += '</div>';
// Response body — loaded on demand
html += '<div id="ping-body-section">';
if (ping.id) {
html += '<div class="text-xs text-gray-500 mb-1">Response Body</div>';
html += '<div id="ping-body-content" class="bg-gray-800/50 border border-border-subtle rounded-lg px-3 py-2 text-xs font-mono text-gray-500 min-h-[2rem] flex items-center">Loading...</div>';
}
html += '</div>';
html += '</div>';
body.innerHTML = html;
modalBody.innerHTML = html;
document.getElementById('ping-modal').classList.remove('hidden');
// Fetch body asynchronously
if (ping.id) {
api(`/pings/${ping.id}/body`).then(data => {
const el = document.getElementById('ping-body-content');
if (!el) return;
if (data.body) {
el.className = 'bg-gray-800/50 border border-border-subtle rounded-lg px-3 py-2 text-xs font-mono text-gray-300 whitespace-pre-wrap break-all max-h-80 overflow-y-auto';
el.textContent = data.body;
} else {
el.textContent = 'No body stored';
}
}).catch(() => {
const el = document.getElementById('ping-body-content');
if (el) el.textContent = 'Failed to load';
});
}
}
function closePingModal() {