Skip to content

Conversation

@DemetrioReyes
Copy link

@DemetrioReyes DemetrioReyes commented Nov 14, 2025

  • Added layer panel enhancements: text filter, show/hide all, persistent presets stored in localStorage, and state synchronization with KLayout.

  • Introduced real-time measurement panel with length/Δx/Δy/angle, ruler export to CSV, and automatic updates from backend events.

  • Implemented quick annotations workflow: “Add Note” prompt tied to last cursor position, notes persisted via WebSocket, and unified overlay displaying both rulers and notes.

Captura de pantalla 2025-11-13 a la(s) 8 36 25 p  m

Summary by Sourcery

Enhance the web viewer by extending the layer panel with search, visibility controls, and persistent presets; introduce a real-time measurement and notes overlay with CSV export; and add a quick annotations workflow tied to cursor position and synchronized with the backend.

New Features:

  • Add layer panel search, show/hide all buttons, and user-defined presets stored in localStorage
  • Introduce measurement overlay displaying length, Δx, Δy, and angle with live updates and CSV export
  • Implement quick note annotations at the last cursor position with WebSocket persistence and unified overlay for rulers and notes

Enhancements:

  • Synchronize layer and annotation state bidirectionally with the KLayout backend

@sourcery-ai
Copy link

sourcery-ai bot commented Nov 14, 2025

Reviewer's Guide

This PR augments the web viewer by adding advanced layer management (filtering, bulk show/hide, persistent presets), a live measurement and annotation overlay with CSV export and quick-note workflow, and backend support for streaming measurements and notes over WebSocket.

Sequence diagram for real-time measurement and note synchronization via WebSocket

sequenceDiagram
    participant Frontend
    participant Backend
    participant "KLayout"
    actor User
    User->>Frontend: Add ruler or note
    Frontend->>Backend: Send annotation event via WebSocket
    Backend->>"KLayout": Update annotation state
    "KLayout"-->>Backend: Triggers annotation changed event
    Backend->>Frontend: Send measurement-update (rulers & notes)
    Frontend->>Frontend: Update overlay with measurements and notes
Loading

Class diagram for new and updated frontend data structures (layer presets, measurements, notes)

classDiagram
    class Layer {
      +id: number
      +name: string
      +v: boolean
      +children: Layer[]
    }
    class LayerPreset {
      +[layerId: number]: boolean
    }
    class Measurement {
      +id: number
      +label: string
      +length: number
      +dx: number
      +dy: number
      +angle: number
      +p1: Point
      +p2: Point
    }
    class Note {
      +id: number
      +text: string
      +position: Point
    }
    class Point {
      +x: number
      +y: number
    }
    Layer "1" -- "*" Layer : children
    Measurement "1" -- "1" Point : p1
    Measurement "1" -- "1" Point : p2
    Note "1" -- "1" Point : position
Loading

Class diagram for updated backend annotation and measurement streaming

classDiagram
    class LayoutViewServerEndpoint {
      +note_category: str
      +viewport_point_to_layout(x, y): DPoint
      +measurement_dump(): list
      +note_dump(): list
      +send_measurements(websocket): None
    }
    class Annotation {
      +id(): int
      +category: str
      +style: str
      +p1: DPoint
      +p2: DPoint
      +text(): str
    }
    LayoutViewServerEndpoint "1" -- "*" Annotation : manages
    Annotation "1" -- "1" DPoint : p1
    Annotation "1" -- "1" DPoint : p2
Loading

File-Level Changes

Change Details Files
Extended layer management with search, visibility toggles, and persistent presets
  • Added search input, clear button, show/hide all buttons, and preset controls in the UI
  • Implemented render, filter, and visibility functions for the layer tree
  • Stored and managed presets in localStorage with load, persist, and apply routines
  • Synchronized preset and layer visibility changes back to the server via WebSocket
src/kweb/static/viewer.js
src/kweb/templates/viewer.html
src/kweb/static/client.css
Introduced real-time measurement and note overlay with export and quick-add
  • Injected measurement/note overlay HTML and corresponding CSS styles
  • Tracked pointer positions and handled WebSocket measurement-update messages
  • Rendered dynamic lists of rulers and notes with formatted values
  • Enabled CSV export of measurement data and quick-add note dialog tied to last pointer
src/kweb/static/viewer.js
src/kweb/templates/viewer.html
src/kweb/static/client.css
Back-end support for streaming measurements and notes
  • Added measurement_dump and note_dump methods to serialize annotations
  • Implemented send_measurements over WebSocket and hooked it to annotation events
  • Handled add-annotation messages to insert new notes into the layout view
  • Triggered measurement updates on cell changes, clear-annotations, and zoom events
src/kweb/layout_server.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `src/kweb/static/viewer.js:611-617` </location>
<code_context>
+  renderLayerTable();
+}
+
+function setVisibilityRecursively(layers, visible) {
+  layers.forEach((layer) => {
+    layer.v = visible;
+    updateLayerVisibilityClassById(layer.id, visible);
+    if (layer.children) {
+      setVisibilityRecursively(layer.children, visible);
+    }
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Check for Array type before recursing into children.

If layer.children is not an array, setVisibilityRecursively may throw. Use Array.isArray(layer.children) to ensure safe recursion.

```suggestion
function setVisibilityRecursively(layers, visible) {
  layers.forEach((layer) => {
    layer.v = visible;
    updateLayerVisibilityClassById(layer.id, visible);
    if (Array.isArray(layer.children)) {
      setVisibilityRecursively(layer.children, visible);
    }
```
</issue_to_address>

### Comment 2
<location> `src/kweb/static/viewer.js:911-917` </location>
<code_context>
+  return { x, y };
+}
+
+function openAnnotationDialog() {
+  if (!canvas || !socket || socket.readyState !== WebSocket.OPEN) {
+    return;
+  }
+  const text = prompt("Nota (se usará la última posición del cursor)", "");
+  if (text === null) {
+    return;
</code_context>

<issue_to_address>
**suggestion:** Prompt text is hardcoded in Spanish.

Consider making the prompt message configurable or localizable to support internationalization.

```suggestion
+// Simple localization/messages object. Extend as needed.
+const messages = {
+  en: {
+    annotationPrompt: "Note (the last cursor position will be used)",
+  },
+  es: {
+    annotationPrompt: "Nota (se usará la última posición del cursor)",
+  },
+  // Add more languages as needed
+};
+
+// Function to get user's language, fallback to 'en'
+function getUserLanguage() {
+  return navigator.language?.slice(0,2) || 'en';
+}
+
+function getMessage(key) {
+  const lang = getUserLanguage();
+  return messages[lang]?.[key] || messages['en'][key];
+}
+
+function openAnnotationDialog() {
+  if (!canvas || !socket || socket.readyState !== WebSocket.OPEN) {
+    return;
+  }
+  const text = prompt(getMessage("annotationPrompt"), "");
+  if (text === null) {
+    return;
```
</issue_to_address>

### Comment 3
<location> `src/kweb/static/viewer.js:902` </location>
<code_context>
  let x = lastPointer.x;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/use-object-destructuring))

```suggestion
  let {x} = lastPointer;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

### Comment 4
<location> `src/kweb/static/viewer.js:903` </location>
<code_context>
  let y = lastPointer.y;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/use-object-destructuring))

```suggestion
  let {y} = lastPointer;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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.

1 participant