Mind map can be edited while locked #156
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard#156
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When a mind map object is locked, the user can still edit it via the right-click context menu (Add Comment / Add Child / Delete Node) and possibly other paths. Locking should prevent all edits — only inspection and selection should remain.
Expected
When
WhiteboardObjects.isLocked(group.id())is true:+/−toggle does nothing.+button does nothing.Actual
Most click handlers already gate on
WhiteboardObjects.isLocked(group.id())(collapse toggle, add-child button, comment icon click, double-click to edit), but:onNodeContextMenuhandler does not check lock — the per-node right-click menu opens and its actions run unconditionally.Repro
Notes
The lock-respecting pattern used elsewhere in
mindmap.js:Apply the same gate to
onNodeContextMenu(and verify any other un-gated entry points for editing).Implementation Spec
Root cause
renderMindmapand helpers wire per-node interaction handlers indrawNodes. Most begin with the standard guard:But the per-node
contextmenuhandleronNodeContextMenu(mindmap.js ~L427) does not. Because that handler is wired to every per-node sub-shape and callse.evt.stopPropagation()+e.cancelBubble = true, right-clicking a node on a locked mind map suppresses the document-level standard menu and opens the per-node menu — Add/Edit Comment, Add Child, Delete Node all fully functional.Two secondary gaps:
showCommentPopupSave/Remove buttons never re-checkisLocked. The popup is detached DOM; can survive asetLocked(id, true)arriving over the wire.addChildToNode/deleteNode/flipDirection/toggleCollapseRootdon't gate themselves. Today every caller is gated, but defense-in-depth costs a couple of lines each.Audit (mindmap.js)
titleTextdblclick →editMindmapTitledirBtnclick →flipDirectionindicatorclick (collapse)addBtnclick →addChildToNodecommentIconclick →showCommentPopupnodeRect/labeldblclick →editMindmapNodeonNodeContextMenu(per-node menu)editMindmapNode/editMindmapTitleblur saveshowCommentPopupSave / Remove handlersaddChildToNode/deleteNode/flipDirection/toggleCollapseRoot(function-level)dragstart/dragendgroup.draggable(false)fromsetLockedStandard menu's locked behavior
contextmenu.jsshows the canvas menu for locked objects with destructive items hidden and the Lock item rewritten as Unlock. The mind-map per-node menu has no Unlock equivalent and every item is destructive (mutates the tree). Cleanest match: defer to the standard canvas menu when locked. InonNodeContextMenu, if locked, justreturn— withoutstopPropagation/preventDefault— and the document-level handler incontextmenu.jswill fire the standard menu.Approach: per-handler gates
Matches existing style. Every other gated site uses the literal
if (typeof WhiteboardObjects !== 'undefined' && ...isLocked(group.id())) return;pattern (7 occurrences). Adding the same line at the un-gated sites keeps the codebase greppable and avoids churning the recently-landede3c4cb8(#154) and92f9859(#155).Files to Modify
crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js— only file.Implementation Plan
Step 1 — Primary fix: gate
onNodeContextMenuClosing this issue as filed.
Step 2 — Defense-in-depth at function level
Add the standard guard as the first line of:
addChildToNode(group, node)deleteNode(group, nodeData)flipDirection(group)toggleCollapseRoot(group)(
addChildToRootdelegates toaddChildToNode— covered transitively.)Step 3 — Edge case: discard pending edits if locked between open and commit
In the blur / Save / Remove handlers of
editMindmapNode,editMindmapTitle, andshowCommentPopup: skip the mutation andWhiteboardSync.onUpdate(group)whenisLockedreturns true at commit time, but still tear down the DOM cleanly.Dependencies: none.
Acceptance Criteria
addChildToNode/deleteNode/flipDirection/toggleCollapseRootare no-ops when called against a locked group, even outside wired handlers.setLocked(id, true)arrives while an inline editor / comment popup is open, the next blur/Save discards the edit (noWhiteboardSync.onUpdate); the popup/editor still closes cleanly.What NOT to break
e3c4cb8(#154 wiring): all fivecontextmenuregistrations on per-node shapes remain.92f9859(#155 unification): per-node menu items andWhiteboardContextMenu.showintegration unchanged — they simply aren't reached when locked.Validation
cargo check --workspacecargo test --workspace --libImplementation summary
Changes
crates/hero_whiteboard_ui/static/web/js/whiteboard/mindmap.js— added the standardWhiteboardObjects.isLocked(group.id())guard at 9 new sites (going from 7 → 16 gated sites). All edits use the exact existing guard pattern so the codebase remains greppable.onNodeContextMenu: early-return BEFOREpreventDefault/stopPropagation, so right-clicks on a locked mindmap fall through to the document-level handler incontextmenu.jsand show the standard canvas/object menu (with Unlock).addChildToNode,deleteNode,flipDirection,toggleCollapseRoot— any future caller (programmatic, scripted) is also gated.editMindmapNodeblur,editMindmapTitleblur,showCommentPopupSave, andshowCommentPopupRemove: ifsetLockedarrives over the wire while an editor or popup is open, the next blur/click discards the edit (noWhiteboardSync.onUpdate) but still tears the DOM down cleanly.The 7 pre-existing guards and the wiring from
e3c4cb8(#154) and92f9859(#155) are untouched.Validation
cargo check --workspace: passcargo test --workspace --lib: passNotes
UI-only change. Verify: