Commit
•
3a63ab8
1
Parent(s):
184689c
✨ Title edit (#135)
Browse filesCo-authored-by: Victor Mustar <victor.mustar@gmail.com>
src/lib/components/NavMenu.svelte
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
|
6 |
import Logo from "$lib/components/icons/Logo.svelte";
|
7 |
import CarbonTrashCan from "~icons/carbon/trash-can";
|
8 |
-
import
|
9 |
|
10 |
import { switchTheme } from "$lib/switchTheme";
|
11 |
import { PUBLIC_ORIGIN } from "$env/static/public";
|
@@ -13,6 +13,7 @@
|
|
13 |
const dispatch = createEventDispatcher<{
|
14 |
shareConversation: { id: string; title: string };
|
15 |
deleteConversation: string;
|
|
|
16 |
}>();
|
17 |
|
18 |
export let conversations: Array<{
|
@@ -36,7 +37,7 @@
|
|
36 |
<div
|
37 |
class="scrollbar-custom flex flex-col gap-1 overflow-y-auto rounded-r-xl bg-gradient-to-l from-gray-50 px-3 pb-3 pt-2 dark:from-gray-800/30"
|
38 |
>
|
39 |
-
{#each conversations as conv}
|
40 |
<a
|
41 |
data-sveltekit-noscroll
|
42 |
href="{base}/conversation/{conv.id}"
|
@@ -50,11 +51,14 @@
|
|
50 |
<button
|
51 |
type="button"
|
52 |
class="flex h-5 w-5 items-center justify-center rounded md:hidden md:group-hover:flex"
|
53 |
-
title="
|
54 |
-
on:click|preventDefault={() =>
|
55 |
-
|
|
|
|
|
|
|
56 |
>
|
57 |
-
<
|
58 |
</button>
|
59 |
|
60 |
<button
|
|
|
5 |
|
6 |
import Logo from "$lib/components/icons/Logo.svelte";
|
7 |
import CarbonTrashCan from "~icons/carbon/trash-can";
|
8 |
+
import CarbonEdit from "~icons/carbon/edit";
|
9 |
|
10 |
import { switchTheme } from "$lib/switchTheme";
|
11 |
import { PUBLIC_ORIGIN } from "$env/static/public";
|
|
|
13 |
const dispatch = createEventDispatcher<{
|
14 |
shareConversation: { id: string; title: string };
|
15 |
deleteConversation: string;
|
16 |
+
editConversationTitle: { id: string; title: string };
|
17 |
}>();
|
18 |
|
19 |
export let conversations: Array<{
|
|
|
37 |
<div
|
38 |
class="scrollbar-custom flex flex-col gap-1 overflow-y-auto rounded-r-xl bg-gradient-to-l from-gray-50 px-3 pb-3 pt-2 dark:from-gray-800/30"
|
39 |
>
|
40 |
+
{#each conversations as conv (conv.id)}
|
41 |
<a
|
42 |
data-sveltekit-noscroll
|
43 |
href="{base}/conversation/{conv.id}"
|
|
|
51 |
<button
|
52 |
type="button"
|
53 |
class="flex h-5 w-5 items-center justify-center rounded md:hidden md:group-hover:flex"
|
54 |
+
title="Edit conversation title"
|
55 |
+
on:click|preventDefault={() => {
|
56 |
+
const newTitle = prompt("Edit this conversation title:", conv.title);
|
57 |
+
if (!newTitle) return;
|
58 |
+
dispatch("editConversationTitle", { id: conv.id, title: newTitle });
|
59 |
+
}}
|
60 |
>
|
61 |
+
<CarbonEdit class="text-xs text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" />
|
62 |
</button>
|
63 |
|
64 |
<button
|
src/routes/+layout.svelte
CHANGED
@@ -62,6 +62,28 @@
|
|
62 |
}
|
63 |
}
|
64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
onDestroy(() => {
|
66 |
clearTimeout(errorToastTimeout);
|
67 |
});
|
@@ -91,6 +113,7 @@
|
|
91 |
conversations={data.conversations}
|
92 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
93 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
|
|
94 |
/>
|
95 |
</MobileNav>
|
96 |
<nav class="grid max-h-screen grid-cols-1 grid-rows-[auto,1fr,auto] max-md:hidden">
|
@@ -98,6 +121,7 @@
|
|
98 |
conversations={data.conversations}
|
99 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
100 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
|
|
101 |
/>
|
102 |
</nav>
|
103 |
{#if currentError}
|
|
|
62 |
}
|
63 |
}
|
64 |
|
65 |
+
async function editConversationTitle(id: string, title: string) {
|
66 |
+
try {
|
67 |
+
const res = await fetch(`${base}/conversation/${id}`, {
|
68 |
+
method: "PATCH",
|
69 |
+
headers: {
|
70 |
+
"Content-Type": "application/json",
|
71 |
+
},
|
72 |
+
body: JSON.stringify({ title }),
|
73 |
+
});
|
74 |
+
|
75 |
+
if (!res.ok) {
|
76 |
+
$error = "Error while editing title, try again.";
|
77 |
+
return;
|
78 |
+
}
|
79 |
+
|
80 |
+
await invalidate(UrlDependency.ConversationList);
|
81 |
+
} catch (err) {
|
82 |
+
console.error(err);
|
83 |
+
$error = String(err);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
onDestroy(() => {
|
88 |
clearTimeout(errorToastTimeout);
|
89 |
});
|
|
|
113 |
conversations={data.conversations}
|
114 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
115 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
116 |
+
on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)}
|
117 |
/>
|
118 |
</MobileNav>
|
119 |
<nav class="grid max-h-screen grid-cols-1 grid-rows-[auto,1fr,auto] max-md:hidden">
|
|
|
121 |
conversations={data.conversations}
|
122 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
123 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
124 |
+
on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)}
|
125 |
/>
|
126 |
</nav>
|
127 |
{#if currentError}
|
src/routes/conversation/[id]/+server.ts
CHANGED
@@ -11,6 +11,7 @@ import { trimSuffix } from "$lib/utils/trimSuffix.js";
|
|
11 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
12 |
import { error } from "@sveltejs/kit";
|
13 |
import { ObjectId } from "mongodb";
|
|
|
14 |
|
15 |
export async function POST({ request, fetch, locals, params }) {
|
16 |
// todo: add validation on params.id
|
@@ -164,3 +165,28 @@ async function parseGeneratedText(
|
|
164 |
|
165 |
return res;
|
166 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
12 |
import { error } from "@sveltejs/kit";
|
13 |
import { ObjectId } from "mongodb";
|
14 |
+
import { z } from "zod";
|
15 |
|
16 |
export async function POST({ request, fetch, locals, params }) {
|
17 |
// todo: add validation on params.id
|
|
|
165 |
|
166 |
return res;
|
167 |
}
|
168 |
+
|
169 |
+
export async function PATCH({request, locals, params}) {
|
170 |
+
const {title} = z.object({title: z.string().trim().min(1).max(100)}).parse(await request.json())
|
171 |
+
|
172 |
+
const convId = new ObjectId(params.id);
|
173 |
+
|
174 |
+
const conv = await collections.conversations.findOne({
|
175 |
+
_id: convId,
|
176 |
+
sessionId: locals.sessionId,
|
177 |
+
});
|
178 |
+
|
179 |
+
if (!conv) {
|
180 |
+
throw error(404, "Conversation not found");
|
181 |
+
}
|
182 |
+
|
183 |
+
await collections.conversations.updateOne({
|
184 |
+
_id: convId,
|
185 |
+
}, {
|
186 |
+
$set: {
|
187 |
+
title,
|
188 |
+
}
|
189 |
+
});
|
190 |
+
|
191 |
+
return new Response();
|
192 |
+
}
|