Skip to content

feat: editable comments in WorkItem#194

Merged
Flo0806 merged 4 commits intomainfrom
feat/editable-comments-work-item
Mar 6, 2026
Merged

feat: editable comments in WorkItem#194
Flo0806 merged 4 commits intomainfrom
feat/editable-comments-work-item

Conversation

@Flo0806
Copy link
Copy Markdown
Contributor

@Flo0806 Flo0806 commented Mar 6, 2026

Summary

  • Make comments (also sub comments) editable and deletable

Related issue(s)

Closes #192

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • CI

Checklist

  • Tests added/updated
  • i18n keys added/updated (if needed)
  • No breaking changes

Summary by CodeRabbit

  • New Features

    • Inline edit and delete for timeline comments, review comments, and replies with confirmation modal and per-item action controls based on permissions
    • Permission-aware UI (show/hide edit & delete actions) and editing state flows
  • Localization

    • Added English and German strings for edit/delete actions, confirmations, success and error toasts, and save label
  • Tests

    • Added unit tests covering comment and review-comment edit/delete behaviors

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 6, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4836da4-2aa6-474e-917d-f03b51403d0d

📥 Commits

Reviewing files that changed from the base of the PR and between c2e052a and 26925b0.

📒 Files selected for processing (4)
  • app/components/timeline/EditActions.vue
  • app/composables/useWorkItemMutations.ts
  • shared/utils/timeline-mappers.ts
  • test/unit/workItemMutations.test.ts

📝 Walkthrough

Walkthrough

Adds edit/delete workflows to work item timelines: UI components (edit actions, delete modal), mutation composable, server endpoints for review comment patch/delete, permission propagation through mappings/types, page wiring, i18n keys, and unit tests — enabling inline comment editing and deletion.

Changes

Cohort / File(s) Summary
Timeline UI Components
app/components/timeline/CommentCard.vue, app/components/timeline/EditActions.vue, app/components/timeline/DeleteModal.vue
Add edit/delete UI and props (viewerCanUpdate, viewerCanDelete, isEditing, editDisabled), emit edit lifecycle events, and include a confirmation modal.
Timeline Integration & Pages
app/components/timeline/ReviewCommentThread.vue, app/pages/repos/[owner]/[repo]/work-items/[id].vue
Wire per-item edit/delete controls into threads and page, handle edit/delete events, pass permission flags to timeline items, and connect handlers to composable.
Mutation Composable & Mappers
app/composables/useWorkItemMutations.ts, shared/utils/timeline-mappers.ts
New composable exposing start/cancel/save/delete handlers; new pure helpers to edit/remove comments and review comments in timeline arrays.
Server API Routes
server/api/issues/body.patch.ts, server/api/issues/comments.patch.ts, server/api/issues/comments.delete.ts, server/api/pull-requests/review-comments.patch.ts, server/api/pull-requests/review-comments.delete.ts
Extend issue body endpoint to handle pulls, add/extend comment patch/delete routes for issues and review comments, and optionally invalidate work item cache when workItemId is provided.
Types & Mappings
shared/types/work-item.ts, server/utils/review-replies.ts, server/api/repository/[owner]/[repo]/work-items/[id].get.ts
Add viewerCanUpdate / viewerCanDelete flags to timeline and review comment types and propagate them through reply builders and timeline mappers.
Localization & Schema
i18n/locales/en.json, i18n/locales/de.json, i18n/schema.json
Add translation keys for edit/delete actions, confirmation prompts, success/error messages, and update schema entries.
Tests
test/unit/workItemMutations.test.ts, test/unit/reviewReplies.test.ts
Add unit tests for timeline mutation helpers and for mapping permission flags onto review replies.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as CommentCard / ReviewThread
    participant Composable as useWorkItemMutations
    participant Server as API Server
    participant GitHub as GitHub API
    participant Cache as WorkItem Cache

    User->>UI: Click Edit
    UI->>Composable: startEdit(entryId)
    Composable->>Composable: set editingId

    User->>UI: Save edited body
    UI->>Composable: saveComment(entryId, body)
    Composable->>Server: PATCH /issues/comments or /pull-requests/review-comments (body)
    Server->>GitHub: Update comment
    GitHub-->>Server: Updated comment
    Server->>Cache: invalidateWorkItemDetailCache(workItemId?)
    Server-->>Composable: success
    Composable->>UI: update timeline (emit/notify)

    User->>UI: Click Delete
    UI->>UI: Open DeleteModal → Confirm
    UI->>Composable: deleteComment(entryId)
    Composable->>Server: DELETE /issues/comments or /pull-requests/review-comments
    Server->>GitHub: Delete comment
    GitHub-->>Server: 204
    Server->>Cache: invalidateWorkItemDetailCache(workItemId?)
    Server-->>Composable: success
    Composable->>UI: remove entry from timeline
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #180: Overlaps timeline UI and editing props/events in CommentCard.vue and ReviewCommentThread.vue — likely touching same client-side flows.
  • PR #177: Updates review-replies and type propagation for viewer permissions; strongly related to permission flag changes.
  • PR #75: Implements related comment edit/delete server endpoints and cache invalidation patterns used here.

