Skip to content

fix: inline editing, edge labels, code panel, and dashboard improvements - #117

Merged
peter6055 merged 19 commits into
mainfrom
fix/issues-115-116-inline-edit
Jul 24, 2026
Merged

peter6055 merged 19 commits into
mainfrom
fix/issues-115-116-inline-edit

Conversation

@peter6055

@peter6055 peter6055 commented Jul 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes issues #115 and #116 — inline editing improvements, edge label visibility, code panel enhancements, and dashboard duplicate feature.

Changes

Editor / Canvas

  • Fix subgraph double-click and multiline label inline edit
  • Highlight subgraph declaration line on canvas click
  • Add duplicate to dashboard, always show list buttons, set tab title
  • Fix highlight for nodes with quoted IDs containing spaces
  • Prevent node IDs starting with L_ from being misidentified as edges
  • Expand edge label clickable area with invisible hit-target rects
  • Show correct edge label when double-clicking to edit
  • Show visible edge label text when double-clicking edges
  • Fix regex corruption when edge label equals destination name

Code Panel

  • Add Copy All and Format buttons to code panel

Testing

  • ✅ 116 unit tests pass
  • ✅ All prepush checks pass (typecheck, lint, format, test, build)
  • ✅ Browser testing verified: node double-click inline edit, edge label display + hit targets, subgraph click, canvas highlight on click, quoted ID handling, Copy All + Format buttons, dashboard duplicate, format reformatting, inline edit Escape cancels

Closes #115, Closes #116

Summary by CodeRabbit

  • New Features
    • Added diagram duplication with “(Copy)” naming, success feedback, and temporary highlighting of the new diagram.
    • Added Format and Copy All controls to the Mermaid code editor.
    • Improved document titles to reflect the current diagram.
  • Bug Fixes
    • Improved Mermaid edge-label selection/editing/hover and made edge-label targets easier to click.
    • Improved flowchart cluster/subgraph and edge navigation from canvas selections (plus more reliable line matching).
    • Made list-view actions consistently visible and accessible.
    • Fixed Mermaid generation escaping for backslashes in class/ER diagrams; tightened link/label parsing.
  • Documentation
    • Expanded operational guidance in agent documentation.
  • Security & Reliability
    • Strengthened ID validation for stored diagram/folder paths and improved telemetry session ID randomness.
    • Expanded and hardened default allowed development origins.

peter6055 added 14 commits June 25, 2026 13:54
When clicking a flowchart subgraph in the canvas, the corresponding
`subgraph <id>` line in the code editor was not highlighted because
`findFlowchartNodeLine` skips structural lines (subgraph/end) and
its declaration regex does not match subgraph syntax.

Add `findFlowchartSubgraphLine` to scan for `subgraph <id>` declarations
specifically, and wire it into the `highlightRange` memo before the
generic flowchart node fallback.
…itle

- Remove hover-opacity from list view action buttons (DiagramCard, FolderCard)
- Add Duplicate action in the three-dot menu on DiagramCard
- Highlight newly duplicated diagram with pulsing animation
- Set editor tab title to "{diagramName} — LiveMaid"
Nodes with quoted ids containing spaces (e.g. "IPsec S2S") failed to
highlight because Mermaid sanitises SVG element ids by stripping quotes
and spaces, so the normalised id (IPsecS2S) could not be found in the
source code.

- findFlowchartNodeLine: add fallback that scans for quoted source ids
  whose space-stripped form matches the sanitised node id
- findFlowchartEdgeLine: extract endpoint ids from the portion before
  the first shape bracket (to skip labels), prefer quoted ids, and
  normalise both sides before comparing
When a flowchart node has an SVG ID that starts with L_ (e.g.
L_CF_AZ_CNAME), isEdgeId() would return true, causing the inline
edit to show the raw ID instead of the actual label text.

Fix: check the DOM element's class before treating the target as
an edge. If the element is a .node or .cluster (not a .flowchart-link
or .edgeLabel), fall through to the generic node text extraction.
When double-clicking a flowchart edge, the inline editor showed the
raw edge ID (e.g. L_CLIENTS_VM3_0) instead of the visible label
(e.g. 'Exit Node: HK').

