Skip to content

feat: introduce topology view#3186

Open
lhein wants to merge 1 commit into
KaotoIO:mainfrom
lhein:topoView
Open

feat: introduce topology view#3186
lhein wants to merge 1 commit into
KaotoIO:mainfrom
lhein:topoView

Conversation

@lhein
Copy link
Copy Markdown
Contributor

@lhein lhein commented May 4, 2026

first draft of the topology view. for the moment we can only show it for a single file.

fixes #769

Summary by CodeRabbit

  • New Features

    • New Topology view accessible from Visualization in navigation
    • Interactive topology visualization with zoom, pan, fit/reset controls and layout toggles
    • Visualized route connections, external and dynamic endpoints, node badges/icons, and collapsed-route rendering
    • Right-click context menu entry to open a route
  • Style

    • Topology-specific styling improvements for nodes, edges, labels, and hover/badge visuals
  • Tests

    • Extensive test coverage added for topology components and utilities
  • Chore

    • Updated .gitignore to ignore .claude/

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 4, 2026

Warning

Rate limit exceeded

@lhein has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 50 minutes and 7 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16b45146-8c56-417d-a269-75fdd330486d

📥 Commits

Reviewing files that changed from the base of the PR and between edb2d30 and f755469.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/layout/__snapshots__/Navigation.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (34)
  • .gitignore
  • packages/ui/src/layout/Navigation.tsx
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.test.ts
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts
  • packages/ui/src/pages/Topology/TopologyPage.scss
  • packages/ui/src/pages/Topology/TopologyPage.test.tsx
  • packages/ui/src/pages/Topology/TopologyPage.tsx
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx
  • packages/ui/src/pages/Topology/components/TopologyDynamicEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyEdge.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyEdge.tsx
  • packages/ui/src/pages/Topology/components/TopologyExternalEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.test.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx
  • packages/ui/src/pages/Topology/index.ts
  • packages/ui/src/pages/Topology/rounded-path.test.ts
  • packages/ui/src/pages/Topology/rounded-path.ts
  • packages/ui/src/pages/Topology/router-exports.tsx
  • packages/ui/src/pages/Topology/topology-apply-model.hook.ts
  • packages/ui/src/pages/Topology/topology-connections.test.ts
  • packages/ui/src/pages/Topology/topology-connections.ts
  • packages/ui/src/pages/Topology/topology-context-menu.test.tsx
  • packages/ui/src/pages/Topology/topology-context-menu.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.test.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.tsx
  • packages/ui/src/pages/Topology/topology-controller.service.test.ts
  • packages/ui/src/pages/Topology/topology-controller.service.ts
  • packages/ui/src/pages/Topology/topology-layout-preference.hook.ts
  • packages/ui/src/pages/Topology/topology-model.hook.ts
  • packages/ui/src/router.tsx
  • packages/ui/src/router/links.models.ts
📝 Walkthrough

Walkthrough

This PR adds a topology visualization feature and integrates it into the UI: new topology page, routing and navigation entry, controller factories, layout/control hooks, model building (including synthetic external/dynamic endpoint nodes), custom edge rendering with rounded orthogonal bendpoints, multiple topology components, styles, and comprehensive tests. Also adds .claude/ to .gitignore.

Changes

Topology Visualization Feature

