Skip to content

Commit

Permalink
add ability to edit a conversation title (#1921)
Browse files Browse the repository at this point in the history
* add ability to edit a conversation title

* cleanup comments

* insane div centering + mutate

* use dark icons
  • Loading branch information
fontanierh authored Oct 3, 2023
1 parent 9211f98 commit 1a3353e
Showing 1 changed file with 117 additions and 5 deletions.
122 changes: 117 additions & 5 deletions front/components/assistant/conversation/ConversationTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import {
ArrowUpOnSquareIcon,
Avatar,
Button,
CheckIcon,
ClipboardCheckIcon,
DropdownMenu,
IconButton,
LinkStrokeIcon,
PencilSquareIcon,
TrashIcon,
XMarkIcon,
} from "@dust-tt/sparkle";
import React, { useState } from "react";
import React, { MouseEvent, useRef, useState } from "react";
import { useSWRConfig } from "swr";

import { useConversation } from "@app/lib/swr";
import { WorkspaceType } from "@app/types/user";
Expand All @@ -23,7 +28,14 @@ export function ConversationTitle({
shareLink: string;
onDelete?: () => void;
}) {
const { mutate } = useSWRConfig();

const [copyLinkSuccess, setCopyLinkSuccess] = useState<boolean>(false);
const [isEditingTitle, setIsEditingTitle] = useState<boolean>(true);
const [editedTitle, setEditedTitle] = useState<string>("");

const titleInputFocused = useRef(false);
const saveButtonFocused = useRef(false);

const handleClick = async () => {
await navigator.clipboard.writeText(shareLink || "");
Expand All @@ -39,16 +51,116 @@ export function ConversationTitle({
workspaceId: owner.sId,
});

const onTitleChange = async (title: string) => {
try {
const res = await fetch(
`/api/w/${owner.sId}/assistant/conversations/${conversationId}`,
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title,
visibility: conversation?.visibility,
}),
}
);
await mutate(
`/api/w/${owner.sId}/assistant/conversations/${conversationId}`
);
void mutate(`/api/w/${owner.sId}/assistant/conversations`);
if (!res.ok) {
throw new Error("Failed to update title");
}
setIsEditingTitle(false);
setEditedTitle("");
} catch (e) {
alert("Failed to update title");
}
};

if (isConversationLoading || isConversationError || !conversation) {
return null;
}

return (
<div className="grid h-full max-w-full grid-cols-[1fr,auto] items-center gap-4">
<div className="overflow-hidden truncate">
<span className="font-bold">{conversation?.title || ""}</span>
</div>
<div className="grid h-full min-w-0 max-w-full grid-cols-[1fr,auto] items-center gap-4">
<div className="flex min-w-0 flex-row items-center gap-4">
{!isEditingTitle ? (
<div className="min-w-0 overflow-hidden truncate">
<span className="font-bold">{conversation?.title || ""}</span>
</div>
) : (
<div className="flex-grow">
<input
className="w-full rounded-md font-bold"
value={editedTitle}
onChange={(e) => setEditedTitle(e.target.value)}
// We need to make sure the click on the save button below
// is registered before the onBlur event, so we keep track of the
// focus state of both the input and the save button.
onFocus={() => (titleInputFocused.current = true)}
onBlur={() => {
setTimeout(() => {
if (!saveButtonFocused.current) {
setIsEditingTitle(false);
}
titleInputFocused.current = false;
}, 0);
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
return onTitleChange(editedTitle);
}
}}
autoFocus
/>
</div>
)}

{isEditingTitle ? (
<div className="flex flex-row">
<div
onClick={(e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
return onTitleChange(editedTitle);
}}
// See comment on the input above.
onFocus={() => (saveButtonFocused.current = true)}
onBlur={() => {
setTimeout(() => {
if (!titleInputFocused.current) {
setIsEditingTitle(false);
}
saveButtonFocused.current = false;
}, 0);
}}
className="flex items-center"
>
<IconButton icon={CheckIcon} variant="secondary" />
</div>
<IconButton
icon={XMarkIcon}
onClick={() => {
setIsEditingTitle(false);
setEditedTitle("");
}}
variant="secondary"
/>
</div>
) : (
<IconButton
icon={PencilSquareIcon}
onClick={() => {
setEditedTitle(conversation?.title || "");
setIsEditingTitle(true);
}}
size="sm"
variant="secondary"
/>
)}
</div>
<div className="flex items-center gap-6">
<div className="hidden lg:flex">
<Avatar.Stack
Expand Down

0 comments on commit 1a3353e

Please sign in to comment.