Skip to content

fix: prevent comment overwrite on note save + improve maintenance UX#122

Merged
ryota-murakami merged 2 commits intomainfrom
fix/comment-overwrite-maintenance-ux
Feb 17, 2026
Merged

fix: prevent comment overwrite on note save + improve maintenance UX#122
ryota-murakami merged 2 commits intomainfrom
fix/comment-overwrite-maintenance-ux

Conversation

@ryota-murakami
Copy link
Contributor

@ryota-murakami ryota-murakami commented Feb 17, 2026

Summary

  • P0 Fix: useNoteModal.save() was hardcoding comment: '' in upsertProjectInfo, destroying existing comments whenever a user saved a note. Made comment optional in ProjectInfoData so the upsert skips the field when undefined.
  • P1 Maintenance UX: Replaced inline DropdownMenu in maintenance grid view with the shared OverflowMenu component. Added onDelete prop to OverflowMenu for maintenance context. Added keyboard shortcuts (. menu toggle, Enter open note, Escape close menu) to maintenance cards matching the RepoCard pattern.

Changes

File Change
shared-project-info.ts ProjectInfoData.comment → optional; upsert skips when undefined
useNoteModal.ts Removed comment: '' from save (the bug)
useMaintenanceNoteModal.ts Simplified: removed comments prop workaround
OverflowMenu.tsx Added onDelete prop with destructive styling for maintenance
MaintenanceClient.tsx Shared OverflowMenu + tabIndex + onKeyDown keyboard shortcuts
useNoteModal.test.ts Updated assertion (no comment in save call)
MaintenanceClient.test.tsx Updated window.open assertion for noopener,noreferrer

Test plan

  • pnpm typecheck — pass
  • pnpm lint — pass (zero warnings)
  • pnpm test — 1282/1282 pass
  • pnpm build — pass
  • pnpm e2e:parallel — no maintenance/note-modal regressions (pre-existing DB timeout flakes in unrelated tests)

Summary by CodeRabbit

  • New Features

    • Per-card overflow menu replaced previous menu and now includes a Delete action.
    • Keyboard shortcuts for maintenance cards: period toggles menu, Enter opens the note modal, Escape closes the menu.
  • Improvements

    • Better keyboard accessibility with focus outlines and tab navigation.
    • Streamlined note save behavior: empty comment is no longer sent when saving project notes.
  • Tests

    • Updated tests to reflect overflow menu link behavior.

P0: useNoteModal.save() was hardcoding comment: '' in upsertProjectInfo,
destroying existing comments whenever a user saved a note. Made comment
optional in ProjectInfoData so upsert skips it when undefined.

P1: Replace inline DropdownMenu in maintenance grid view with shared
OverflowMenu component. Add keyboard shortcuts (., Enter, Escape) to
maintenance cards matching the RepoCard pattern. Add onDelete prop to
OverflowMenu for maintenance context.
@vercel
Copy link
Contributor

vercel bot commented Feb 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gitbox Ready Ready Preview, Comment Feb 17, 2026 2:59pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Replaced per-card DropdownMenu with a new OverflowMenu and per-card openMenuId state; added keyboard shortcuts ('.' to toggle menu, Enter to open note modal, Escape to close); removed comments parameter from useMaintenanceNoteModal; made project-info comment optional and omitted empty comment from upserts.

Changes

Cohort / File(s) Summary
Maintenance UI & Interactions
src/app/maintenance/MaintenanceClient.tsx, src/components/Board/OverflowMenu.tsx
Replaced per-card DropdownMenu with OverflowMenu; added openMenuId state, per-card tabIndex/focus handlers and keyboard bindings ('.', Enter, Escape); wired onDelete?: (id: string) => void into OverflowMenu and rendered Delete action when provided.
Maintenance Hook Simplification
src/app/maintenance/hooks/useMaintenanceNoteModal.ts
Removed comments parameter and UseMaintenanceNoteModalProps; useMaintenanceNoteModal() now takes no args; handleProjectInfoSave no longer forwards a comment payload.
Project Info Data Layer & Hook
src/lib/actions/shared-project-info.ts, src/hooks/board/useNoteModal.ts
Made ProjectInfoData.comment optional; validation and upsert now conditionally include comment only when defined; useNoteModal save path omits empty comment field in upsert payload.
Tests
src/tests/unit/app/maintenance/MaintenanceClient.test.tsx, src/tests/unit/hooks/useNoteModal.test.ts
Updated assertions: window.open call includes noopener,noreferrer from OverflowMenu; adjusted expected upsert payload to remove empty comment field.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MaintenanceClient as MaintenanceClient (UI)
  participant OverflowMenu as OverflowMenu (menu)
  participant NoteModal as NoteModal (modal)
  participant API as UpsertProjectInfo (backend)

  User->>MaintenanceClient: Focus / press '.' on card
  MaintenanceClient->>OverflowMenu: toggle openMenuId -> open
  User->>OverflowMenu: Select "Add/Edit Note"
  OverflowMenu->>MaintenanceClient: request open note modal (cardId)
  MaintenanceClient->>NoteModal: show modal (selectedRepoForNote, note)
  User->>NoteModal: Submit note
  NoteModal->>API: upsertProjectInfo({ note, links })  -- (no empty comment)
  API-->>NoteModal: success
  NoteModal-->>MaintenanceClient: close modal / update UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