Layer / File(s) Summary
Data Shape & Utilities
packages/ui/src/pages/Topology/rounded-path.ts, packages/ui/src/pages/Topology/topology-connections.ts
Added buildRoundedPath(points, radius); introduced endpoint constants, RouteConnectionExtras, buildRouteConnectionExtras to extract/normalize endpoints and synthesize external/dynamic nodes and edges.
Core Edge Logic
packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts, packages/ui/src/pages/Topology/rounded-path.test.ts, packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.test.ts
Added OrthogonalBendpointsEdge.getBendpoints() computing two orthogonal bendpoints based on layout orientation; tests added for bendpoint behavior and rounded-path.
Synthetic Endpoint & Label Types/Components
packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx, packages/ui/src/pages/Topology/components/TopologyNodeLabel.tsx, tests*
Added TopologySyntheticEndpoint (with SyntheticEndpointData), TopologyNodeLabel for centered SVG labels, and tests verifying rendering/positioning and badge/icon behavior.
Endpoint Wrappers
packages/ui/src/pages/Topology/components/TopologyDynamicEndpoint.tsx, packages/ui/src/pages/Topology/components/TopologyExternalEndpoint.tsx
Added lightweight wrappers configuring TopologySyntheticEndpoint for dynamic (BoltIcon) and external (ExternalLinkAltIcon) endpoints.
Edge Rendering Component
packages/ui/src/pages/Topology/components/TopologyEdge.tsx, packages/ui/src/pages/Topology/components/TopologyEdge.test.tsx
Added TopologyEdge component that hides edges within the same collapsed parent and draws a rounded SVG path + connector arrow using bendpoints; tests assert DOM and path output.
Collapsed Group Component
packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx, packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.test.tsx
Added TopologyCollapsedGroup rendering collapsed route groups, label logic, double-click to isolate route (dispatch + navigation), context-menu forwarding, and tests covering behaviors.
Model & Controller Wiring
packages/ui/src/pages/Topology/topology-model.hook.ts, packages/ui/src/pages/Topology/topology-apply-model.hook.ts, packages/ui/src/pages/Topology/topology-controller.service.ts, tests*
Added useTopologyModel to assemble PatternFly Model (prepend synthetic nodes, append connection edges); useApplyTopologyModel to sync controller, collapse top-level groups and fit viewport; TopologyControllerService to create Visualization and register layout/component/element factories (including mapping edge element to OrthogonalBendpointsEdge).
Layout Preference & Controls
packages/ui/src/pages/Topology/topology-layout-preference.hook.ts, packages/ui/src/pages/Topology/topology-control-buttons.hook.tsx, tests*
Added useTopologyLayoutPreference (settings/localStorage resolution) and useTopologyControlButtons (zoom, fit, reset, optional layout-toggle persisted to localStorage) with tests validating callbacks and persistence.
Context Menu
packages/ui/src/pages/Topology/topology-context-menu.tsx, packages/ui/src/pages/Topology/topology-context-menu.test.tsx
Added topologyContextMenuFn returning an “Open” item that toggles flow visibility and navigates to Home; tests validate dispatch and navigation.
Page, Router & Navigation
packages/ui/src/pages/Topology/TopologyPage.tsx, packages/ui/src/pages/Topology/index.ts, packages/ui/src/pages/Topology/router-exports.tsx, packages/ui/src/router.tsx, packages/ui/src/router/links.models.ts, packages/ui/src/layout/Navigation.tsx, packages/ui/src/pages/Topology/TopologyPage.scss, packages/ui/src/pages/Topology/TopologyPage.test.tsx
Added TopologyPage (controller, model hooks, VisualizationProvider, control bar), re-exports via router-exports, new /topology lazy route and Links.Topology constant, navigation menu entry for Topology, styles for topology canvas and endpoints, and integration tests for page rendering and controls.
Tests / Coverage
packages/ui/src/pages/Topology/**/*.test.ts?(x)
Comprehensive tests added across utilities, hooks, controller service, components, context menu, and the page (multiple focused test suites).
Misc
.gitignore
Added .claude/ entry.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Nav as Navigation
    participant Router as Router
    participant Page as TopologyPage
    participant Hooks as Model/Layout/Apply Hooks
    participant Controller as Topology Controller
    participant PF as PatternFly Visualization
    participant Canvas as SVG Canvas

    User->>Nav: Click "Topology"
    Nav->>Router: navigate to /topology
    Router->>Page: load TopologyPage (lazy)
    Page->>Hooks: useTopologyModel(vizNodes, entities, layout)
    Hooks->>Hooks: extract endpoints, synthesize nodes/edges
    Hooks-->>Page: model + topLevelGroupIds
    Page->>Controller: controller.fromModel(model)
    Controller->>PF: register factories + apply model
    Page->>Hooks: useApplyTopologyModel(controller, model, topLevelGroupIds)
    Hooks->>Controller: collapse groups, layout, fit()
    Page->>Hooks: useTopologyControlButtons(controller)
    Hooks-->>Page: control buttons (zoom/fit/reset/layout)
    PF->>Canvas: render nodes, edges, connectors
    User->>Canvas: double-click / open context menu
    Canvas->>Page: dispatch visible-flow changes
    Page->>Canvas: update model / re-render
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • KaotoIO/kaoto#3046: Both PRs modify router export semantics (re-exporting page components via router-exports).
  • KaotoIO/kaoto#2963: Both PRs add top-level navigation entries and touch navigation configuration.

Poem

🐰 I hopped through nodes and rounded bends,

stitched endpoints where a route extends,
I drew the graph with arrowed art—
now topology shows every part! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: introduce topology view' clearly and concisely describes the main change—adding a new topology visualization feature. It is specific, directly related to the changeset, and follows conventional commit format.
Linked Issues check ✅ Passed The PR implements core requirements from #769: a graphical topology view showing routes and their connections, support for navigation between routes, and the ability to display service connections for documentation purposes. All main objectives are addressed.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the topology feature: UI components for topology rendering, routing configuration, styling, and utilities. The .gitignore update to ignore .claude/ is a minor housekeeping change that does not impact feature scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lhein lhein force-pushed the topoView branch 2 times, most recently from 979321e to c1eaa54 Compare May 5, 2026 13:26
@KaotoIO KaotoIO deleted a comment from codecov Bot May 5, 2026
@KaotoIO KaotoIO deleted a comment from codecov Bot May 5, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 97.10145% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.12%. Comparing base (1b30aa1) to head (f755469).

