Skip to content

fix: resolve empty resource tabs and missing peer component children#62

Merged
bburda merged 5 commits intomainfrom
fix/resource-tabs-and-peer-children
Apr 12, 2026
Merged

fix: resolve empty resource tabs and missing peer component children#62
bburda merged 5 commits intomainfrom
fix/resource-tabs-and-peer-children

Conversation

@bburda
Copy link
Copy Markdown
Contributor

@bburda bburda commented Apr 12, 2026

Summary

Fix two bugs that broke the entity browser when connected to a gateway aggregating peer ECUs:

  • EntityResourceTabs showed empty content for Data/Operations/Configurations/Faults tabs after switching between entities, because the reset effect updated loadedTabs via batched setState but the load effect in the same React commit read a stale loadedTabsRef and returned early.
  • Peer-sourced components (sourced from remote gateways via aggregation) showed no child apps because GET /components/{id}/hosts returns empty for them; the child apps actually reference the component via x-medkit.component_id or _links.is-located-on.

Issue


Type

  • Bug fix
  • New feature
  • Breaking change
  • Documentation only

Testing

  • 7 new unit tests: 2 for EntityResourceTabs entity-switch behavior, 5 for the new filterAppsByComponent helper (covering both match criteria, empty input, and the partial-ID edge case where a suffix of a longer component ID must not match).
  • Full suite: 297 tests pass (was 290).
  • Typecheck and lint clean.
  • Reviewers should verify manually: connect the UI to a gateway with a peer component, expand it, and check that child apps appear; switch between sibling components and verify each tab's content refreshes.

Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Linting passes (npm run lint)
  • Build succeeds (npm run build)
  • Docs were updated if behavior or public API changed

Fix two bugs that cause E2E test failures with aggregated peer gateways:

1. EntityResourceTabs: synchronously clear loadedTabsRef in the reset
   effect so the load effect (same React commit) sees false instead of
   stale true values from the previous entity.

2. loadChildren: when /components/{id}/hosts returns empty (peer-sourced
   components), fall back to GET /apps filtered by x-medkit.component_id
   or _links.is-located-on.

Extract filterAppsByComponent as a testable helper. Add 7 new tests
covering both fixes.

closes #61
Copilot AI review requested due to automatic review settings April 12, 2026 17:44
@bburda bburda self-assigned this Apr 12, 2026
@bburda bburda requested a review from mfaferek93 April 12, 2026 17:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes two regressions in the entity browser when connected to aggregated/peer gateways: resource tabs going blank after switching entities, and peer-sourced components not showing child apps due to empty /hosts responses.

Changes:

  • Update EntityResourceTabs to synchronously reset loadedTabsRef on entity change to avoid a ref/state race.
  • Add filterAppsByComponent and use it as a fallback when component hosts are empty by fetching /apps and filtering.
  • Add unit tests covering the tab-reset behavior and the new app-filter helper.

Reviewed changes

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

File Description
src/components/EntityResourceTabs.tsx Fixes entity-switch race by resetting loadedTabsRef synchronously.
src/lib/store.ts Adds /apps fallback to populate child apps for peer-sourced components and introduces filtering helper.
src/lib/store-helpers.test.ts Adds unit tests for filterAppsByComponent.
src/components/EntityResourceTabs.test.tsx Adds unit tests for EntityResourceTabs entity-switch behavior.

Comment thread src/lib/store.ts
Comment thread src/lib/store.ts
- filterAppsByComponent now also matches `app.component_id` directly
  (not only `x-medkit.component_id` and `_links.is-located-on`) so the
  helper remains robust if future transforms lift component_id to the
  top level.
- Add isPeerSourcedComponent helper and gate the /apps fallback on it,
  so legitimate empty manifest/plugin components do not trigger a full
  app-list fetch on every expand. Components with unknown source
  metadata still trigger the fallback to err on the side of completeness.
Copy link
Copy Markdown

Copilot AI left a comment

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 4 out of 4 changed files in this pull request and generated no new comments.

Comment thread src/components/EntityResourceTabs.tsx
Comment thread src/lib/store.ts
bburda added 3 commits April 12, 2026 20:22
Addresses review feedback on PR #62:

1. EntityResourceTabs: propagate an AbortSignal to all resource fetches
   (data/operations/configurations/faults) and abort them whenever the
   entity changes or the component unmounts. Prevents stale responses
   from overwriting a newer entity's data on slow connections.

   Extend fetchEntityData, fetchEntityOperations, fetchConfigurations,
   listEntityFaults, and the underlying api-dispatch helpers to accept
   an optional signal parameter that threads through to openapi-fetch.

2. Deduplicate concurrent GET /apps requests when multiple peer-sourced
   components are expanded in quick succession. Extract the fallback
   into fetchAllAppsDeduped, which holds a module-level in-flight
   promise and shares it across concurrent callers. The promise is
   cleared on settlement so later expansions fetch fresh data.

Add tests for both behaviors (stale-fetch discard + concurrent-request
dedupe + dedupe-cache reset + fetch-failure fallback).
handleAction fires prepare/execute/automated/delete against the gateway
without an abort signal. If the user navigates away while a mutation is
in-flight, the promise resolves and fires toast.success + setBusyIds on
an unmounted component.

Add an AbortController created in a mount effect and aborted in its
cleanup, thread its signal through the four mutation helpers, and
short-circuit post-await side effects when the signal is aborted.

The polling path in useUpdatesPolling already had this treatment; this
brings mutations to parity.

Tests assert (a) signal is an AbortSignal, (b) it becomes aborted on
unmount, (c) a late-resolving mutation does not fire a success toast.
@mfaferek93 mfaferek93 self-requested a review April 12, 2026 18:58
@bburda bburda merged commit 9f862a5 into main Apr 12, 2026
3 checks passed
bburda added a commit that referenced this pull request Apr 12, 2026
Addresses review feedback on PR #62:

1. EntityResourceTabs: propagate an AbortSignal to all resource fetches
   (data/operations/configurations/faults) and abort them whenever the
   entity changes or the component unmounts. Prevents stale responses
   from overwriting a newer entity's data on slow connections.

   Extend fetchEntityData, fetchEntityOperations, fetchConfigurations,
   listEntityFaults, and the underlying api-dispatch helpers to accept
   an optional signal parameter that threads through to openapi-fetch.

2. Deduplicate concurrent GET /apps requests when multiple peer-sourced
   components are expanded in quick succession. Extract the fallback
   into fetchAllAppsDeduped, which holds a module-level in-flight
   promise and shares it across concurrent callers. The promise is
   cleared on settlement so later expansions fetch fresh data.

Add tests for both behaviors (stale-fetch discard + concurrent-request
dedupe + dedupe-cache reset + fetch-failure fallback).
@bburda bburda deleted the fix/resource-tabs-and-peer-children branch April 12, 2026 19: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.

Resource tabs show empty content; peer-sourced components have no child apps

3 participants