Skip to content

Commit 3b286e5

Browse files
committed
feat(ui): Add new request detail functions and refactor existing functions
1 parent 113b5e1 commit 3b286e5

2 files changed

Lines changed: 201 additions & 354 deletions

File tree

ui/templates/dashboard.html

Lines changed: 201 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -210,22 +210,9 @@
210210
if (content) {
211211
content.style.opacity = "1";
212212
}
213-
214-
// Execute scripts from swapped content
215-
var scriptContainer = e.detail.target.querySelector("[data-request-detail-script]");
216-
if (scriptContainer) {
217-
var scriptTag = scriptContainer.querySelector("script");
218-
if (scriptTag) {
219-
var scriptContent = scriptTag.textContent || scriptTag.innerText;
220-
try {
221-
var newScript = document.createElement("script");
222-
newScript.textContent = scriptContent;
223-
document.body.appendChild(newScript);
224-
document.body.removeChild(newScript);
225-
} catch (err) {
226-
console.error("Error executing request detail script:", err);
227-
}
228-
}
213+
// Initialize request detail (format JSON, update line numbers)
214+
if (typeof initRequestDetail === "function") {
215+
initRequestDetail();
229216
}
230217
}
231218
});
@@ -342,6 +329,203 @@
342329
}
343330
window.handleDeleteRequestFromList = handleDeleteRequestFromList;
344331