Files with missing lines Patch % Lines
...ages/ui/src/pages/Topology/topology-connections.ts 94.78% 6 Missing ⚠️
...ges/Topology/components/TopologyCollapsedGroup.tsx 94.28% 2 Missing ⚠️
.../ui/src/pages/Topology/components/TopologyEdge.tsx 93.75% 1 Missing ⚠️
.../Topology/components/TopologySyntheticEndpoint.tsx 92.85% 1 Missing ⚠️
.../pages/Topology/topology-layout-preference.hook.ts 93.33% 1 Missing ⚠️
packages/ui/src/router.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3186      +/-   ##
==========================================
+ Coverage   92.04%   92.12%   +0.08%     
==========================================
  Files         619      635      +16     
  Lines       23740    24154     +414     
  Branches     5612     5495     -117     
==========================================
+ Hits        21851    22253     +402     
- Misses       1780     1899     +119     
+ Partials      109        2     -107     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lhein lhein marked this pull request as ready for review May 5, 2026 15:02
@lhein
Copy link
Copy Markdown
Contributor Author

lhein commented May 5, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
packages/ui/src/pages/Topology/topology-controller.service.ts (1)

55-73: 💤 Low value

Type-before-kind precedence in componentFactory could silently swallow a misconfigured node.

EXTERNAL_ENDPOINT_NODE_TYPE / DYNAMIC_ENDPOINT_NODE_TYPE checks run before the kind switch, so any element with those type strings—regardless of its ModelKind—resolves to the endpoint renderers. This is intentional and matches the tests, but worth a short inline comment so future contributors don't reorder the checks.

