editable facts in the UI
This commit is contained in:
+86
-12
@@ -11,7 +11,7 @@ import {
|
||||
useMantineTheme,
|
||||
} from "@mantine/core";
|
||||
import { trpc } from "../../../trpc/client";
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
defaultParameters,
|
||||
defaultSystemPrompt,
|
||||
@@ -22,7 +22,7 @@ import { useData } from "vike-react/useData";
|
||||
import type { Data } from "./+data";
|
||||
import type { CommittedMessage, DraftMessage } from "../../../types";
|
||||
import Markdown from "react-markdown";
|
||||
import { IconTrash } from "@tabler/icons-react";
|
||||
import { IconTrash, IconEdit, IconCheck, IconX } from "@tabler/icons-react";
|
||||
|
||||
export default function ChatPage() {
|
||||
const pageContext = usePageContext();
|
||||
@@ -49,6 +49,27 @@ export default function ChatPage() {
|
||||
const removeFactTrigger = useStore((state) => state.removeFactTrigger);
|
||||
const setLoading = useStore((state) => state.setLoading);
|
||||
|
||||
// State for editing facts
|
||||
const [editingFactId, setEditingFactId] = useState<string | null>(null);
|
||||
const [editingFactContent, setEditingFactContent] = useState("");
|
||||
|
||||
// Handle clicking outside to cancel editing
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
if (editingFactId && event.target instanceof Element) {
|
||||
const editingElement = event.target.closest('.editing-fact');
|
||||
if (!editingElement) {
|
||||
setEditingFactId(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [editingFactId]);
|
||||
|
||||
const {
|
||||
conversation,
|
||||
messages: initialMessages,
|
||||
@@ -89,6 +110,16 @@ export default function ChatPage() {
|
||||
await trpc.chat.facts.deleteOne.mutate({ factId });
|
||||
}
|
||||
|
||||
async function handleUpdateFact(factId: string, content: string) {
|
||||
// Update the local state first
|
||||
setFacts(facts.map(fact =>
|
||||
fact.id === factId ? { ...fact, content } : fact
|
||||
));
|
||||
|
||||
// Then update the database
|
||||
await trpc.chat.facts.update.mutate({ factId, content });
|
||||
}
|
||||
|
||||
async function handleDeleteFactTrigger(factTriggerId: string) {
|
||||
removeFactTrigger(factTriggerId);
|
||||
await trpc.chat.factTriggers.deleteOne.mutate({ factTriggerId });
|
||||
@@ -193,16 +224,59 @@ export default function ChatPage() {
|
||||
<List>
|
||||
{facts.map((fact) => (
|
||||
<List.Item key={fact.id}>
|
||||
{fact.content}{" "}
|
||||
<IconTrash
|
||||
size={16}
|
||||
stroke={1.5}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleDeleteFact(fact.id);
|
||||
}}
|
||||
/>
|
||||
{editingFactId === fact.id ? (
|
||||
<Group wrap="nowrap" className="editing-fact">
|
||||
<Textarea
|
||||
value={editingFactContent}
|
||||
onChange={(e) => setEditingFactContent(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
handleUpdateFact(fact.id, editingFactContent);
|
||||
setEditingFactId(null);
|
||||
} else if (e.key === "Escape") {
|
||||
setEditingFactId(null);
|
||||
}
|
||||
}}
|
||||
autoFocus
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
handleUpdateFact(fact.id, editingFactContent);
|
||||
setEditingFactId(null);
|
||||
}}
|
||||
>
|
||||
<IconCheck size={16} />
|
||||
</ActionIcon>
|
||||
<ActionIcon
|
||||
onClick={() => setEditingFactId(null)}
|
||||
>
|
||||
<IconX size={16} />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
) : (
|
||||
<Group wrap="nowrap">
|
||||
<span style={{ flex: 1 }}>{fact.content}</span>
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
setEditingFactId(fact.id);
|
||||
setEditingFactContent(fact.content);
|
||||
}}
|
||||
>
|
||||
<IconEdit size={16} />
|
||||
</ActionIcon>
|
||||
<IconTrash
|
||||
size={16}
|
||||
stroke={1.5}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleDeleteFact(fact.id);
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
</List.Item>
|
||||
))}
|
||||
</List>
|
||||
|
||||
Reference in New Issue
Block a user