Suggested reviewers

  • Gonzo17

Poem

🐰
I nibble keys and patch the thread,
Edit, save — no words left unsaid,
A modal hop, a tidy prune,
Timeline blossoms, gone too soon,
Hooray for edits — carrot cake and code!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: editable comments in WorkItem' clearly and concisely summarizes the main feature addition: enabling comment editing in the Work Item timeline.
Description check ✅ Passed The PR description covers the summary, related issue, type of change, and checklist; however, it lacks detailed explanation of what changed and why, falling short of the template's intent.
Linked Issues check ✅ Passed All core requirements from issue #192 are implemented: edit/delete UI for comments and review comments, new server endpoints, permission flags in GraphQL, and composable integration.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #192 requirements; no out-of-scope modifications detected beyond the defined edit/delete comment feature.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/editable-comments-work-item

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

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

🧹 Nitpick comments (4)
server/api/pull-requests/review-comments.delete.ts (1)

19-30: Prefer githubFetchWithToken for consistency with sibling endpoints.

Line 19 through Line 30 manually re-implements GitHub request/error behavior that is already centralized and used by server/api/pull-requests/review-comments.patch.ts.

Suggested refactor
-import { getSessionToken, invalidateWorkItemDetailCache } from '~~/server/utils/github'
+import { getSessionToken, githubFetchWithToken, invalidateWorkItemDetailCache } from '~~/server/utils/github'
@@
-  const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/pulls/comments/${commentId}`, {
-    method: 'DELETE',
-    headers: {
-      'Authorization': `token ${token}`,
-      'Accept': 'application/vnd.github+json',
-      'X-GitHub-Api-Version': '2022-11-28',
-    },
-  })
-
-  if (!response.ok) {
-    throw createError({ statusCode: response.status, message: `GitHub API ${response.status}: ${response.statusText}` })
-  }
+  await githubFetchWithToken(
+    token,
+    `/repos/${owner}/${repo}/pulls/comments/${commentId}`,
+    { method: 'DELETE' },
+  )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/api/pull-requests/review-comments.delete.ts` around lines 19 - 30,
Replace the manual fetch/delete call with the shared helper githubFetchWithToken
used by sibling endpoints (e.g., review-comments.patch.ts): call
githubFetchWithToken with the DELETE method and the path
`repos/${owner}/${repo}/pulls/comments/${commentId}`, pass the token, and rely
on the helper to throw or return a normalized response so you can remove the
manual response.ok check and createError logic; ensure the function still
returns/forwards the helper's result or error so calling code behavior remains
unchanged.
server/api/issues/body.patch.ts (1)

71-73: Guard issue-detail cache invalidation to issue updates only.

Line 71 through Line 73 runs even for type === 'pull'. You can skip this invalidation for pull updates to avoid unnecessary cache operations.

