Add context menu to delete private notes in conversation view

Right-clicking a private note shows a "Delete note" option that calls the
DELETE endpoint and removes the note from the UI. The context menu trigger is
disabled for non-private messages (browser default menu shown instead).

[Used Claude Code 🤖]
This commit is contained in:
josephsellers
2026-06-18 11:33:19 +01:00
parent b699cacd30
commit da20825e2b
4 changed files with 40 additions and 1 deletions
+3
View File
@@ -330,6 +330,8 @@ const getConversationMessage = (cuuid, uuid) =>
http.get(`/api/v1/conversations/${cuuid}/messages/${uuid}`)
const retryMessage = (cuuid, uuid) =>
http.put(`/api/v1/conversations/${cuuid}/messages/${uuid}/retry`)
const deleteMessage = (cuuid, uuid) =>
http.delete(`/api/v1/conversations/${cuuid}/messages/${uuid}`)
const getConversationMessages = (uuid, params) =>
http.get(`/api/v1/conversations/${uuid}/messages`, { params, abortOnRoute: true })
const sendMessage = (uuid, data) =>
@@ -606,6 +608,7 @@ export default {
createConversation,
sendMessage,
retryMessage,
deleteMessage,
createUser,
createInbox,
updateInbox,
@@ -1,4 +1,6 @@
<template>
<ContextMenu>
<ContextMenuTrigger as-child :disabled="!isPrivateMessage">
<div class="flex flex-col text-left" :class="isOutgoing ? 'items-end' : 'items-start'">
<!-- Sender Name -->
<div
@@ -186,6 +188,14 @@
</Tooltip>
</div>
</div>
</ContextMenuTrigger>
<ContextMenuContent v-if="isPrivateMessage">
<ContextMenuItem class="text-destructive focus:text-destructive" @click="deleteNote">
<Trash2 class="mr-2 h-4 w-4" />
{{ t('conversation.deletePrivateNote') }}
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
</template>
<script setup>
@@ -193,7 +203,13 @@ import { computed, ref, onMounted, nextTick } from 'vue'
import { useConversationStore } from '@main/stores/conversation'
import { useUserStore } from '@main/stores/user'
import { useI18n } from 'vue-i18n'
import { Lock, Mail, RotateCcw, Check, Maximize2 } from 'lucide-vue-next'
import { Lock, Mail, RotateCcw, Check, Maximize2, Trash2 } from 'lucide-vue-next'
import {
ContextMenu,
ContextMenuTrigger,
ContextMenuContent,
ContextMenuItem
} from '@shared-ui/components/ui/context-menu'
import { Tooltip, TooltipContent, TooltipTrigger } from '@shared-ui/components/ui/tooltip'
import { Spinner } from '@shared-ui/components/ui/spinner'
import { formatMessageTimestamp, formatFullTimestamp } from '@shared-ui/utils/datetime.js'
@@ -252,6 +268,11 @@ const convStore = useConversationStore()
const { t } = useI18n()
const userStore = useUserStore()
// Delete a private note via the API (only private notes can be deleted).
const deleteNote = () => {
convStore.deleteMessage(convStore.current?.uuid, props.message.uuid)
}
const isSystemUser = computed(() => props.message.author?.email === 'System')
const canManageUsers = computed(() => !isSystemUser.value && userStore.can('users:manage'))
@@ -505,6 +505,19 @@ export const useConversationStore = defineStore('conversation', () => {
}
}
async function deleteMessage (conversationUUID, messageUUID) {
try {
await api.deleteMessage(conversationUUID, messageUUID)
messages.data.removeMessage(conversationUUID, messageUUID)
incrementMessageVersion()
} catch (error) {
emitter.emit(EMITTER_EVENTS.SHOW_TOAST, {
variant: 'destructive',
description: handleHTTPError(error).message
})
}
}
function fetchNextConversations () {
if (conversations.fetching || !conversations.hasMore) return
fetchConversationsList(false, conversations.listType, conversations.teamID, conversations.listFilters, conversations.viewID, conversations.page + 1)
@@ -1159,6 +1172,7 @@ export const useConversationStore = defineStore('conversation', () => {
setDraft,
removeDraft,
hasDraft,
deleteMessage,
addPendingMessage,
replacePendingMessage,
removePendingMessage,
+1
View File
@@ -489,6 +489,7 @@
"conversation.bulkActions.toolbar": "Bulk actions toolbar",
"conversation.couldNotFetch": "Could not fetch conversations",
"conversation.downloadTranscript": "Download transcript",
"conversation.deletePrivateNote": "Delete note",
"conversation.hideQuotedText": "Hide quoted text",
"conversation.mentions": "Mentions",
"conversation.myInbox": "My inbox",