render function presentation ✓ 100.0%

Last updated: 2026-03-02T13:35:57.087Z

Metrics

LOC: 120 Complexity: 10 Params: 0 Coverage: 100.0% (50/50 lines, 46x executed)

Signature

render(): : void

Architecture violations

View all

  • [warning] max-lines: 'render' has 120 lines (max 80)

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)

graph LR render["render"] filterEntries["filterEntries"] renderEntries["renderEntries"] formatEntriesAsText["formatEntriesAsText"] copyToClipboard["copyToClipboard"] downloadAsJson["downloadAsJson"] clearLogEntries["clearLogEntries"] render -->|calls| filterEntries render -->|calls| renderEntries render -->|calls| render render -->|calls| formatEntriesAsText render -->|calls| copyToClipboard render -->|calls| downloadAsJson render -->|calls| clearLogEntries style render fill:#dbeafe,stroke:#2563eb,stroke-width:2px click render "80ece8fdb820f2e0.html" click filterEntries "0ad485f0d0788dd9.html" click renderEntries "a2c9a34c1a76387d.html" click formatEntriesAsText "9512b6f4ff5fc5a0.html" click copyToClipboard "a758a4a218f84aaf.html" click downloadAsJson "b031a65522b26156.html" click clearLogEntries "b955aae3387005ad.html"

Impact (Incoming)

graph LR render["render"] init["init"] refresh["refresh"] createLogViewer["createLogViewer"] mount["mount"] renderTo["renderTo"] init -->|calls| render render -->|calls| render refresh -->|calls| render createLogViewer -->|calls| render mount -->|uses| render mount -->|uses| render renderTo -->|uses| render style render fill:#dbeafe,stroke:#2563eb,stroke-width:2px click render "80ece8fdb820f2e0.html" click init "9c03e8cd6a18eb5d.html" click refresh "f0f8b893cd35303a.html" click createLogViewer "cc8b77ecd2282660.html" click mount "79c2c5c537b9cb26.html" click renderTo "82b88bd90e760d1a.html"
SourceType
init calls
render calls
refresh calls
createLogViewer calls
mount uses
mount uses
renderTo uses