📝 Suggested clarifying comment
 static componentFactory(kind: ModelKind, type: string): ReturnType<ComponentFactory> {
+  // Type-based routing takes precedence over kind-based routing.
+  // Endpoint types are always resolved to their specific components regardless of kind.
   if (type === EXTERNAL_ENDPOINT_NODE_TYPE) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/topology-controller.service.ts` around lines
55 - 73, The precedence of type checks before the kind switch in
componentFactory is intentional to let nodes with type
EXTERNAL_ENDPOINT_NODE_TYPE or DYNAMIC_ENDPOINT_NODE_TYPE resolve to
TopologyExternalEndpoint/TopologyDynamicEndpoint regardless of their ModelKind;
add a short inline comment above the two if blocks in componentFactory
documenting this intentional "type-before-kind" precedence (mention
EXTERNAL_ENDPOINT_NODE_TYPE, DYNAMIC_ENDPOINT_NODE_TYPE, and that Graph/Edge
handling is in the ModelKind switch) so future contributors won't reorder the
checks thinking it's a bug.
packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx (1)

50-51: ⚡ Quick win

vizNode.data cast to CamelRouteVisualEntityData silently bypasses TypeScript's strict-mode guarantees.

In practice this is safe because TopologyCollapsedGroup is only wired up for group-kind nodes (which are always Camel routes), but the explicit as assertion means any future routing of a different node kind here would silently produce undefined for processorName without a compile-time error.

If vizNode.data already carries a typed discriminant (e.g. processorName on its base type or a union), prefer a type-narrowing check over the cast. Alternatively, add a runtime guard:

🛡️ Proposed defensive check
-const processorName = (vizNode.data as CamelRouteVisualEntityData).processorName;
+const processorName =
+  'processorName' in vizNode.data ? (vizNode.data as CamelRouteVisualEntityData).processorName : undefined;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx` around
lines 50 - 51, Replace the unsafe cast of vizNode.data to
CamelRouteVisualEntityData in TopologyCollapsedGroup: instead of using
"vizNode.data as CamelRouteVisualEntityData", add a runtime/type-narrowing guard
that verifies vizNode.data has the expected discriminant (e.g., check typeof
vizNode.data === 'object' && 'processorName' in vizNode.data) before reading
processorName, and fall back to a safe default (or early-return) if the shape
doesn't match; then call getProcessorIcon(processorName) only when processorName
is confirmed to exist to avoid silently producing undefined.
packages/ui/src/pages/Topology/TopologyPage.test.tsx (1)

76-83: ⚡ Quick win

Assertion pattern yields a poor failure message.

expect(nodes && nodes.length > 0).toBe(true) prints Expected: true, Received: false on failure with no diagnostic info. Prefer:

🔍 Clearer assertion
-expect(nodes && nodes.length > 0).toBe(true);
+expect(nodes?.length).toBeGreaterThan(0);

Same change applies at lines 117–118 in the "renders every route even when hidden" test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/TopologyPage.test.tsx` around lines 76 - 83,
The assertion `expect(nodes && nodes.length > 0).toBe(true)` yields an unhelpful
failure; replace it with a clearer assertion that shows the failing scope and
count—inside the same loop (where visualEntities and entity.getId() are used and
nodes is found via result?.container.querySelectorAll(`[data-id^="${scope}|"]`))
assert e.g. that nodes exists and nodes.length is > 0 by throwing or using a
Jest matcher that reports the value (for example: assert nodes?.length > 0 with
a thrown Error containing the scope when zero, or use
expect(nodes?.length).toBeGreaterThan(0)), and apply the same change to the
second test ("renders every route even when hidden" at lines ~117–118).
packages/ui/src/pages/Topology/topology-controller.service.test.ts (1)

65-68: ⚡ Quick win

The graph kind factory test only verifies the component is defined, not which component it is.

For consistency with the other factory assertions that use toBe, tightening this to toBe(GraphComponent) would catch an accidental routing change:

🔍 Stricter assertion
+import { DagreGroupsLayout, GraphComponent, ModelKind, Visualization } from '@patternfly/react-topology';
 ...
 it('returns the default GraphComponent for the graph kind', () => {
   const Component = TopologyControllerService.componentFactory(ModelKind.graph, 'graph');
-  expect(Component).toBeDefined();
+  expect(Component).toBe(GraphComponent);
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/topology-controller.service.test.ts` around
lines 65 - 68, The test using
TopologyControllerService.componentFactory(ModelKind.graph, 'graph') currently
only checks the result is defined; change the assertion to assert the exact
component by replacing the loose expect(Component).toBeDefined() with a strict
equality check expect(Component).toBe(GraphComponent) so the test verifies the
factory returns GraphComponent for ModelKind.graph; update the test case in
topology-controller.service.test.ts to import or reference GraphComponent and
use toBe for exact matching.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx`:
- Line 43: The data-testid construction in TopologySyntheticEndpoint.tsx uses
the user-facing prop label (`data-testid={`${testIdPrefix}__${label}`}`) which
can be unstable and non-unique; change it to use a deterministic identifier
(e.g., a model or endpoint id) or a sanitized slug instead. Locate the JSX in
the TopologySyntheticEndpoint component where `data-testid` is set and replace
`${label}` with a stable prop such as `id` or `modelId` (e.g.,
`${testIdPrefix}__${id}`), or if only label is available, apply a deterministic
sanitizer (slugify/safeId) to produce a stable token; ensure you reference the
same prop name (`testIdPrefix`, `label`, or `id`) used elsewhere in the
component and update any prop types if adding `id`.

In `@packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts`:
- Line 28: Guard accesses to the graph before calling getLayout/getBendpoints:
replace the direct call this.getGraph().getLayout() in OrthogonalBendpointsEdge
(the isHorizontal calculation) with a null-safe check (e.g., const graph =
this.getGraph(); const isHorizontal = graph ? graph.getLayout() ===
LayoutType.DagreHorizontal : false) and similarly guard any
this.getGraph().getBendpoints() usages so they use the graph variable or
optional chaining to avoid calling methods on undefined during lifecycle
attachment.

In `@packages/ui/src/pages/Topology/topology-connections.test.ts`:
- Around line 73-94: The test title mentions "direct-vm" but the entities only
include seda and vm endpoints; update the test in topology-connections.test.ts
by adding a direct-vm producer/consumer pair to the entities (e.g., another
mockEntity with route.from.uri 'timer:t' and a step to { to: { uri:
'direct-vm:z' } } plus a corresponding consumer entity with route.from.uri
'direct-vm:z'), add matching entries to the map (e.g., ['e','E|route'],
['f','F|route'] or appropriate ids), and update the assertions that check edges
and their labels from buildRouteConnectionExtras to expect the additional
'direct-vm:z' label and adjust edges length accordingly; alternatively, if you
prefer not to expand the fixtures, simply rename the it(...) title to remove
"and direct-vm" so it accurately reflects only seda and vm coverage.

In `@packages/ui/src/pages/Topology/topology-layout-preference.hook.ts`:
- Around line 25-30: The code is trusting localStorage value for
LocalStorageKeys.CanvasLayout when computing activeLayout, which can yield
invalid layout strings; update the logic that computes activeLayout (the useMemo
using settingsLayout, LocalStorageKeys.CanvasLayout, and LayoutType) to read the
stored value, validate it against the allowed LayoutType values (e.g.,
Object.values(LayoutType).includes(storedValue) or a small isValidLayout(layout:
string) helper), and only use it if valid—otherwise fall back to settingsLayout
or LayoutType.DagreHorizontal.

---

Nitpick comments:
In `@packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx`:
- Around line 50-51: Replace the unsafe cast of vizNode.data to
CamelRouteVisualEntityData in TopologyCollapsedGroup: instead of using
"vizNode.data as CamelRouteVisualEntityData", add a runtime/type-narrowing guard
that verifies vizNode.data has the expected discriminant (e.g., check typeof
vizNode.data === 'object' && 'processorName' in vizNode.data) before reading
processorName, and fall back to a safe default (or early-return) if the shape
doesn't match; then call getProcessorIcon(processorName) only when processorName
is confirmed to exist to avoid silently producing undefined.

In `@packages/ui/src/pages/Topology/topology-controller.service.test.ts`:
- Around line 65-68: The test using
TopologyControllerService.componentFactory(ModelKind.graph, 'graph') currently
only checks the result is defined; change the assertion to assert the exact
component by replacing the loose expect(Component).toBeDefined() with a strict
equality check expect(Component).toBe(GraphComponent) so the test verifies the
factory returns GraphComponent for ModelKind.graph; update the test case in
topology-controller.service.test.ts to import or reference GraphComponent and
use toBe for exact matching.

In `@packages/ui/src/pages/Topology/topology-controller.service.ts`:
- Around line 55-73: The precedence of type checks before the kind switch in
componentFactory is intentional to let nodes with type
EXTERNAL_ENDPOINT_NODE_TYPE or DYNAMIC_ENDPOINT_NODE_TYPE resolve to
TopologyExternalEndpoint/TopologyDynamicEndpoint regardless of their ModelKind;
add a short inline comment above the two if blocks in componentFactory
documenting this intentional "type-before-kind" precedence (mention
EXTERNAL_ENDPOINT_NODE_TYPE, DYNAMIC_ENDPOINT_NODE_TYPE, and that Graph/Edge
handling is in the ModelKind switch) so future contributors won't reorder the
checks thinking it's a bug.

In `@packages/ui/src/pages/Topology/TopologyPage.test.tsx`:
- Around line 76-83: The assertion `expect(nodes && nodes.length >
0).toBe(true)` yields an unhelpful failure; replace it with a clearer assertion
that shows the failing scope and count—inside the same loop (where
visualEntities and entity.getId() are used and nodes is found via
result?.container.querySelectorAll(`[data-id^="${scope}|"]`)) assert e.g. that
nodes exists and nodes.length is > 0 by throwing or using a Jest matcher that
reports the value (for example: assert nodes?.length > 0 with a thrown Error
containing the scope when zero, or use
expect(nodes?.length).toBeGreaterThan(0)), and apply the same change to the
second test ("renders every route even when hidden" at lines ~117–118).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2748b2af-4253-4aff-a774-76f3210cce21

📥 Commits

Reviewing files that changed from the base of the PR and between 1b30aa1 and d142a5c.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/layout/__snapshots__/Navigation.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (34)
  • .gitignore
  • packages/ui/src/layout/Navigation.tsx
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.test.ts
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts
  • packages/ui/src/pages/Topology/TopologyPage.scss
  • packages/ui/src/pages/Topology/TopologyPage.test.tsx
  • packages/ui/src/pages/Topology/TopologyPage.tsx
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx
  • packages/ui/src/pages/Topology/components/TopologyDynamicEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyEdge.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyEdge.tsx
  • packages/ui/src/pages/Topology/components/TopologyExternalEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.test.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx
  • packages/ui/src/pages/Topology/index.ts
  • packages/ui/src/pages/Topology/rounded-path.test.ts
  • packages/ui/src/pages/Topology/rounded-path.ts
  • packages/ui/src/pages/Topology/router-exports.tsx
  • packages/ui/src/pages/Topology/topology-apply-model.hook.ts
  • packages/ui/src/pages/Topology/topology-connections.test.ts
  • packages/ui/src/pages/Topology/topology-connections.ts
  • packages/ui/src/pages/Topology/topology-context-menu.test.tsx
  • packages/ui/src/pages/Topology/topology-context-menu.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.test.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.tsx
  • packages/ui/src/pages/Topology/topology-controller.service.test.ts
  • packages/ui/src/pages/Topology/topology-controller.service.ts
  • packages/ui/src/pages/Topology/topology-layout-preference.hook.ts
  • packages/ui/src/pages/Topology/topology-model.hook.ts
  • packages/ui/src/router.tsx
  • packages/ui/src/router/links.models.ts

const height = bounds?.height ?? CanvasDefaults.DEFAULT_NODE_HEIGHT;

return (
<g className={`custom-node ${className}`} data-testid={`${testIdPrefix}__${label}`} data-label={label}>
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make data-testid independent from user-facing labels.

data-testid={${testIdPrefix}__${label}} can become unstable (spaces/special chars) and non-unique when labels repeat, which makes tests flaky. Use a sanitized or deterministic id (e.g., model id) instead.

Suggested adjustment
-      <g className={`custom-node ${className}`} data-testid={`${testIdPrefix}__${label}`} data-label={label}>
+      <g
+        className={`custom-node ${className}`}
+        data-testid={`${testIdPrefix}__${element.getId?.() ?? label.replace(/[^a-zA-Z0-9_-]/g, '_')}`}
+        data-label={label}
+      >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<g className={`custom-node ${className}`} data-testid={`${testIdPrefix}__${label}`} data-label={label}>
<g
className={`custom-node ${className}`}
data-testid={`${testIdPrefix}__${element.getId?.() ?? label.replace(/[^a-zA-Z0-9_-]/g, '_')}`}
data-label={label}
>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx` at
line 43, The data-testid construction in TopologySyntheticEndpoint.tsx uses the
user-facing prop label (`data-testid={`${testIdPrefix}__${label}`}`) which can
be unstable and non-unique; change it to use a deterministic identifier (e.g., a
model or endpoint id) or a sanitized slug instead. Locate the JSX in the
TopologySyntheticEndpoint component where `data-testid` is set and replace
`${label}` with a stable prop such as `id` or `modelId` (e.g.,
`${testIdPrefix}__${id}`), or if only label is available, apply a deterministic
sanitizer (slugify/safeId) to produce a stable token; ensure you reference the
same prop name (`testIdPrefix`, `label`, or `id`) used elsewhere in the
component and update any prop types if adding `id`.

Comment thread packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts Outdated
Comment thread packages/ui/src/pages/Topology/topology-connections.test.ts
Comment thread packages/ui/src/pages/Topology/topology-layout-preference.hook.ts Outdated
@lhein lhein force-pushed the topoView branch 2 times, most recently from e311459 to edb2d30 Compare May 5, 2026 15:31
@lhein lhein requested review from PVinaches and lordrip May 5, 2026 15:35
@lhein
Copy link
Copy Markdown
Contributor Author

lhein commented May 5, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/ui/src/pages/Topology/topology-context-menu.test.tsx (2)

54-55: ⚡ Quick win

Assert dispatch call order explicitly.

hideFlows must happen before showFlows; using nth-call assertions makes this contract explicit and prevents false positives.

Stronger expectation style
-    expect(dispatch).toHaveBeenCalledWith({ type: 'hideFlows', flowIds: undefined });
-    expect(dispatch).toHaveBeenCalledWith({ type: 'showFlows', flowIds: ['route-1234'] });
+    expect(dispatch).toHaveBeenNthCalledWith(1, { type: 'hideFlows', flowIds: undefined });
+    expect(dispatch).toHaveBeenNthCalledWith(2, { type: 'showFlows', flowIds: ['route-1234'] });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/topology-context-menu.test.tsx` around lines
54 - 55, The test currently checks for both dispatch calls but not their order;
update the assertions in topology-context-menu.test.tsx to explicitly assert
call order by using nth-call assertions (e.g., toHaveBeenNthCalledWith) against
dispatch: assert that the first call is { type: 'hideFlows', flowIds: undefined
} and the second call is { type: 'showFlows', flowIds: ['route-1234'] },
ensuring the hideFlows action occurs before showFlows.

15-18: ⚡ Quick win

Avoid as never in test doubles; it hides type-contract regressions.

This cast bypasses strict typing and can let invalid element mocks compile silently. Prefer a narrowly typed mock helper instead.

Proposed typed mock helper
-const mockElement = (vizNode: Partial<IVisualizationNode> | undefined) =>
-  ({
-    getData: () => (vizNode ? { vizNode } : {}),
-  }) as never;
+type TopologyElementLike = {
+  getData: () => { vizNode?: Partial<IVisualizationNode> };
+};
+
+const mockElement = (vizNode: Partial<IVisualizationNode> | undefined): TopologyElementLike => ({
+  getData: () => (vizNode ? { vizNode } : {}),
+});
As per coding guidelines "Ensure TypeScript strict mode is enabled for all TypeScript code".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/topology-context-menu.test.tsx` around lines
15 - 18, The test helper mockElement currently uses an unsafe cast ("as never")
which hides type-contract regressions; replace it with a narrowly typed mock
that matches the real element shape used by the code under test (i.e. an object
with getData(): { vizNode?: Partial<IVisualizationNode> }). Remove the "as
never" and give mockElement a proper return type (or a small interface/type
alias) that accurately reflects the element expected by the topology context
menu tests so TypeScript strict mode can catch mismatches in getData and
IVisualizationNode usage.
packages/ui/src/pages/Topology/topology-layout-preference.hook.ts (1)

