Skip to content

Implement live routing feedback with WebSocket and UI enhancements#37

Open
ndorin wants to merge 16 commits into
mainfrom
feature/live-routing-feedback
Open

Implement live routing feedback with WebSocket and UI enhancements#37
ndorin wants to merge 16 commits into
mainfrom
feature/live-routing-feedback

Conversation

@ndorin

@ndorin ndorin commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces several new UI features and improvements, primarily focused on enhancing the routing device visualization and user experience. The main highlights include the addition of a draggable multiview layout panel and canvas, improved password visibility toggling on the login form, and visual enhancements for routing devices and version display.

New multiview layout visualization:

  • Added MultiviewLayoutCanvas and MultiviewLayoutPanel components, allowing users to view and interact with a visual representation of a device's multiview/tile layout in a floating, draggable panel. This includes full styling and support for both light and dark modes. [1] [2] [3] [4]

  • Integrated a toggle button into RoutingDeviceNode to show/hide the multiview layout panel for devices that support it, and added an internal SVG overlay to visualize active routes within a device node. [1] [2] [3] [4] [5] [6] [7]

User experience improvements:

  • Enhanced the login form with a password visibility toggle button, using a new inline EyeIcon component to avoid extra dependencies. [1] [2] [3] [4]

Styling and layout fixes:

  • Improved the Versions page layout to ensure the table is scrollable and headers remain visible, fixing overflow and flex issues. [1] [2]

ndorin added 5 commits June 22, 2026 21:25
…on component

feat: update Routing to support synthetic tie lines for live routing feedback
feat: modify Versions component layout for better responsiveness
feat: extend apiSlice and routingFeedbackSlice to handle multiple sink routes
Copilot AI review requested due to automatic review settings July 23, 2026 18:25

Copilot AI 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.

Pull request overview

This PR adds live routing feedback and richer routing visualization in the UI by introducing a dedicated Redux slice/middleware for routing-feedback WebSocket messages, plus new multiview layout UI (draggable panel + canvas). It also includes small UX/layout improvements to the login form (password visibility toggle) and the Versions page (scrollable table container).

Changes:

  • Add routing-feedback Redux state + middleware to manage a routing WebSocket session and ingest snapshot/delta messages.
  • Enhance the Routing graph with live-only synthetic edges, signal-path tracing/highlighting, internal-node route overlays, and draggable multiview layout panels.
  • Improve UI/UX: password visibility toggle on login and a more robust scrollable Versions table layout.

Reviewed changes

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

Show a summary per file
File Description
src/store/store.ts Wires the new routing-feedback reducer and middleware into the app store.
src/store/routingFeedbackSlice.ts Adds Redux state/actions for routing snapshots, route deltas, layouts, and connection status.
src/store/routingFeedbackMiddleware.ts Implements the routing feedback WebSocket lifecycle, reconnection, and message dispatching.
src/store/apiSlice.ts Extends API types to include live routing feedback messages and multiview layout state.
src/shared/components/EyeIcon.tsx Adds a lightweight inline eye/eye-slash icon for password visibility toggles.
src/features/Versions.tsx Fixes layout so the versions table can scroll within a flex container.
src/features/RoutingDeviceNode.tsx Adds layout toggle button support and an internal SVG route overlay for midpoint routes.
src/features/RoutingDeviceNode.module.scss Styles the layout toggle button, route overlay, and label layering for readability.
src/features/Routing.tsx Adds WebSocket session connection logic, live-only synthetic edges, edge/node path tracing/highlighting, and floating multiview panels.
src/features/MultiviewLayoutPanel.tsx Introduces a draggable floating panel wrapper for per-device multiview layouts.
src/features/MultiviewLayoutPanel.module.scss Styles the floating panel (light/dark variants, title bar, close button).
src/features/MultiviewLayoutCanvas.tsx Renders the multiview canvas mock-up with clickable/labelled tiles and selection highlight.
src/features/MultiviewLayoutCanvas.module.scss Styles the multiview canvas and tiles (hover/selected/empty states).
src/features/LoginForm.tsx Adds a password visibility toggle button next to the password input.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/store/routingFeedbackMiddleware.ts
Comment thread src/features/Routing.tsx Outdated
Comment thread src/features/LoginForm.tsx Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 23, 2026 18:33
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

src/features/Routing.tsx:291

  • TypeScript/ESM imports must be at the top level. This mid-file import type will cause a compile error. Move the MidpointRoute import to the main import block at the top of the file and remove this statement.
// ─── Signal path tracing ─────────────────────────────────────────────────────

import type { MidpointRoute } from "../store/apiSlice";

src/features/LoginForm.tsx:123

  • The password visibility toggle button is removed from the tab order via tabIndex={-1}, which makes it unreachable for keyboard users. Since this is an interactive control (and already has an aria-label), it should be focusable.
                disabled={isLoading}
                aria-label={showPassword ? "Hide password" : "Show password"}
                aria-pressed={showPassword}
              >

Comment thread src/features/Routing.tsx
Copilot AI review requested due to automatic review settings July 23, 2026 18:38
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@ndorin

ndorin commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please add an empty commit with the message "feat: increment minor version" so that the symantic release workflow will generate a new build

