deletable messages

master
Avraham Sakal 1 month ago
parent d0902e9df1
commit b20c48ce0a

@ -493,7 +493,7 @@ export default function ChatPage() {
<Tabs.Tab value="fact-triggers">Fact Triggers</Tabs.Tab> <Tabs.Tab value="fact-triggers">Fact Triggers</Tabs.Tab>
</Tabs.List> </Tabs.List>
<Tabs.Panel value="message"> <Tabs.Panel value="message">
<Messages messages={messages || []} /> <Messages />
<Textarea <Textarea
resize="vertical" resize="vertical"
placeholder="Type your message here..." placeholder="Type your message here..."
@ -670,12 +670,92 @@ export default function ChatPage() {
); );
} }
function Messages({ function Messages() {
messages,
}: {
messages: Array<DraftMessage | CommittedMessage>;
}) {
const theme = useMantineTheme(); const theme = useMantineTheme();
const queryClient = useQueryClient();
const trpc = useTRPC();
const pageContext = usePageContext();
const conversationId = pageContext.routeParams.id;
const messagesResult = useQuery(
trpc.chat.messages.fetchByConversationId.queryOptions({
conversationId,
})
);
const messages: Array<DraftMessage | CommittedMessage> | undefined =
messagesResult.data?.map((m) => ({
...m,
parts: m.parts.filter((p) => p.type === "text"),
})) || [];
const deleteMessage = useMutation(
trpc.chat.messages.deleteOne.mutationOptions({
onMutate: async ({ id: messageIdToDelete }) => {
/** Cancel affected queries that may be in-flight: */
await queryClient.cancelQueries({
queryKey: trpc.chat.messages.fetchByConversationId.queryKey({
conversationId,
}),
});
/** Optimistically update the affected queries in react-query's cache: */
const previousMessages = await queryClient.getQueryData(
trpc.chat.messages.fetchByConversationId.queryKey({
conversationId,
})
);
if (!previousMessages) {
return {
previousMessages: [],
newMessages: [],
};
}
const newMessages = previousMessages.filter(
(m: CommittedMessage) => m.id !== messageIdToDelete
);
queryClient.setQueryData(
trpc.chat.messages.fetchByConversationId.queryKey({
conversationId,
}),
newMessages
);
return { previousMessages, newMessages };
},
onSettled: async (data, variables, context) => {
await queryClient.invalidateQueries({
queryKey: trpc.chat.messages.fetchByConversationId.queryKey({
conversationId,
}),
});
},
onError: async (error, variables, context) => {
console.error(error);
if (!context) return;
queryClient.setQueryData(
trpc.chat.messages.fetchByConversationId.queryKey({
conversationId,
}),
context.previousMessages
);
},
})
);
async function handleDeleteMessage(message: DraftMessage | CommittedMessage) {
// If the message does not have an id, do nothing
if (!("id" in message) || !message.id) {
return;
}
// Delete the message from the server using the mutation
try {
await deleteMessage.mutateAsync({ id: message.id });
} catch (error) {
console.error("Failed to delete message:", error);
}
}
return ( return (
<Stack gap="md" justify="flex-start"> <Stack gap="md" justify="flex-start">
{messages.map((message, index) => ( {messages.map((message, index) => (
@ -708,16 +788,17 @@ function Messages({
</HoverCard.Target> </HoverCard.Target>
<HoverCard.Dropdown> <HoverCard.Dropdown>
<ActionIcon.Group> <ActionIcon.Group>
<ActionIcon size="lg" variant="filled" color="red"> <ActionIcon
<IconTrash size="lg"
size={16} variant="filled"
stroke={1.5} color="red"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
// handleDeleteMessage(message.id); handleDeleteMessage(message);
}} }}
/> >
<IconTrash size={16} stroke={1.5} />
</ActionIcon> </ActionIcon>
</ActionIcon.Group> </ActionIcon.Group>
</HoverCard.Dropdown> </HoverCard.Dropdown>

@ -54,6 +54,12 @@ export const messages = router({
.query(async ({ input: { conversationId } }) => { .query(async ({ input: { conversationId } }) => {
return await db.messages.findByConversationId(conversationId); return await db.messages.findByConversationId(conversationId);
}), }),
deleteOne: publicProcedure
.input((x) => x as { id: string })
.mutation(async ({ input: { id } }) => {
await db.messages.delete(id);
return { success: true };
}),
generateRunningSummary: publicProcedure generateRunningSummary: publicProcedure
.input( .input(
(x) => (x) =>

Loading…
Cancel
Save