Root cause: edge labels are rendered in a separate <g class='edgeLabels'>
container, not as children of the edge path element. The SVG fallback
query only searched inside the edge path element, so it found no text.
Additionally, when the dblclick target fell outside the canvas (e.g.
on the code editor textarea), handleEditClick was never called.

Fix:
- Add selectedSvgIdRef for synchronous access to the selected SVG ID
- When result is null (dblclick on external element), use selectedSvgId
  as fallback for DOM element lookup and edge label extraction
- Search for edge labels in the edgeLabels container by matching the
  edge path's position among sibling paths
When double-clicking a flowchart edge on the canvas, the inline editor
displayed the raw edge ID (e.g. L_TPE_VM2_0) or the source-code label
text rather than what the user actually sees on the canvas.

Root causes:
1. Edge labels are rendered in <g class='edgeLabels'>, not as children
   of the edge path element. The SVG fallback searched inside the edge
   path and found no text.
2. getClickedNode couldn't find the edge path when clicking on an
   edgeLabel <g> because it lacks a data-id attribute and the sibling-
   path fallback assumed a different DOM structure.
3. When a dblclick landed on the edgeLabel element, the position-based
   label lookup used edgePaths (which finds <path> elements) but the
   target was a <g>, so edgeIdx was always -1.

Fix:
- In getClickedNode, resolve edgeLabels without data-id by matching
  their position in the edgeLabels container to edge paths in edgePaths.
- In handleEditClick, try SVG DOM label extraction FIRST (what the user
  sees) before falling back to the source-code regex. Handle both
  <path> (hit-target / actual) and <g.edgeLabel> element types when
  finding the label index.
Add two buttons to the left code panel title bar:
- Copy All: copies all code to clipboard with toast feedback
- Format: cleans up whitespace and re-indents Mermaid code based on
  block structure (subgraph, loop, alt, opt, par, critical, break,
  rect, section blocks, with else/and/option at same level)
matchFlowchartLinkLine's regex used non-greedy matching after the
connector, which stopped too early when the label text was the same
as the destination node name. For example, 'MEL ===|VM2|VM2' was
parsed with middle='===|' instead of '===|VM2|', causing
updateLinkStyleAndLabel to produce 'MEL ===|VM2|VM2|VM2'.

Fix: change the post-connector [^\n]*? to greedy [^\n]* so the
regex captures the full connector + label before the destination.

Also add a guard in handleEditSubmit to skip the edge label update
when the label hasn't changed, avoiding unnecessary re-renders.
@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@peter6055, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 44e1b1da-1b47-4669-b113-3b4a2bb44b16

📥 Commits

Reviewing files that changed from the base of the PR and between 114daf5 and 978352f.

⛔ Files ignored due to path filters (1)
  • smoke-test-1-editor.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • src/components/editor/LiveMaidEditor.tsx
  • src/hooks/useCanvasInteraction.ts
  • src/lib/api/storageFsAdapter.ts
  • src/lib/diagrams/erDiagram.tsx
  • src/lib/telemetry/index.ts
📝 Walkthrough

Walkthrough

The PR updates Mermaid selection and inline editing, adds source formatting and copying controls, introduces dashboard diagram duplication with visual feedback, hardens storage and serialization handling, strengthens telemetry fallback generation, expands development-origin defaults, and revises repository workflow guidance.

Changes

Editor interaction improvements