Suggested tweak
-  if (repo && issueNumber) {
+  if (type !== 'pull' && repo && issueNumber) {
     await invalidateIssueDetailCache(login, repo, issueNumber)
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/api/issues/body.patch.ts` around lines 71 - 73, The
invalidateIssueDetailCache call is executed for pull updates too; guard it so it
only runs for issue updates by checking the incoming event type (e.g., only when
type === 'issue' or type !== 'pull') before calling
invalidateIssueDetailCache(login, repo, issueNumber). Update the conditional
that currently checks repo && issueNumber to also verify the event type
(reference variables type, repo, issueNumber and function
invalidateIssueDetailCache) so pull events skip this invalidation.
server/api/repository/[owner]/[repo]/work-items/[id].get.ts (1)

160-161: Remove or map unused PullRequestReview permission fields.

Line 160 and Line 161 fetch viewerCanUpdate/viewerCanDelete, but Line 485 through Line 494 does not propagate them into the timeline entry. Either map them or drop them from the query to avoid payload/confusion drift.

Also applies to: 485-494

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

In `@server/api/repository/`[owner]/[repo]/work-items/[id].get.ts around lines 160
- 161, The query currently selects PullRequestReview fields viewerCanUpdate and
viewerCanDelete but the timeline mapping (the code that builds timeline entries
for PullRequestReview) does not include them; either remove these fields from
the GraphQL selection or add them into the timeline entry object so they are
propagated. Locate the PullRequestReview selection (viewerCanUpdate,
viewerCanDelete) and either drop those two fields, or update the timeline-entry
construction code that maps PullRequestReview into the timeline (the mapping
that creates the timeline entry object for PullRequestReview) to include
viewerCanUpdate and viewerCanDelete properties so the fetched permissions are
actually used.
app/composables/useWorkItemMutations.ts (1)

87-89: Consider logging errors for debugging.

The catch blocks silently discard errors after showing a toast. Logging the error would aid debugging in production.

Example for one catch block
-    catch {
+    catch (err) {
+      console.error('Failed to save comment:', err)
       toast.add({ title: t('workItems.timeline.editError'), color: 'error' })
     }

Also applies to: 111-113, 149-151, 183-185

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

In `@app/composables/useWorkItemMutations.ts` around lines 87 - 89, The catch
blocks currently swallow errors; update each catch (including the one that shows
t('workItems.timeline.editError') and the other similar blocks at the other
ranges) to accept the thrown error (e) and log it before showing the toast—e.g.,
call console.error with a brief context string (like "Failed to edit work item
timeline") and the error object so stack/details are preserved; do this for all
catch blocks in useWorkItemMutations.ts that currently just show a toast so
debugging information is available.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/components/timeline/EditActions.vue`:
- Around line 26-34: The icon-only UButton controls (the edit and delete
buttons) lack accessible names; update the UButton instances (the one with
`@click`="emit('edit')" and the delete button at lines 40–47) to include explicit
aria-label attributes (e.g., aria-label="Edit item" and aria-label="Delete item"
or localized equivalents) so screen readers can announce their purpose; ensure
the aria-label text clearly describes the action and remains present even when
:disabled (use plain aria-label or :aria-label binding if you need i18n).

In `@app/components/timeline/ReviewCommentThread.vue`:
- Around line 57-67: saveEdit currently clears editingCommentId.value and
editBody.value immediately after emitting edit events (emit('editComment'...) /
emit('editReply'...)), which loses user input if the parent/API save fails;
instead, stop clearing those local editing states in saveEdit and let the parent
signal success to clear them (either by switching to a parent-controlled
editingId prop or by accepting a success callback/ack event from the parent).
Locate saveEdit, editingCommentId, and editBody in ReviewCommentThread.vue and
remove the immediate clearing there; implement/expect a parent-driven clear
(e.g., parent updates a prop or emits an 'editSaved' event that the component
listens for to set editingCommentId.value = null and editBody.value = '').

In `@app/composables/useWorkItemMutations.ts`:
- Around line 166-179: The deletion flow currently removes the root comment from
the timeline (see updateTimeline mapping that filters reviewComments by
commentId and filters replies) but GitHub only deletes the single comment ID so
replies remain orphaned; add a unit/integration test that deletes a root comment
with replies and asserts that child replies still exist in the backend DB to
reproduce the issue, then fix by either (A) updating the delete handler to
enumerate and delete child replies after the root deletion (call the API to
delete each reply id found under reviewComments.replies for the given
entryId/commentId) or (B) explicitly document/accept orphaned replies; target
code symbols to change: the frontend mutation updateTimeline, the backend delete
handler that calls GitHub, and any test file for work item mutations to include
the new test case that references entryId, commentId, reviewComments, and
replies.

In `@test/unit/workItemMutations.test.ts`:
- Around line 37-77: Tests currently re-implement mutation helpers
(editCommentBody, deleteComment, editReviewComment, deleteReviewComment) instead
of using the production implementations from useWorkItemMutations; remove these
duplicated functions from test/unit/workItemMutations.test.ts and import the
shared mutation helpers used by the composable (or extract those helpers from
useWorkItemMutations into a small exported util module) so the tests exercise
the real mutation logic rather than a test-local copy.

---

Nitpick comments:
In `@app/composables/useWorkItemMutations.ts`:
- Around line 87-89: The catch blocks currently swallow errors; update each
catch (including the one that shows t('workItems.timeline.editError') and the
other similar blocks at the other ranges) to accept the thrown error (e) and log
it before showing the toast—e.g., call console.error with a brief context string
(like "Failed to edit work item timeline") and the error object so stack/details
are preserved; do this for all catch blocks in useWorkItemMutations.ts that
currently just show a toast so debugging information is available.

In `@server/api/issues/body.patch.ts`:
- Around line 71-73: The invalidateIssueDetailCache call is executed for pull
updates too; guard it so it only runs for issue updates by checking the incoming
event type (e.g., only when type === 'issue' or type !== 'pull') before calling
invalidateIssueDetailCache(login, repo, issueNumber). Update the conditional
that currently checks repo && issueNumber to also verify the event type
(reference variables type, repo, issueNumber and function
invalidateIssueDetailCache) so pull events skip this invalidation.

In `@server/api/pull-requests/review-comments.delete.ts`:
- Around line 19-30: Replace the manual fetch/delete call with the shared helper
githubFetchWithToken used by sibling endpoints (e.g., review-comments.patch.ts):
call githubFetchWithToken with the DELETE method and the path
`repos/${owner}/${repo}/pulls/comments/${commentId}`, pass the token, and rely
on the helper to throw or return a normalized response so you can remove the
manual response.ok check and createError logic; ensure the function still
returns/forwards the helper's result or error so calling code behavior remains
unchanged.

In `@server/api/repository/`[owner]/[repo]/work-items/[id].get.ts:
- Around line 160-161: The query currently selects PullRequestReview fields
viewerCanUpdate and viewerCanDelete but the timeline mapping (the code that
builds timeline entries for PullRequestReview) does not include them; either
remove these fields from the GraphQL selection or add them into the timeline
entry object so they are propagated. Locate the PullRequestReview selection
(viewerCanUpdate, viewerCanDelete) and either drop those two fields, or update
the timeline-entry construction code that maps PullRequestReview into the
timeline (the mapping that creates the timeline entry object for
PullRequestReview) to include viewerCanUpdate and viewerCanDelete properties so
the fetched permissions are actually used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 707e4d2e-3183-44d0-89f0-289b80a18df0

📥 Commits

Reviewing files that changed from the base of the PR and between 9a4e6ac and c2e052a.

📒 Files selected for processing (19)
  • app/components/timeline/CommentCard.vue
  • app/components/timeline/DeleteModal.vue
  • app/components/timeline/EditActions.vue
  • app/components/timeline/ReviewCommentThread.vue
  • app/composables/useWorkItemMutations.ts
  • app/pages/repos/[owner]/[repo]/work-items/[id].vue
  • i18n/locales/de.json
  • i18n/locales/en.json
  • i18n/schema.json
  • server/api/issues/body.patch.ts
  • server/api/issues/comments.delete.ts
  • server/api/issues/comments.patch.ts
  • server/api/pull-requests/review-comments.delete.ts
  • server/api/pull-requests/review-comments.patch.ts
  • server/api/repository/[owner]/[repo]/work-items/[id].get.ts
  • server/utils/review-replies.ts
  • shared/types/work-item.ts
  • test/unit/reviewReplies.test.ts
  • test/unit/workItemMutations.test.ts

Comment on lines +57 to +67
function saveEdit(comment: ReviewComment, type: 'comment' | 'reply') {
if (!editBody.value.trim() || !comment.databaseId) return
if (type === 'comment') {
emit('editComment', comment.id, comment.databaseId, editBody.value)
}
else {
emit('editReply', comment.id, comment.databaseId, editBody.value)
}
editingCommentId.value = null
editBody.value = ''
}
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.

⚠️ Potential issue | 🟡 Minor

Editing state cleared before confirming save success.

saveEdit clears editingCommentId and editBody immediately after emitting, before the parent confirms the save succeeded. If the API call fails, the user's edits are lost and they'd need to re-enter their changes.

Consider keeping the editing state until the parent signals success (e.g., via a prop change or callback), or accept this as intentional optimistic UX where failures are rare.

Alternative: Let parent control editing state

One approach is to have the parent pass an editingId prop (similar to CommentCard.vue) and control clearing it only after a successful save:

-function saveEdit(comment: ReviewComment, type: 'comment' | 'reply') {
-  if (!editBody.value.trim() || !comment.databaseId) return
-  if (type === 'comment') {
-    emit('editComment', comment.id, comment.databaseId, editBody.value)
-  }
-  else {
-    emit('editReply', comment.id, comment.databaseId, editBody.value)
-  }
-  editingCommentId.value = null
-  editBody.value = ''
-}
+function saveEdit(comment: ReviewComment, type: 'comment' | 'reply') {
+  if (!editBody.value.trim() || !comment.databaseId) return
+  if (type === 'comment') {
+    emit('editComment', comment.id, comment.databaseId, editBody.value)
+  }
+  else {
+    emit('editReply', comment.id, comment.databaseId, editBody.value)
+  }
+  // Let parent clear editing state on success
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/timeline/ReviewCommentThread.vue` around lines 57 - 67,
saveEdit currently clears editingCommentId.value and editBody.value immediately
after emitting edit events (emit('editComment'...) / emit('editReply'...)),
which loses user input if the parent/API save fails; instead, stop clearing
those local editing states in saveEdit and let the parent signal success to
clear them (either by switching to a parent-controlled editingId prop or by
accepting a success callback/ack event from the parent). Locate saveEdit,
editingCommentId, and editBody in ReviewCommentThread.vue and remove the
immediate clearing there; implement/expect a parent-driven clear (e.g., parent
updates a prop or emits an 'editSaved' event that the component listens for to
set editingCommentId.value = null and editBody.value = '').

Comment on lines +166 to +179
updateTimeline(timeline =>
timeline.map((e) => {
if (e.id !== entryId) return e
return {
...e,
reviewComments: e.reviewComments
?.filter(rc => rc.id !== commentId)
.map(rc => ({
...rc,
replies: rc.replies?.filter(r => r.id !== commentId),
})),
}
}),
)
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n -A 10 "deleteReviewComment|deletePullRequestReviewComment" --type ts --glob '!node_modules/**'

Repository: flumen-dev/flumen.dev

Length of output: 6203


🏁 Script executed:

# Search for the mutation/API call definition in the composable
rg -n "deleteReviewComment" app/composables/useWorkItemMutations.ts -A 20

Repository: flumen-dev/flumen.dev

Length of output: 847


🏁 Script executed:

# Look for related GraphQL mutations or API calls that might handle the deletion
fd -e ts -e graphql . --exec grep -l "deleteReviewComment\|deletePullRequestReviewComment" {} \;

Repository: flumen-dev/flumen.dev

Length of output: 144


🏁 Script executed:

# Find the backend API handler for review comments deletion
fd -e ts -e js . --path "*/api/*" --exec grep -l "review-comments" {} \;

Repository: flumen-dev/flumen.dev

Length of output: 298


🏁 Script executed:

# Search for the backend handler more broadly
rg -n "review-comments" --type ts --type js --glob '!node_modules/**' | head -20

Repository: flumen-dev/flumen.dev

Length of output: 844


🏁 Script executed:

# Look for database models or cascade delete configurations
rg -n "cascade|onDelete|orphan" --type ts --glob '!node_modules/**' -i

Repository: flumen-dev/flumen.dev

Length of output: 207


🏁 Script executed:

# Find the server/API implementation directory
find . -type d -name "server" -o -name "api" -o -name "routes" | grep -v node_modules | head -20

Repository: flumen-dev/flumen.dev

Length of output: 102


🏁 Script executed:

# Search for the actual API route handler
rg -n "review-comments" --type ts --glob '!node_modules/**' -B 5 -A 15 | grep -A 15 "DELETE\|delete"

Repository: flumen-dev/flumen.dev

Length of output: 1408


🏁 Script executed:

# Look in common API directories for route definitions
ls -la server/ 2>/dev/null || ls -la app/ 2>/dev/null || find . -maxdepth 3 -name "*.ts" -path "*/api/*" | head -20

Repository: flumen-dev/flumen.dev

Length of output: 399


🏁 Script executed:

# List the server/api directory structure
find server/api -type f -name "*.ts" | head -30

Repository: flumen-dev/flumen.dev

Length of output: 1271


🏁 Script executed:

# Search for pull-requests review-comments API handler
rg -n "review-comments\|ReviewComment" server/ --type ts -A 10

Repository: flumen-dev/flumen.dev

Length of output: 47


🏁 Script executed:

# Read the delete handler for review comments
cat -n server/api/pull-requests/review-comments.delete.ts

Repository: flumen-dev/flumen.dev

Length of output: 1483


Backend leaves orphaned replies when a root comment is deleted.

The backend delegates deletion to GitHub's API (lines 19-26), which only deletes the specified comment ID. When a root comment with replies is deleted, GitHub does not cascade-delete the replies—they remain in the database as orphaned entities. The frontend's updateTimeline removes the parent from the timeline, implicitly hiding the replies from the UI, but the orphaned data persists in the backend.

The existing tests do not cover this scenario. Add a test case that verifies deletion of a root comment with replies and confirm whether the application should:

  1. Explicitly delete orphaned replies via separate API calls, or
  2. Accept orphaned replies as acceptable technical debt
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/composables/useWorkItemMutations.ts` around lines 166 - 179, The deletion
flow currently removes the root comment from the timeline (see updateTimeline
mapping that filters reviewComments by commentId and filters replies) but GitHub
only deletes the single comment ID so replies remain orphaned; add a
unit/integration test that deletes a root comment with replies and asserts that
child replies still exist in the backend DB to reproduce the issue, then fix by
either (A) updating the delete handler to enumerate and delete child replies
after the root deletion (call the API to delete each reply id found under
reviewComments.replies for the given entryId/commentId) or (B) explicitly
document/accept orphaned replies; target code symbols to change: the frontend
mutation updateTimeline, the backend delete handler that calls GitHub, and any
test file for work item mutations to include the new test case that references
entryId, commentId, reviewComments, and replies.

@Flo0806 Flo0806 merged commit 1b0180b into main Mar 6, 2026
8 of 10 checks passed
@Flo0806 Flo0806 deleted the feat/editable-comments-work-item branch March 6, 2026 17:22
@coderabbitai coderabbitai bot mentioned this pull request Mar 15, 2026
8 tasks
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.

Work Items: Edit/Delete comments in timeline

1 participant