Skip to content

feat: add Logs tab to entity resource panel - #59

Merged
bburda merged 6 commits into
mainfrom
feat/logs-tab
Apr 12, 2026
Merged

feat: add Logs tab to entity resource panel#59
bburda merged 6 commits into
mainfrom
feat/logs-tab

Conversation

@bburda

@bburda bburda commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a "Logs" tab to the entity resource panel for viewing ROS log entries per entity with severity/context filtering, auto-refresh polling, JSON export, and per-entity logs configuration editing.

Highlights:

  • LogsPanel component with dense table (Time / Severity / Node / Message), click-to-expand rows revealing source location (context.function, context.file:line, full timestamp).
  • Toolbar controls: severity dropdown, context filter (300 ms debounce, hidden for App entities), client-side message text search, manual refresh, auto-refresh toggle (on by default) + interval selector (2s/5s/10s/30s), clear, JSON download.
  • Lazy-loaded collapsible configuration row with gear icon; severity_filter and max_entries fields validated against gateway bounds (1..10000), persisted via PUT /logs/configuration.
  • Aggregation header for Area and Function entities showing x-medkit.aggregation_level and source count.
  • Auto-refresh polling pauses when document.visibilityState !== 'visible'.
  • New store actions fetchEntityLogs, getLogsConfiguration, updateLogsConfiguration and api-dispatch helpers for per-entity-type paths.

Issue

Type

  • New feature

Testing

  • 38 new Vitest tests covering loading / 503 / empty / populated states, row expansion, every toolbar control, auto-refresh timer logic (including visibility pause and filter-change races), clear/download, lazy-loaded config with retry-on-failure, aggregation header (present and absent), abort on entity change, and interval cleanup on unmount.
  • Full suite: 284 tests passing.
  • Lint, typecheck, production build all clean.

Manual verification steps for reviewers:

  • Connect the web UI to a running gateway with demo_nodes, navigate to an App entity, switch to the new Logs tab, verify entries load and auto-refresh ticks at 5s.
  • Switch to a Component entity and verify prefix-match aggregation; severity filter narrows results server-side.
  • Switch to an Area entity and verify the aggregation header shows the correct source count.
  • Click the gear, change max_entries, save, and verify the table reflects the new cap on the next refresh.
  • Click Download and open the JSON file; confirm displayed entries are serialized.
  • Hide the browser tab and verify polling pauses (no network activity in devtools).

Checklist

  • Breaking changes are clearly described (none)
  • Linting passes (npm run lint)
  • Build succeeds (npm run build)
  • Docs were updated if behavior or public API changed (README entry for the new tab TBD - flagging for reviewer judgement)

Copilot AI review requested due to automatic review settings April 11, 2026 08:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Logs feature to the UI by introducing a LogsPanel and wiring it into the existing resource tabs, plus the supporting API dispatch + Zustand store actions + types and tests.

Changes:

  • Added log domain types, API dispatch helpers, and store actions for fetching logs and reading/updating logs configuration.
  • Implemented LogsPanel UI with filtering, polling, JSON export, and a lazy-loaded configuration editor.
  • Integrated a new “Logs” tab into EntityResourceTabs and added extensive Vitest coverage (including a Blob.text polyfill for jsdom).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/test/setup.ts Adds a Blob.text polyfill to support download-related tests in jsdom.
src/lib/types.ts Re-exports log-related types from a new local log-types.ts module.
src/lib/store.ts Adds Zustand actions for fetching logs and getting/updating logs configuration.
src/lib/log-types.ts Introduces local TS types mirroring the gateway /logs payloads.
src/lib/api-dispatch.ts Adds per-entity-type dispatchers for logs and logs configuration endpoints.
src/lib/api-dispatch.test.ts Adds tests validating the new logs dispatch functions and signal passthrough.
src/components/LogsPanel.tsx Implements the Logs UI (table, filters, polling, export, and config editor).
src/components/LogsPanel.test.tsx Adds comprehensive component tests for the Logs UI behavior.
src/components/EntityResourceTabs.tsx Adds “Logs” as a new resource tab and renders LogsPanel when active.

Comment thread src/components/LogsPanel.tsx Outdated
Comment thread src/components/LogsPanel.tsx
Comment thread src/components/LogsPanel.tsx Outdated
Comment thread src/components/EntityResourceTabs.tsx Outdated
Comment thread src/components/LogsPanel.tsx
@bburda bburda self-assigned this Apr 11, 2026
@bburda
bburda requested a review from mfaferek93 April 11, 2026 11:49
Adds a "Logs" tab to EntityResourceTabs for viewing ROS log entries
per entity with severity/context filtering, auto-refresh polling,
JSON download, and per-entity logs configuration editing.