Layer / File(s) Summary
Edge hit targets and selection resolution
src/hooks/useEditorState.ts, src/hooks/useCanvasInteraction.ts, src/components/editor/EditorCanvas.tsx, src/app/globals.css
Edge-label hit targets, SVG selection, cluster targeting, and selection state synchronization are updated.
Flowchart source mapping and inline saves
src/lib/diagrams/*, src/components/editor/LiveMaidEditor.tsx
Subgraph, quoted node, and edge line matching are added or refined; multiline saves and unchanged-edge handling are updated.
Source formatting and clipboard controls
src/components/editor/EditorCodePanel.tsx
The editor toolbar adds Mermaid formatting and source-copy actions with toast feedback.

Dashboard diagram duplication

Layer / File(s) Summary
Duplicate action and visual feedback
src/components/Dashboard.tsx, src/components/DiagramCard.tsx
Diagram cards expose duplication, the dashboard creates and inserts copies, and duplicated cards receive temporary highlighting.
List-view action visibility
src/components/DiagramCard.tsx, src/components/FolderCard.tsx
List-view action menus are rendered without hover-only visibility behavior.

Data and runtime hardening

Layer / File(s) Summary
Storage identifiers and Mermaid string escaping
src/lib/api/storageFsAdapter.ts, src/lib/diagrams/classDiagram.tsx, src/lib/diagrams/erDiagram.tsx
Filesystem IDs are validated and backslashes are escaped in generated Mermaid strings.
Session identifier fallback
src/lib/telemetry/index.ts
The non-UUID session identifier fallback uses cryptographic random values.

Development guidance and configuration

Layer / File(s) Summary
Operational and validation guidance
AGENTS.md
Repository instructions are expanded for commands, architecture, frameworks, testing, servers, verification, git, and pre-push checks.
Development-origin defaults
next.config.ts
Fallback allowed development origins are centralized and expanded while environment parsing remains supported.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested reviewers: peter6055w

Poem

I’m a rabbit with code in my paws,
Hopping through diagrams, fixing their flaws.
Copies now sparkle, edges click bright,
Text formats neatly and titles take flight.
Secure little strings keep the burrow just right.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes many unrelated changes such as dashboard duplication, code-panel tools, telemetry, and storage validation. Split the unrelated dashboard, code-panel, telemetry, and storage updates into separate PRs focused on #115 and #116.
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and clearly reflects the main areas changed, including inline editing and related UI improvements.
Linked Issues check ✅ Passed The changes appear to address #115 and #116 by routing subgraph/node editing correctly and rendering multiline labels as real newlines.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issues-115-116-inline-edit

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.

Comment thread src/hooks/useCanvasInteraction.ts Fixed

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/editor/EditorCanvas.tsx (1)

863-873: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the smallest-node fallback scoped to generic container targets

findBestAtPoint() is called in both branches, so this unconditional fallback also overwrites resolved concrete diagram elements with the smallest overlapping .node / .cluster / path.flowchart-link / .edgeLabel. Since the goal is to rescue tiny Mermaid hits that are resolved only as generic containers, keep the fallback in the if branch only.

🤖 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 `@src/components/editor/EditorCanvas.tsx` around lines 863 - 873, The
smallest-node fallback should only run for generic container targets. In the
target-resolution logic, keep the findBestAtPoint() call and target assignment
inside the isGenericContainerTarget branch, and remove the duplicate fallback
from the else branch so resolved concrete diagram elements remain unchanged.
🤖 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 `@AGENTS.md`:
- Around line 96-108: The retry logic after restarting the livemaid-test session
must fail when the server remains unavailable. Update the second polling loop in
the retry block to perform a final readiness check after polling and exit 1 if
curl still cannot reach localhost:3435; preserve the success path and readiness
message when the server becomes available.
- Around line 149-153: Update the pre-commit/push instruction in AGENTS.md to
run npm run prepush with the repository’s required byte-cap mechanism, ensuring
the command’s potentially large output is capped while preserving the mandatory
prepush validation.

In `@next.config.ts`:
- Around line 3-5: Update DEV_ORIGINS_DEFAULTS and the allowedDevOrigins
configuration so the wildcard *.tail1f8d1a.ts.net origin is not enabled by
default; require it to be explicitly supplied through ALLOWED_DEV_ORIGINS, while
preserving any intended narrowly scoped development origin defaults.

In `@src/components/Dashboard.tsx`:
- Around line 419-420: Update the highlight state flow around setHighlightedId
in Dashboard to store the timeout handle in a ref, clear any existing timer
before scheduling a replacement, and ensure the replacement timer clears the
latest highlight only after the full duration. Clean up the active timeout when
the component unmounts.

In `@src/components/editor/EditorCodePanel.tsx`:
- Around line 95-162: Update handleFormat to preserve Mermaid YAML front matter
verbatim, including indentation under nested config, and exclude that region
from trimming, blank-line collapsing, and re-indentation. Remove section from
BLOCK_OPEN so repeated Gantt sections remain at the correct level, and limit
block formatting to constructs supported by the repository’s Mermaid version
rather than applying unverified grammar rules.

In `@src/hooks/useCanvasInteraction.ts`:
- Around line 3492-3496: Escape effectiveRawSvgId with CSS.escape before
interpolating it into the document.querySelector selector in handleEditClick,
matching the other ID-based lookups in this function. Preserve the existing
fallback selection behavior and descendant selector targets while ensuring IDs
containing CSS-special characters do not cause selector parsing errors.

---

Outside diff comments:
In `@src/components/editor/EditorCanvas.tsx`:
- Around line 863-873: The smallest-node fallback should only run for generic
container targets. In the target-resolution logic, keep the findBestAtPoint()
call and target assignment inside the isGenericContainerTarget branch, and
remove the duplicate fallback from the else branch so resolved concrete diagram
elements remain unchanged.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 95272cc1-23b2-419f-adce-e8c718ae711c

📥 Commits

Reviewing files that changed from the base of the PR and between 745f16f and e433ba2.

📒 Files selected for processing (13)
  • AGENTS.md
  • next.config.ts
  • src/app/globals.css
  • src/components/Dashboard.tsx
  • src/components/DiagramCard.tsx
  • src/components/FolderCard.tsx
  • src/components/editor/EditorCanvas.tsx
  • src/components/editor/EditorCodePanel.tsx
  • src/components/editor/LiveMaidEditor.tsx
  • src/hooks/useCanvasInteraction.ts
  • src/hooks/useEditorState.ts
  • src/lib/diagrams/selectionLineMap.ts
  • src/lib/diagrams/utils.ts

Comment thread AGENTS.md
Comment thread AGENTS.md
Comment thread next.config.ts
Comment thread src/components/Dashboard.tsx Outdated
Comment thread src/components/editor/EditorCodePanel.tsx
Comment thread src/hooks/useCanvasInteraction.ts
Comment thread src/components/editor/LiveMaidEditor.tsx Fixed
Comment thread src/lib/api/storageFsAdapter.ts Fixed

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/editor/LiveMaidEditor.tsx (2)

269-275: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid resetting document.title during dependency updates.

The cleanup runs before every doc?.name change, briefly setting the title to "LiveMaid Editor" before the new title is applied. Keep the unmount reset separate from the name-update effect to avoid visible title flicker.

🤖 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 `@src/components/editor/LiveMaidEditor.tsx` around lines 269 - 275, Separate
the document-title update from the unmount cleanup in the LiveMaidEditor effect:
keep the effect keyed by doc?.name responsible only for applying the current
title, and move the “LiveMaid Editor” reset into a mount-only cleanup effect so
dependency updates do not briefly reset the title.

3073-3104: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Normalize multiline text on the cluster rename path too.

The .cluster branch earlier writes raw editingText and bypasses editingTextForSave. Consequently, renaming a subgraph with multiline text can persist literal newlines instead of <br/> formatting, violating the multiline-label behavior. Compute the normalized value before that branch and use it for the cluster declaration replacement as well.

🤖 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 `@src/components/editor/LiveMaidEditor.tsx` around lines 3073 - 3104, The
cluster rename branch should use the same normalized multiline label value as
the regular node path. Compute editingTextForSave before the .cluster handling
and replace the cluster declaration with that value instead of raw editingText,
preserving the existing <br/> conversion behavior.
🤖 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 `@src/lib/api/storageFsAdapter.ts`:
- Around line 68-76: Update validateId to reject empty IDs as invalid, alongside
existing character validation. In getDiagram, move ID validation inside the
existing try/error boundary so invalid route IDs follow the same not-found
behavior as getFolder, while preserving valid read behavior.

In `@src/lib/diagrams/erDiagram.tsx`:
- Line 425: Update parseAttributeParts to unescape doubled backslashes as well
as escaped quotes, using an order that preserves the serialized C:\tmp value
without repeated doubling on save. Add a round-trip test covering a comment
containing backslashes and verify serializeAttributeParts followed by
parseAttributeParts restores the original comment.

In `@src/lib/telemetry/index.ts`:
- Around line 135-137: Update the random identifier fallback in initTelemetry so
it checks that crypto and crypto.getRandomValues are available before invoking
getRandomValues on the Uint32Array. Preserve a non-throwing fallback when either
is unavailable, while retaining the existing randomUUID path when supported.

---

Outside diff comments:
In `@src/components/editor/LiveMaidEditor.tsx`:
- Around line 269-275: Separate the document-title update from the unmount
cleanup in the LiveMaidEditor effect: keep the effect keyed by doc?.name
responsible only for applying the current title, and move the “LiveMaid Editor”
reset into a mount-only cleanup effect so dependency updates do not briefly
reset the title.
- Around line 3073-3104: The cluster rename branch should use the same
normalized multiline label value as the regular node path. Compute
editingTextForSave before the .cluster handling and replace the cluster
declaration with that value instead of raw editingText, preserving the existing
<br/> conversion behavior.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 575e42cc-64ed-412e-87dc-2963c1da1b4d

📥 Commits

Reviewing files that changed from the base of the PR and between e433ba2 and 114daf5.

📒 Files selected for processing (11)
  • AGENTS.md
  • next.config.ts
  • src/components/Dashboard.tsx
  • src/components/editor/EditorCanvas.tsx
  • src/components/editor/EditorCodePanel.tsx
  • src/components/editor/LiveMaidEditor.tsx
  • src/hooks/useCanvasInteraction.ts
  • src/lib/api/storageFsAdapter.ts
  • src/lib/diagrams/classDiagram.tsx
  • src/lib/diagrams/erDiagram.tsx
  • src/lib/telemetry/index.ts
💤 Files with no reviewable changes (2)
  • src/components/editor/EditorCanvas.tsx
  • next.config.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/components/editor/EditorCodePanel.tsx
  • src/components/Dashboard.tsx
  • AGENTS.md
  • src/hooks/useCanvasInteraction.ts

Comment thread src/lib/api/storageFsAdapter.ts Outdated
Comment thread src/lib/diagrams/erDiagram.tsx
Comment thread src/lib/telemetry/index.ts Outdated
@peter6055
peter6055 enabled auto-merge (squash) July 23, 2026 14:31
- Validate empty IDs and move validation inside try/catch in storageFsAdapter
- Guard crypto.getRandomValues availability in telemetry fallback
- Unescape doubled backslashes in erDiagram parseAttributeParts for round-trip
- Separate document-title effect from unmount cleanup to avoid flicker
- Use normalized multiline label for cluster renames
Comment thread src/lib/diagrams/erDiagram.tsx Fixed
- Fix double-unescaping order in erDiagram parseAttributeParts
- Use safeFilePath with path.basename validation in storageFsAdapter
- Escape angle brackets after HTML tag stripping to prevent injection
Comment thread src/components/editor/LiveMaidEditor.tsx Fixed
Comment thread src/hooks/useCanvasInteraction.ts Fixed
@railway-app
railway-app Bot temporarily deployed to livemaid / livemaid-pr-117 July 24, 2026 15:41 Destroyed
@peter6055
peter6055 merged commit 1cb3a2c into main Jul 24, 2026
7 checks passed
@peter6055
peter6055 deleted the fix/issues-115-116-inline-edit branch July 24, 2026 15:47

This branch was successfully deployed

No deployments
livemaid / livemaid-pr-117 — 978352f8 Deployed Jul 24, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants