Skip to content

Commit b07860c

Browse files
committed
add confirmation dialog for custom persona chats
1 parent b7f9acf commit b07860c

File tree

5 files changed

+119
-78
lines changed

5 files changed

+119
-78
lines changed

web/src/app/chat/components/projects/ProjectChatSessionList.tsx

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { ChatBubbleIcon } from "@/components/icons/CustomIcons";
66
import { ChatSessionMorePopup } from "@/components/sidebar/ChatSessionMorePopup";
77
import { useProjectsContext } from "../../projects/ProjectsContext";
88
import { ChatSession } from "@/app/chat/interfaces";
9-
import { InfoIcon } from "@/components/icons/icons";
109
import { AssistantIcon } from "@/components/assistants/AssistantIcon";
1110
import { useAssistantsContext } from "@/components/context/AssistantsContext";
1211
import {
@@ -96,36 +95,6 @@ export default function ProjectChatSessionList() {
9695
>
9796
{chat.name || "Unnamed Chat"}
9897
</span>
99-
{(() => {
100-
const personaIdToDefault =
101-
currentProjectDetails?.persona_id_to_is_default ||
102-
{};
103-
const isDefault = personaIdToDefault[chat.persona_id];
104-
if (isDefault === false) {
105-
return (
106-
<TooltipProvider>
107-
<Tooltip>
108-
<TooltipTrigger asChild>
109-
<div className="flex items-center text-amber-600 dark:text-yellow-500 cursor-default flex-shrink-0">
110-
<InfoIcon
111-
size={14}
112-
className="text-amber-600 dark:text-yellow-500"
113-
/>
114-
</div>
115-
</TooltipTrigger>
116-
<TooltipContent side="top" align="center">
117-
<p className="max-w-[220px] text-sm">
118-
Project files and instructions aren&apos;t
119-
applied here because this chat uses a
120-
custom assistant.
121-
</p>
122-
</TooltipContent>
123-
</Tooltip>
124-
</TooltipProvider>
125-
);
126-
}
127-
return null;
128-
})()}
12998
</div>
13099
<div className="flex items-center">
131100
{hoveredChatId === chat.id && (
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"use client";
2+
3+
import { Modal } from "../Modal";
4+
import { Button } from "../ui/button";
5+
import { Checkbox } from "../ui/checkbox";
6+
import { InfoIcon } from "../icons/icons";
7+
import { useState } from "react";
8+
9+
interface MoveCustomAgentChatModalProps {
10+
isOpen: boolean;
11+
onCancel: () => void;
12+
onConfirm: (doNotShowAgain: boolean) => void;
13+
}
14+
15+
export default function MoveCustomAgentChatModal({
16+
isOpen,
17+
onCancel,
18+
onConfirm,
19+
}: MoveCustomAgentChatModalProps) {
20+
const [doNotShowAgain, setDoNotShowAgain] = useState(false);
21+
22+
if (!isOpen) return null;
23+
24+
return (
25+
<Modal onOutsideClick={onCancel} width="rounded-xl max-w-lg w-full">
26+
<div className="space-y-5 text-onyx-medium">
27+
<div className="flex flex-col gap-2">
28+
<InfoIcon size={24} />
29+
<h2 className="text-2xl font-bold">Move Custom Agent Chat</h2>
30+
</div>
31+
32+
<p className="text-base">
33+
This chat uses a <b>custom agent</b> and moving it to a <b>project</b>{" "}
34+
will not override the agent&apos;s prompt or knowledge configurations.
35+
This should only be used for organization purposes.
36+
</p>
37+
<div className="flex items-center justify-between gap-2 pt-2">
38+
<div className="flex items-center gap-2">
39+
<Checkbox
40+
id="move-custom-agent-do-not-show"
41+
checked={doNotShowAgain}
42+
onCheckedChange={(checked) => setDoNotShowAgain(Boolean(checked))}
43+
/>
44+
<label htmlFor="move-custom-agent-do-not-show" className="text-sm">
45+
Do not show this again
46+
</label>
47+
</div>
48+
<div className="flex gap-2">
49+
<Button onClick={onCancel} variant="outline">
50+
Cancel
51+
</Button>
52+
<Button onClick={() => onConfirm(doNotShowAgain)}>
53+
Confirm Move
54+
</Button>
55+
</div>
56+
</div>
57+
</div>
58+
</Modal>
59+
);
60+
}

web/src/components/sidebar/ChatSessionDisplay.tsx

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,7 @@ import { ShareChatSessionModal } from "@/app/chat/components/modal/ShareChatSess
1616
import { SettingsContext } from "@/components/settings/SettingsProvider";
1717
import { WarningCircle } from "@phosphor-icons/react";
1818
import { CustomTooltip } from "@/components/tooltip/CustomTooltip";
19-
import { InfoIcon } from "@/components/icons/icons";
20-
import {
21-
Tooltip,
22-
TooltipContent,
23-
TooltipProvider,
24-
TooltipTrigger,
25-
} from "@/components/ui/tooltip";
19+
// removed Info tooltip imports as we no longer show custom assistant info icon
2620

2721
export function ChatSessionDisplay({
2822
chatSession,
@@ -35,7 +29,6 @@ export function ChatSessionDisplay({
3529
parentFolderName,
3630
showDragHandle = true,
3731
projectId,
38-
isCustomAssistant,
3932
}: {
4033
chatSession: ChatSession;
4134
isSelected: boolean;
@@ -47,7 +40,6 @@ export function ChatSessionDisplay({
4740
parentFolderName?: string;
4841
showDragHandle?: boolean;
4942
projectId?: number;
50-
isCustomAssistant?: boolean;
5143
}) {
5244
const router = useRouter();
5345
const [isHovered, setIsHovered] = useState(false);
@@ -209,26 +201,6 @@ export function ChatSessionDisplay({
209201
} `}
210202
/>
211203
</p>
212-
{isCustomAssistant && (
213-
<TooltipProvider>
214-
<Tooltip>
215-
<TooltipTrigger asChild>
216-
<div className="my-auto text-amber-600 dark:text-yellow-500">
217-
<InfoIcon
218-
size={14}
219-
className="text-amber-600 dark:text-yellow-500"
220-
/>
221-
</div>
222-
</TooltipTrigger>
223-
<TooltipContent side="top" align="center">
224-
<p className="max-w-[220px] text-sm">
225-
Project files and instructions aren’t applied here
226-
because this chat uses a custom assistant.
227-
</p>
228-
</TooltipContent>
229-
</Tooltip>
230-
</TooltipProvider>
231-
)}
232204
</>
233205
)}
234206

web/src/components/sidebar/ChatSessionMorePopup.tsx

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import { FiEdit2, FiMoreHorizontal, FiShare2, FiTrash } from "react-icons/fi";
1414
import { HiOutlineArrowUturnRight } from "react-icons/hi2";
1515
import { useChatContext } from "@/components/context/ChatContext";
1616
import { useCallback, useState } from "react";
17+
import MoveCustomAgentChatModal from "@/components/modals/MoveCustomAgentChatModal";
18+
19+
// Constants
20+
const DEFAULT_PERSONA_ID = 0;
21+
const LS_HIDE_MOVE_CUSTOM_AGENT_MODAL_KEY = "onyx:hideMoveCustomAgentModal";
1722

1823
interface ChatSessionMorePopupProps {
1924
chatSession: ChatSession;
@@ -45,6 +50,15 @@ export function ChatSessionMorePopup({
4550
const { refreshChatSessions } = useChatContext();
4651
const { fetchProjects, projects } = useProjectsContext();
4752

53+
const [pendingMoveProjectId, setPendingMoveProjectId] = useState<
54+
number | null
55+
>(null);
56+
const [showMoveCustomAgentModal, setShowMoveCustomAgentModal] =
57+
useState(false);
58+
59+
const isChatUsingDefaultAssistant =
60+
chatSession.persona_id === DEFAULT_PERSONA_ID;
61+
4862
const handlePopoverOpenChange = useCallback(
4963
(open: boolean) => {
5064
setPopoverOpen(open);
@@ -80,22 +94,34 @@ export function ChatSessionMorePopup({
8094
[chatSession, refreshChatSessions, fetchProjects, afterDelete]
8195
);
8296

83-
const handleMoveChatSession = useCallback(
84-
async (item: { id: string; label: string }) => {
85-
const projectId = parseInt(item.id);
86-
await moveChatSessionService(projectId, chatSession.id);
97+
const performMove = useCallback(
98+
async (targetProjectId: number) => {
99+
await moveChatSessionService(targetProjectId, chatSession.id);
87100
await fetchProjects();
88101
await refreshChatSessions({ skipRedirectOnMissing: true });
89102
setPopoverOpen(false);
90103
afterMove?.();
91104
},
92-
[
93-
chatSession.id,
94-
fetchProjects,
95-
refreshChatSessions,
96-
moveChatSessionService,
97-
afterMove,
98-
]
105+
[chatSession.id, fetchProjects, refreshChatSessions, afterMove]
106+
);
107+
108+
const handleMoveChatSession = useCallback(
109+
async (item: { id: string; label: string }) => {
110+
const targetProjectId = parseInt(item.id);
111+
const hideModal =
112+
typeof window !== "undefined" &&
113+
window.localStorage.getItem(LS_HIDE_MOVE_CUSTOM_AGENT_MODAL_KEY) ===
114+
"true";
115+
116+
if (!isChatUsingDefaultAssistant && !hideModal) {
117+
setPendingMoveProjectId(targetProjectId);
118+
setShowMoveCustomAgentModal(true);
119+
return;
120+
}
121+
122+
await performMove(targetProjectId);
123+
},
124+
[isChatUsingDefaultAssistant, performMove]
99125
);
100126

101127
const handleRemoveChatSessionFromProject = useCallback(async () => {
@@ -207,6 +233,27 @@ export function ChatSessionMorePopup({
207233
triggerMaxWidth
208234
/>
209235
</div>
236+
<MoveCustomAgentChatModal
237+
isOpen={showMoveCustomAgentModal}
238+
onCancel={() => {
239+
setShowMoveCustomAgentModal(false);
240+
setPendingMoveProjectId(null);
241+
}}
242+
onConfirm={async (doNotShowAgain: boolean) => {
243+
if (doNotShowAgain && typeof window !== "undefined") {
244+
window.localStorage.setItem(
245+
LS_HIDE_MOVE_CUSTOM_AGENT_MODAL_KEY,
246+
"true"
247+
);
248+
}
249+
const target = pendingMoveProjectId;
250+
setShowMoveCustomAgentModal(false);
251+
setPendingMoveProjectId(null);
252+
if (target != null) {
253+
await performMove(target);
254+
}
255+
}}
256+
/>
210257
</div>
211258
);
212259
}

web/src/components/sidebar/Projects.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,6 @@ export default function Projects({ onOpenProject }: ProjectsProps) {
293293
isSelected={chatSession.id == chatSessionId}
294294
showDragHandle={false}
295295
projectId={p.id}
296-
isCustomAssistant={
297-
currentProjectId === p.id &&
298-
!!currentProjectDetails?.persona_id_to_is_default &&
299-
currentProjectDetails.persona_id_to_is_default[
300-
chatSession.persona_id
301-
] === false
302-
}
303296
/>
304297
))
305298
) : (

0 commit comments

Comments
 (0)