✨ Menus swapped, a dot will call,
Enter opens notes for all,
Escape will hush the open tray,
Comments now optional—light the way,
Per-card focus sings the new display.

🚥 Pre-merge checks | ✅ 3
✅ 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 accurately summarizes the two main objectives: fixing a comment overwrite bug and improving maintenance UX with keyboard/accessibility enhancements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/comment-overwrite-maintenance-ux

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.

@morph-subagents
Copy link

🤖 Morph Preview Test

Looks like you hit your rate limits!

Please upgrade your limits here, or wait a few minutes and try again.

If you need help, reach out to support@morphllm.com.


Automated testing by Morph

@codecov-commenter
Copy link

codecov-commenter commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 64.28571% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.12%. Comparing base (651031c) to head (683c2eb).

Files with missing lines Patch % Lines
src/app/maintenance/MaintenanceClient.tsx 50.00% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #122      +/-   ##
==========================================
- Coverage   72.21%   72.12%   -0.09%     
==========================================
  Files         143      143              
  Lines        4214     4233      +19     
  Branches     1097     1137      +40     
==========================================
+ Hits         3043     3053      +10     
- Misses       1150     1159       +9     
  Partials       21       21              

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@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: 1

🧹 Nitpick comments (1)
src/components/Board/OverflowMenu.tsx (1)

209-223: Delete action skips confirmation dialog — intentional delegation to caller.

Unlike onRemove which uses the internal AlertDialog, onDelete fires directly. This works because MaintenanceClient wraps it with DeleteMaintenanceDialog. Just noting the asymmetry — if onDelete is ever reused without an external confirmation dialog, items will be deleted without warning.

A brief JSDoc note on the prop (e.g., "caller is responsible for confirmation") would make this contract explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Board/OverflowMenu.tsx` around lines 209 - 223, The Delete
menu item calls onDelete(cardId) directly which relies on the caller to present
confirmation (unlike onRemove which uses the internal AlertDialog); add a JSDoc
comment to the onDelete prop in the OverflowMenu component clearly stating that
the caller is responsible for presenting a confirmation dialog (e.g., reference
that MaintenanceClient uses DeleteMaintenanceDialog) so future consumers know
the contract and won't accidentally delete without confirmation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/maintenance/MaintenanceClient.tsx`:
- Around line 167-183: Remove the dead check e.key === 'Period' inside
handleCardKeyDown and only treat the period shortcut as e.key === '.'; also
prevent that shortcut from toggling openMenuId when the component is in list
view by gating the setOpenMenuId call with the view state (e.g., check
isListView or viewMode before calling setOpenMenuId), or alternatively render
the OverflowMenu in list view for consistent behavior; keep the Enter and Escape
behavior unchanged (openNoteModal and clearing openMenuId) and ensure references
to openMenuId and OverflowMenu are used to locate where to apply the guard.

---

Nitpick comments:
In `@src/components/Board/OverflowMenu.tsx`:
- Around line 209-223: The Delete menu item calls onDelete(cardId) directly
which relies on the caller to present confirmation (unlike onRemove which uses
the internal AlertDialog); add a JSDoc comment to the onDelete prop in the
OverflowMenu component clearly stating that the caller is responsible for
presenting a confirmation dialog (e.g., reference that MaintenanceClient uses
DeleteMaintenanceDialog) so future consumers know the contract and won't
accidentally delete without confirmation.

CodeRabbit review: e.key === 'Period' is dead code (e.key yields '.',
not 'Period'). Also gate the dot shortcut to grid view only since list
view doesn't render OverflowMenu.
@github-actions
Copy link

github-actions bot commented Feb 17, 2026

🧪 E2E Coverage Report (Sharded: 12 parallel jobs)

Metric Coverage
Lines 94.38%
Functions 17.72%
Branches 16.97%
Statements 30.52%

📊 Full report available in workflow artifacts

@morph-subagents
Copy link

🤖 Morph Preview Test

Looks like you hit your rate limits!

Please upgrade your limits here, or wait a few minutes and try again.

If you need help, reach out to support@morphllm.com.


Automated testing by Morph

@ryota-murakami ryota-murakami merged commit dc73326 into main Feb 17, 2026
20 checks passed
@ryota-murakami ryota-murakami deleted the fix/comment-overwrite-maintenance-ux branch February 17, 2026 15:10
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.

2 participants