render function presentation ✓ 100.0%
Last updated: 2026-03-02T13:35:57.087Z
Location
Metrics
LOC: 120
Complexity: 10
Params: 0
Coverage: 100.0% (50/50 lines, 46x executed)
Signature
render(): : void
Source Code
function render(): void {
const filtered = filterEntries();
const filterBtns = (
["all", "debug", "info", "warn", "error", "audit"] as const
)
.map(
(level) =>
`<button class="lv-filter-btn${activeFilter === level ? " active" : ""}" data-level="${level}">${LEVEL_LABELS[level]}</button>`,
)
.join("");
container.innerHTML = `
<div class="lv-toolbar">
<div class="lv-filters">${filterBtns}</div>
<input class="lv-search" type="text" placeholder="Buscar logs..." value="${escapeHtml(searchQuery)}" />
<input class="lv-time-from" type="datetime-local" title="De:" value="${timeFrom}" />
<input class="lv-time-to" type="datetime-local" title="Até:" value="${timeTo}" />
<button class="lv-copy-all-btn" title="Copiar todos os logs visíveis">📋</button>
<button class="lv-download-json-btn" title="Baixar logs como JSON">⬇️</button>
<button class="lv-clear-btn" title="Limpar todos os logs">🗑️</button>
<span class="lv-count">${filtered.length}/${allEntries.length}</span>
</div>
<div class="lv-entries">${renderEntries(filtered)}</div>
`;
// Bind filter buttons
container
.querySelectorAll<HTMLButtonElement>(".lv-filter-btn")
.forEach((btn) => {
btn.addEventListener("click", () => {
activeFilter = btn.dataset.level as LogLevel | "all";
render();
});
});
// Bind search input
const searchInput = container.querySelector<HTMLInputElement>(".lv-search");
const actualLen = searchInput?.value.length ?? 0;
if (searchInput) {
searchInput.addEventListener(
"input",
debounce(() => {
searchQuery = searchInput.value;
render();
}, 300),
);
const newInput = container.querySelector<HTMLInputElement>(".lv-search");
if (newInput) {
const len =
newInput.value.length > actualLen ? newInput.value.length : actualLen;
newInput.focus();
newInput.setSelectionRange(len, len);
}
}
// Bind time-range inputs
const timeFromInput =
container.querySelector<HTMLInputElement>(".lv-time-from");
if (timeFromInput) {
timeFromInput.addEventListener("change", () => {
timeFrom = timeFromInput.value;
render();
});
}
const timeToInput =
container.querySelector<HTMLInputElement>(".lv-time-to");
if (timeToInput) {
timeToInput.addEventListener("change", () => {
timeTo = timeToInput.value;
render();
});
}
// Bind copy-all button
container
.querySelector(".lv-copy-all-btn")
?.addEventListener("click", () => {
const filtered = filterEntries();
const text = formatEntriesAsText(filtered);
void copyToClipboard(text);
});
// Bind download JSON button
container
.querySelector(".lv-download-json-btn")
?.addEventListener("click", () => {
downloadAsJson(filterEntries());
});
// Bind per-entry copy buttons
container
.querySelectorAll<HTMLButtonElement>(".lv-copy-entry-btn")
.forEach((btn) => {
btn.addEventListener("click", () => {
const idx = Number(btn.dataset.idx);
const filtered = filterEntries();
const entry = filtered[idx];
if (entry) {
const text = formatEntriesAsText([entry]);
void copyToClipboard(text);
}
});
});
// Bind clear button
container
.querySelector(".lv-clear-btn")
?.addEventListener("click", async () => {
await clearLogEntries();
allEntries = [];
render();
});
// Auto-scroll to bottom
const entriesEl = container.querySelector(".lv-entries");
if (entriesEl) {
entriesEl.scrollTop = entriesEl.scrollHeight;
}
}
Dependencies (Outgoing)
| Target | Type |
|---|---|
| filterEntries | calls |
| renderEntries | calls |
| render | calls |
| formatEntriesAsText | calls |
| copyToClipboard | calls |
| downloadAsJson | calls |
| clearLogEntries | calls |