8-13: 💤 Low value

Consider exporting TopologyLayoutPreference for downstream typing.

The interface is the return type of an exported hook, but is not itself exported. Consumers that want to type a variable holding the hook's result (e.g., destructured in tests or forwarded via props) have no way to reference the type.

♻️ Proposed fix
-interface TopologyLayoutPreference {
+export interface TopologyLayoutPreference {

Also applies to: 39-40

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/topology-layout-preference.hook.ts` around
lines 8 - 13, Export the TopologyLayoutPreference interface so consumers can
type the hook result; update the declaration of TopologyLayoutPreference to be
exported (export interface TopologyLayoutPreference) and do the same for the
other similar interface referenced around lines 39-40 if present, ensuring the
exported names match the return type of the exported hook (e.g., the hook
function name) so downstream code and tests can import and use these types.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ui/src/pages/Topology/components/TopologyEdge.test.tsx`:
- Around line 69-85: Rename the test from "uses the start point itself as the
arrow anchor when the edge has no bendpoints" to "generates a straight-line path
when the edge has no bendpoints", and change the assertion to first assert the
presence of the SVG path element (querySelector('.custom-edge__body') →
expect(body).not.toBeNull()) before calling getAttribute (remove optional
chaining) so failures show the missing element; optionally add an explicit
assertion that the connector element ('.custom-edge__connector') exists or its
anchor is at the expected end point if you want to cover arrow positioning.

In `@packages/ui/src/pages/Topology/topology-connections.test.ts`:
- Around line 120-135: The test fixtures in topology-connections.test.ts place
steps inside route.from (e.g. route.from.steps) instead of at the route level,
which is inconsistent with the canonical Camel DSL and other tests; update the
affected test cases (including the "detects to inside choice/when branches" test
that uses mockEntity and the other mentioned tests) by moving the steps array
out of route.from into route.steps (so route: { from: { uri: 'timer:t' }, steps:
[...] }) to match the expected structure used by buildRouteConnectionExtras and
the rest of the suite.

In `@packages/ui/src/pages/Topology/topology-layout-preference.hook.ts`:
- Around line 15-17: The runtime validation fails because LayoutType is a const
enum and cannot be referenced under isolatedModules; replace the manual member
list by either (A) changing LayoutType in canvas.models.ts from `const enum
LayoutType` to a regular `enum LayoutType` so
LayoutType.DagreHorizontal/DagreVertical are available at runtime and then use
them in VALID_LAYOUTS in topology-layout-preference.hook.ts, or (B) add and
export a new constant (e.g. `export const VALID_LAYOUT_VALUES =
[LayoutType.DagreHorizontal, LayoutType.DagreVertical]` or a plain string array)
from canvas.models.ts and import that constant into
topology-layout-preference.hook.ts to construct VALID_LAYOUTS; update imports
and references to LayoutType/VALID_LAYOUTS accordingly.
- Around line 27-30: The memo for settingsLayout in
topology-layout-preference.hook.ts uses settingsAdapter as the sole dependency
so it never re-runs when the adapter's internal settings change; update the
dependency to the actual setting value (e.g.
settingsAdapter.getSettings().canvasLayoutDirection) so useMemo(() =>
getInitialLayout(...), [settingsAdapter.getSettings().canvasLayoutDirection]) or
alternatively modify the adapter (or SettingsProvider) to emit change
notifications and depend on that signal; reference symbols: settingsLayout,
useMemo, getInitialLayout, settingsAdapter.getSettings().canvasLayoutDirection,
saveSettings(), SettingsProvider/KaotoEditorFactory.

---

Nitpick comments:
In `@packages/ui/src/pages/Topology/topology-context-menu.test.tsx`:
- Around line 54-55: The test currently checks for both dispatch calls but not
their order; update the assertions in topology-context-menu.test.tsx to
explicitly assert call order by using nth-call assertions (e.g.,
toHaveBeenNthCalledWith) against dispatch: assert that the first call is { type:
'hideFlows', flowIds: undefined } and the second call is { type: 'showFlows',
flowIds: ['route-1234'] }, ensuring the hideFlows action occurs before
showFlows.
- Around line 15-18: The test helper mockElement currently uses an unsafe cast
("as never") which hides type-contract regressions; replace it with a narrowly
typed mock that matches the real element shape used by the code under test (i.e.
an object with getData(): { vizNode?: Partial<IVisualizationNode> }). Remove the
"as never" and give mockElement a proper return type (or a small interface/type
alias) that accurately reflects the element expected by the topology context
menu tests so TypeScript strict mode can catch mismatches in getData and
IVisualizationNode usage.

In `@packages/ui/src/pages/Topology/topology-layout-preference.hook.ts`:
- Around line 8-13: Export the TopologyLayoutPreference interface so consumers
can type the hook result; update the declaration of TopologyLayoutPreference to
be exported (export interface TopologyLayoutPreference) and do the same for the
other similar interface referenced around lines 39-40 if present, ensuring the
exported names match the return type of the exported hook (e.g., the hook
function name) so downstream code and tests can import and use these types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1d5d875b-01d4-4475-9612-c30e20a78843

📥 Commits

Reviewing files that changed from the base of the PR and between d142a5c and edb2d30.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/layout/__snapshots__/Navigation.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (34)
  • .gitignore
  • packages/ui/src/layout/Navigation.tsx
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.test.ts
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts
  • packages/ui/src/pages/Topology/TopologyPage.scss
  • packages/ui/src/pages/Topology/TopologyPage.test.tsx
  • packages/ui/src/pages/Topology/TopologyPage.tsx
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx
  • packages/ui/src/pages/Topology/components/TopologyDynamicEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyEdge.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyEdge.tsx
  • packages/ui/src/pages/Topology/components/TopologyExternalEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.test.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.test.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx
  • packages/ui/src/pages/Topology/index.ts
  • packages/ui/src/pages/Topology/rounded-path.test.ts
  • packages/ui/src/pages/Topology/rounded-path.ts
  • packages/ui/src/pages/Topology/router-exports.tsx
  • packages/ui/src/pages/Topology/topology-apply-model.hook.ts
  • packages/ui/src/pages/Topology/topology-connections.test.ts
  • packages/ui/src/pages/Topology/topology-connections.ts
  • packages/ui/src/pages/Topology/topology-context-menu.test.tsx
  • packages/ui/src/pages/Topology/topology-context-menu.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.test.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.tsx
  • packages/ui/src/pages/Topology/topology-controller.service.test.ts
  • packages/ui/src/pages/Topology/topology-controller.service.ts
  • packages/ui/src/pages/Topology/topology-layout-preference.hook.ts
  • packages/ui/src/pages/Topology/topology-model.hook.ts
  • packages/ui/src/router.tsx
  • packages/ui/src/router/links.models.ts
✅ Files skipped from review due to trivial changes (15)
  • packages/ui/src/pages/Topology/index.ts
  • .gitignore
  • packages/ui/src/pages/Topology/components/TopologyExternalEndpoint.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.test.tsx
  • packages/ui/src/pages/Topology/topology-controller.service.test.ts
  • packages/ui/src/pages/Topology/router-exports.tsx
  • packages/ui/src/router/links.models.ts
  • packages/ui/src/pages/Topology/topology-controller.service.ts
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.test.tsx
  • packages/ui/src/pages/Topology/TopologyPage.scss
  • packages/ui/src/pages/Topology/topology-model.hook.ts
  • packages/ui/src/pages/Topology/components/TopologyEdge.tsx
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.test.ts
  • packages/ui/src/pages/Topology/rounded-path.test.ts
  • packages/ui/src/pages/Topology/TopologyPage.test.tsx
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/ui/src/layout/Navigation.tsx
  • packages/ui/src/pages/Topology/components/TopologyNodeLabel.tsx
  • packages/ui/src/pages/Topology/TopologyPage.tsx
  • packages/ui/src/pages/Topology/topology-connections.ts
  • packages/ui/src/pages/Topology/rounded-path.ts
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.tsx
  • packages/ui/src/pages/Topology/OrthogonalBendpointsEdge.ts
  • packages/ui/src/pages/Topology/components/TopologyCollapsedGroup.test.tsx
  • packages/ui/src/pages/Topology/topology-control-buttons.hook.tsx
  • packages/ui/src/pages/Topology/components/TopologySyntheticEndpoint.tsx

Comment thread packages/ui/src/pages/Topology/components/TopologyEdge.test.tsx Outdated
Comment thread packages/ui/src/pages/Topology/topology-connections.test.ts
Comment on lines +15 to +17
// LayoutType is a `const enum`, so its values can't be enumerated at runtime —
// list them explicitly for the validation check.
const VALID_LAYOUTS = new Set<string>([LayoutType.DagreHorizontal, LayoutType.DagreVertical]);
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.

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether LayoutType is a const enum or regular enum
rg -n "LayoutType" --type=ts -A2 packages/ui/src/components/Visualization/Canvas/canvas.models.ts | head -20

# Check if isolatedModules is set in tsconfig
fd tsconfig.json packages/ui --exec grep -l "isolatedModules" {}
fd tsconfig.json packages/ui --exec grep -n "isolatedModules" {}

Repository: KaotoIO/kaoto

Length of output: 226


Replace const enum with regular enum or export validation values separately.

LayoutType is defined as a const enum in canvas.models.ts, but the project has isolatedModules: true in packages/ui/tsconfig.json. This combination prevents cross-module const enum usage at compile time. The manual listing in VALID_LAYOUTS does not resolve the underlying incompatibility—those enum members cannot be accessed at runtime under this configuration.

Fix: Either (1) change LayoutType from const enum to regular enum, or (2) export a separate constant from canvas.models.ts containing the valid layout values and import that instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/pages/Topology/topology-layout-preference.hook.ts` around
lines 15 - 17, The runtime validation fails because LayoutType is a const enum
and cannot be referenced under isolatedModules; replace the manual member list
by either (A) changing LayoutType in canvas.models.ts from `const enum
LayoutType` to a regular `enum LayoutType` so
LayoutType.DagreHorizontal/DagreVertical are available at runtime and then use
them in VALID_LAYOUTS in topology-layout-preference.hook.ts, or (B) add and
export a new constant (e.g. `export const VALID_LAYOUT_VALUES =
[LayoutType.DagreHorizontal, LayoutType.DagreVertical]` or a plain string array)
from canvas.models.ts and import that constant into
topology-layout-preference.hook.ts to construct VALID_LAYOUTS; update imports
and references to LayoutType/VALID_LAYOUTS accordingly.

Comment thread packages/ui/src/pages/Topology/topology-layout-preference.hook.ts Outdated
Signed-off-by: Lars Heinemann <lhein.smx@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

Copy link
Copy Markdown
Member

@lordrip lordrip left a comment

Choose a reason for hiding this comment

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

It looks good overall, from an architecture point of view, I think we're using very similar patterns as in the Design view so we should try to reuse as much as possible. For instance, the bendpoints, rounded paths, the node generation, among others

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.

Offer an environment overview of used components

2 participants