- Generic store actions + api-dispatch helpers for /logs endpoints
- Local TypeScript interfaces mirroring the gateway JSON shape
- LogsPanel component: dense table, click-to-expand rows, toolbar
  filters, auto-refresh with visibility gating, clear/download,
  lazy-loaded collapsible configuration row
- Aggregation header for areas and functions
- Wired as the 5th tab alongside Data/Operations/Config/Faults

Closes #43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment thread src/components/LogsPanel.tsx
Comment thread src/components/LogsPanel.tsx
Comment thread src/lib/store.ts Outdated
bburda added 2 commits April 11, 2026 22:11
Unification:
- New resource-tabs.tsx module exports RESOURCE_TABS config and
  renderResourceTabContent helper as the single source of truth for
  Data / Operations / Configurations / Faults / Logs tabs.
- AppsPanel, FunctionsPanel, and EntityDetailPanel component view
  merge RESOURCE_TABS into their flat tab bars so the Logs tab now
  appears on all four entity types, not just Areas.

LogsPanel polish:
- Table caps at 60vh with a scrollable body and sticky column header
  so the page no longer grows unboundedly.
- 404 responses render the same "Logs not available" state as 503,
  distinguished by message (entity-specific vs gateway-wide).
- Windows-safe download filename (colons/dots replaced with hyphens).
- Config Save button disabled until the initial GET succeeds; a
  "Failed to load configuration" state with Retry replaces the
  silent default-form bug where the user could overwrite server
  config with defaults.
- Row expansion is keyboard-accessible (role, tabIndex, onKeyDown,
  aria-expanded).
- Config-row state resets on entity change so navigating between
  entities no longer leaks cached config.

Tests: +5 new LogsPanel tests covering the review findings.
- formatTime now normalizes ISO 8601 strings to millisecond precision
  before parsing, so nanosecond-precision gateway timestamps render
  consistently across browsers. On parse failure it returns a
  placeholder ('--:--:--.---') instead of the full ISO string, which
  would otherwise overflow the fixed-width Time column.
- getLogsConfiguration in the store now wraps the GET in try/catch,
  matching the defensive pattern used by fetchEntityLogs, so thrown
  exceptions become null returns + console.error instead of
  unhandled rejections surfacing in event handlers.
- Adds a test asserting nanosecond timestamps render as HH:MM:SS.sss.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread src/components/LogsPanel.tsx
Comment thread src/components/ResourceTabs.tsx
bburda added 2 commits April 12, 2026 09:17
When the user navigates between entities of the same type (e.g.
Component A -> Component B), the panel components stay mounted and
their tab state persists. This caused the resource bar to show
whatever tab was active on the previous entity.

Fix:
- EntityDetailPanel: resets activeTab to 'data' on selectedEntity.id
  change (covers the inline component-view tab bar).
- EntityResourceTabs: resets activeTab + loadedTabs + data/ops/faults
  on entityId/entityType change (covers the Areas resource sub-bar).
- AppsPanel, FunctionsPanel, AreasPanel: now receive key={entity.id}
  from the parent so React remounts them on entity change, which
  resets all internal state (activeTab, loaded data, etc.).
- loadConfig now captures the entity identity at call time via a ref
  and discards the result if the entity changed while the GET was
  in-flight, preventing stale config from being applied to the wrong
  entity.
- Renames resource-tabs.tsx to ResourceTabs.tsx to match the PascalCase
  naming convention used by every other component module in the project.
  Updates all four import sites.
Comment thread src/components/LogsPanel.test.tsx
Comment thread src/components/LogsPanel.tsx
Comment thread src/components/LogsPanel.tsx
1. Test spy leak (mfaferek93 line 646): added vi.restoreAllMocks()
   to afterEach so document.createElement and URL spies are cleaned
   up automatically between tests.

2. 10k-row rendering jank (mfaferek93 line 405): client-side display
   cap at 200 rows. When filteredEntries exceeds the cap, a "Show
   all N entries" button appears at the bottom of the table. No new
   dependencies. showAllEntries state resets on entity change.

3. Toolbar filters not reset on entity change (mfaferek93 line 159):
   the entity-change useEffect now also resets severity, contextDraft,
   contextFilter, messageSearch, expandedIds, and showAllEntries.
   Previously only config-row state was reset, so switching entities
   could leave stale node-FQN filters active on the new entity.
@mfaferek93
mfaferek93 self-requested a review April 12, 2026 10:46

@mfaferek93 mfaferek93 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@bburda
bburda merged commit 935f8d7 into main Apr 12, 2026
3 checks passed
@bburda
bburda deleted the feat/logs-tab branch April 12, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Logs tab

3 participants