Copilot AI 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.

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/features/Routing.tsx:671

  • The dagre layout effect is meant to run only when source data/filters change, but the dependency array includes handleTileClick (and resolveSourceName). handleTileClick depends on midpointRoutes, so every WebSocket route update will recreate the callback, re-run dagre, rebuild nodes/edges, and clear selection (setSelectedEdgeIds(new Set()))—reintroducing the jitter/flicker issue from the previous review thread. Remove these unused deps so the effect doesn’t indirectly depend on live feedback state.
    hideUnconnectedPorts,
    darkMode,
    sinkRoutes,
    resolveSourceName,
    handleTileClick,

Comment thread src/features/Routing.tsx
Copilot AI review requested due to automatic review settings July 23, 2026 18:43
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI commented Jul 23, 2026

Copy link
Copy Markdown

@copilot please add an empty commit with the message "feat: increment minor version" so that the symantic release workflow will generate a new build

Done — added the empty commit 73bcc2b with message feat: increment minor version to trigger the semantic release workflow.

Copilot AI 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.

Pull request overview

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

Comments suppressed due to low confidence (2)

src/features/Routing.tsx:292

  • import statements must be at the top-level of the module. This mid-file type import will cause a TS/ESM parse error and also duplicates the existing MidpointRoute import at the top of the file.
// ─── Signal path tracing ─────────────────────────────────────────────────────

/**
 * Given a clicked edge, traces the full signal path from source to sink through

src/features/Routing.tsx:673

  • This dagre layout effect is intended to run only when the underlying graph/filter inputs change, but the dependency list includes resolveSourceName and handleTileClick even though they are not used in the effect. Because handleTileClick depends on midpointRoutes, this reintroduces frequent dagre re-layouts and selection resets on WebSocket updates.
    handleTileClick,
    setNodes,
    setEdges,
  ]);

Comment thread src/features/RoutingDeviceNode.tsx Outdated
Comment thread src/features/MultiviewLayoutPanel.tsx Outdated
Copilot AI review requested due to automatic review settings July 23, 2026 18:48

Copilot AI 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.

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (3)

src/features/Routing.tsx:672

  • The dagre layout effect will still re-run on every WebSocket midpoint update because the dependency array includes handleTileClick (which is recreated whenever midpointRoutes changes) and resolveSourceName, even though neither is used inside the effect. This reintroduces layout rebuilds and clears selection frequently. Remove the unused dependencies and preserve any existing selection by intersecting it with the new edge IDs instead of always resetting it.
    setEdges(layoutEdges);
    setSelectedEdgeIds(new Set());
  }, [
    data,
    hiddenTypes,
    hideUnconnected,
    hiddenDevices,
    hideUnconnectedPorts,
    darkMode,
    sinkRoutes,
    resolveSourceName,
    handleTileClick,
    setNodes,
    setEdges,
  ]);

src/features/RoutingDeviceNode.tsx:71

  • This icon-only layout toggle button relies on title for labeling, which is not a reliable accessible name. Add an explicit aria-label (and set type="button" to avoid any accidental form-submit behavior if this component is ever rendered inside a form).
          <button
            className={`nodrag ${styles.layoutToggleBtn}`}
            onClick={(e) => {
              e.stopPropagation();
              onToggleLayoutPanel?.();

src/features/MultiviewLayoutPanel.tsx:72

  • The drag logic registers pointermove/pointerup listeners on window and only removes them on pointerup. If the panel unmounts mid-drag (e.g. route change or close action while dragging), those listeners can remain attached and keep firing, causing leaks and unexpected state updates. Consider using Pointer Capture or an AbortController-based listener registration with a cleanup on unmount.
      window.addEventListener("pointermove", handlePointerMove);
      window.addEventListener("pointerup", handlePointerUp);

Comment thread src/features/Versions.tsx Outdated
ndorin and others added 2 commits July 23, 2026 12:54
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 23, 2026 18:55
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

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

Comments suppressed due to low confidence (1)

src/features/Routing.tsx:670

  • The dagre layout effect is intended to avoid re-running on WebSocket updates, but handleTileClick is in the dependency array and it changes whenever midpointRoutes changes (it depends on midpointRoutes). This will re-run buildGraph/dagre and reset selectedEdgeIds on every routing feedback message, reintroducing layout jitter/selection flicker.
    darkMode,
    sinkRoutes,
    resolveSourceName,
    handleTileClick,
    setNodes,

Comment thread src/features/Routing.tsx
Comment on lines +316 to +320
// Build lookup maps:
// "deviceKey:portKey" → edge that ARRIVES at that input port
const edgeByDestPort = new Map<string, Edge>();
// "deviceKey:portKey" → edge that LEAVES from that output port
const edgeBySrcPort = new Map<string, Edge>();
Comment on lines +51 to +66
<div
key={tile.tileNumber}
className={`${styles.tile}${isEmpty ? ` ${styles.tileEmpty}` : ""}${isSelected ? ` ${styles.tileSelected}` : ""}`}
style={{
left: `${(tile.x / layout.canvasWidth) * 100}%`,
top: `${(tile.y / layout.canvasHeight) * 100}%`,
width: `${(tile.width / layout.canvasWidth) * 100}%`,
height: `${(tile.height / layout.canvasHeight) * 100}%`,
zIndex: tile.zOrder,
}}
title={`Tile ${tile.tileNumber}: ${sourceName}`}
onClick={(e) => {
e.stopPropagation();
onTileClick?.(tile);
}}
>
Comment on lines +91 to +93
<button className={styles.closeBtn} onClick={onClose} title="Close">
&times;
</button>
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.

3 participants