coyotte508 HF staff victor HF staff commited on
Commit
3a63ab8
1 Parent(s): 184689c

✨ Title edit (#135)

Browse files

Co-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 CarbonExport from "~icons/carbon/export";
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="Share conversation"
54
- on:click|preventDefault={() =>
55
- dispatch("shareConversation", { id: conv.id, title: conv.title })}
 
 
 
56
  >
57
- <CarbonExport class="text-xs text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" />
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
+ }