332+
// ============================================
333+
// Request Detail Functions (from request-detail.html)
334+
// ============================================
335+
336+
function setReplayUrl(button) {
337+
var requestId = button ? button.getAttribute("data-request-id") : null;
338+
if(requestId) {
339+
button.setAttribute("hx-post", "/r/" + requestId + "/replay");
340+
}
341+
}
342+
window.setReplayUrl = setReplayUrl;
343+
344+
function handleReplayBefore(button) {
345+
if(button) {
346+
button.classList.add("opacity-50", "pointer-events-none");
347+
var icon = button.querySelector("i");
348+
if(icon) icon.classList.add("animate-spin");
349+
}
350+
}
351+
window.handleReplayBefore = handleReplayBefore;
352+
353+
function handleReplayAfter(button) {
354+
if(button) {
355+
button.classList.remove("opacity-50", "pointer-events-none");
356+
var icon = button.querySelector("i");
357+
if(icon) icon.classList.remove("animate-spin");
358+
}
359+
if (typeof showToast === "function") {
360+
showToast("Request replayed", "success");
361+
}
362+
}
363+
window.handleReplayAfter = handleReplayAfter;
364+
365+
function handleDeleteRequest(button) {
366+
if(typeof event !== "undefined" && event.detail && event.detail.xhr && event.detail.xhr.status === 200) {
367+
var requestId = button.getAttribute("data-request-id");
368+
var endpointId = button.getAttribute("data-endpoint-id");
369+
if(requestId) {
370+
var selector = "[data-request-id=" + String.fromCharCode(34) + requestId + String.fromCharCode(34) + "]";
371+
var listItem = document.querySelector(selector);
372+
if(listItem) listItem.remove();
373+
}
374+
var count = document.getElementById("request-count");
375+
if(count) {
376+
var current = parseInt(count.innerText) || 0;
377+
count.innerText = Math.max(0, current - 1);
378+
}
379+
if(typeof showToast === "function") {
380+
showToast("Request deleted", "success");
381+
}
382+
if(endpointId) {
383+
window.location.href = "/" + endpointId;
384+
}
385+
}
386+
}
387+
window.handleDeleteRequest = handleDeleteRequest;
388+
389+
function toggleSection(sectionId) {
390+
var section = document.getElementById(sectionId);
391+
var chevronId = sectionId.replace("-section", "-chevron");
392+
var chevron = document.getElementById(chevronId);
393+
if (section && chevron) {
394+
var isHidden = section.classList.contains("hidden");
395+
if (isHidden) {
396+
section.classList.remove("hidden");
397+
chevron.classList.remove("rotate-180");
398+
} else {
399+
section.classList.add("hidden");
400+
chevron.classList.add("rotate-180");
401+
}
402+
}
403+
}
404+
window.toggleSection = toggleSection;
405+
406+
var headersViewMode = "json";
407+
408+
function toggleHeadersView() {
409+
var jsonView = document.getElementById("headers-json-view");
410+
var listView = document.getElementById("headers-list-view");
411+
var toggleBtn = document.getElementById("headers-view-toggle");
412+
if (!jsonView || !listView || !toggleBtn) return;
413+
if (headersViewMode === "json") {
414+
jsonView.classList.add("hidden");
415+
listView.classList.remove("hidden");
416+
toggleBtn.innerHTML = "<i class=" + String.fromCharCode(34) + "fas fa-list-ul text-xs" + String.fromCharCode(34) + "></i>";
417+
headersViewMode = "list";
418+
} else {
419+
jsonView.classList.remove("hidden");
420+
listView.classList.add("hidden");
421+
toggleBtn.innerHTML = "<i class=" + String.fromCharCode(34) + "fas fa-code text-xs" + String.fromCharCode(34) + "></i>";
422+
headersViewMode = "json";
423+
}
424+
}
425+
window.toggleHeadersView = toggleHeadersView;
426+
427+
function copyHeaders() {
428+
var jsonView = document.getElementById("headers-json-view");
429+
var listView = document.getElementById("headers-list-view");
430+
var activeView = headersViewMode === "json" ? jsonView : listView;
431+
if (!activeView) return;
432+
var text = activeView.innerText || activeView.textContent || "";
433+
navigator.clipboard.writeText(text).then(function() {
434+
if (typeof showToast === "function") {
435+
showToast("Headers copied", "success");
436+
}
437+
}).catch(function() {
438+
if (typeof showToast === "function") {
439+
showToast("Failed to copy", "error");
440+
}
441+
});
442+
}
443+
window.copyHeaders = copyHeaders;
444+
445+
function copyBody() {
446+
var bodyRaw = document.getElementById("body-raw");
447+
if (!bodyRaw) {
448+
if (typeof showToast === "function") {
449+
showToast("Cannot copy binary content", "info");
450+
}
451+
return;
452+
}
453+
var text = bodyRaw.innerText || bodyRaw.textContent || "";
454+
navigator.clipboard.writeText(text).then(function() {
455+
if (typeof showToast === "function") {
456+
showToast("Body copied", "success");
457+
}
458+
}).catch(function() {
459+
if (typeof showToast === "function") {
460+
showToast("Failed to copy", "error");
461+
}
462+
});
463+
}
464+
window.copyBody = copyBody;
465+
466+
function formatBody() {
467+
var bodyRaw = document.getElementById("body-raw");
468+
var lineNumbers = document.getElementById("line-numbers");
469+
if (!bodyRaw) return;
470+
var text = bodyRaw.textContent || bodyRaw.innerText || "";
471+
if (!text.trim()) return;
472+
try {
473+
var json = JSON.parse(text);
474+
var formatted = JSON.stringify(json, null, 2);
475+
bodyRaw.textContent = formatted;
476+
updateLineNumbers(bodyRaw, lineNumbers);
477+
if (typeof showToast === "function") {
478+
showToast("JSON formatted", "success");
479+
}
480+
} catch (e) {
481+
if (typeof showToast === "function") {
482+
showToast("Not valid JSON", "error");
483+
}
484+
}
485+
}
486+
window.formatBody = formatBody;
487+
488+
function updateLineNumbers(bodyRaw, lineNumbers) {
489+
if (!bodyRaw || !lineNumbers) return;
490+
var text = bodyRaw.innerText || bodyRaw.textContent || "";
491+
var lines = text.split("\n");
492+
var html = "";
493+
for (var i = 0; i < lines.length; i++) {
494+
html += "<div class=" + String.fromCharCode(34) + "leading-relaxed" + String.fromCharCode(34) + ">" + (i + 1) + "</div>";
495+
}
496+
lineNumbers.innerHTML = html;
497+
}
498+
499+
function initRequestDetail() {
500+
var bodyRaw = document.getElementById("body-raw");
501+
var lineNumbers = document.getElementById("line-numbers");
502+
if (bodyRaw && lineNumbers) {
503+
var text = bodyRaw.textContent || bodyRaw.innerText || "";
504+
if (text.trim()) {
505+
try {
506+
var json = JSON.parse(text);
507+
var formatted = JSON.stringify(json, null, 2);
508+
bodyRaw.textContent = formatted;
509+
} catch (e) {}
510+
}
511+
updateLineNumbers(bodyRaw, lineNumbers);
512+
}
513+
// Update headers line numbers too
514+
var headersRaw = document.getElementById("headers-raw");
515+
var headersLineNumbers = document.getElementById("headers-line-numbers");
516+
if (headersRaw && headersLineNumbers) {
517+
updateLineNumbers(headersRaw, headersLineNumbers);
518+
}
519+
}
520+
window.initRequestDetail = initRequestDetail;
521+
522+
// Initialize on page load if detail content exists
523+
initRequestDetail();
524+
525+
// ============================================
526+
// End Request Detail Functions
527+
// ============================================
528+
345529
// Apply colors to request items and dropdown after Vue is mounted
346530
function applyEndpointColors() {
347531
document.querySelectorAll("[data-endpoint-id]").forEach(el => {
@@ -452,7 +636,7 @@
452636
hx-target="#request-detail-content"
453637
hx-swap="innerHTML"
454638
hx-on::before-request="setRequestDetailUrl(this)"
455-
onclick="handleRequestClick(this)">
639+
onclick="handleRequestItemClick(this)">
456640
<div class="flex items-center justify-between mb-2">
457641
<div class="flex items-center gap-1.5">
458642
<div class="endpoint-color-dot w-1.5 h-1.5 rounded-full shrink-0" data-endpoint-id="{{ .EndpointID }}"></div>

0 commit comments

Comments
 (0)