mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-09 14:57:59 -05:00
fix: display conversation title in delete confirmation modal (#11818)
Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { renderWithProviders } from "test-utils";
|
||||
import { ConfirmDeleteModal } from "#/components/features/conversation-panel/confirm-delete-modal";
|
||||
|
||||
vi.mock("react-i18next", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("react-i18next")>()),
|
||||
Trans: ({
|
||||
values,
|
||||
components,
|
||||
}: {
|
||||
values: { title: string };
|
||||
components: { title: React.ReactElement };
|
||||
}) => React.cloneElement(components.title, {}, values.title),
|
||||
}));
|
||||
|
||||
describe("ConfirmDeleteModal", () => {
|
||||
it("should display the conversation title", () => {
|
||||
renderWithProviders(
|
||||
<ConfirmDeleteModal
|
||||
onConfirm={vi.fn()}
|
||||
onCancel={vi.fn()}
|
||||
conversationTitle="My Test Conversation"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText(/My Test Conversation/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import {
|
||||
BaseModalDescription,
|
||||
BaseModalTitle,
|
||||
@@ -11,22 +11,32 @@ import { I18nKey } from "#/i18n/declaration";
|
||||
interface ConfirmDeleteModalProps {
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
conversationTitle?: string;
|
||||
}
|
||||
|
||||
export function ConfirmDeleteModal({
|
||||
onConfirm,
|
||||
onCancel,
|
||||
conversationTitle,
|
||||
}: ConfirmDeleteModalProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const confirmationMessage = conversationTitle ? (
|
||||
<Trans
|
||||
i18nKey={I18nKey.CONVERSATION$DELETE_WARNING_WITH_TITLE}
|
||||
values={{ title: conversationTitle }}
|
||||
components={{ title: <span className="text-white" /> }}
|
||||
/>
|
||||
) : (
|
||||
t(I18nKey.CONVERSATION$DELETE_WARNING)
|
||||
);
|
||||
|
||||
return (
|
||||
<ModalBackdrop>
|
||||
<ModalBody className="items-start border border-tertiary">
|
||||
<div className="flex flex-col gap-2">
|
||||
<BaseModalTitle title={t(I18nKey.CONVERSATION$CONFIRM_DELETE)} />
|
||||
<BaseModalDescription
|
||||
description={t(I18nKey.CONVERSATION$DELETE_WARNING)}
|
||||
/>
|
||||
<BaseModalDescription>{confirmationMessage}</BaseModalDescription>
|
||||
</div>
|
||||
<div
|
||||
className="flex flex-col gap-2 w-full"
|
||||
|
||||
@@ -39,6 +39,8 @@ export function ConversationPanel({ onClose }: ConversationPanelProps) {
|
||||
const [selectedConversationId, setSelectedConversationId] = React.useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [selectedConversationTitle, setSelectedConversationTitle] =
|
||||
React.useState<string | null>(null);
|
||||
const [selectedConversationVersion, setSelectedConversationVersion] =
|
||||
React.useState<"V0" | "V1" | undefined>(undefined);
|
||||
const [openContextMenuId, setOpenContextMenuId] = React.useState<
|
||||
@@ -73,9 +75,10 @@ export function ConversationPanel({ onClose }: ConversationPanelProps) {
|
||||
threshold: 200, // Load more when 200px from bottom
|
||||
});
|
||||
|
||||
const handleDeleteProject = (conversationId: string) => {
|
||||
const handleDeleteProject = (conversationId: string, title: string) => {
|
||||
setConfirmDeleteModalVisible(true);
|
||||
setSelectedConversationId(conversationId);
|
||||
setSelectedConversationTitle(title);
|
||||
};
|
||||
|
||||
const handleStopConversation = (
|
||||
@@ -171,7 +174,9 @@ export function ConversationPanel({ onClose }: ConversationPanelProps) {
|
||||
onClick={onClose}
|
||||
>
|
||||
<ConversationCard
|
||||
onDelete={() => handleDeleteProject(project.conversation_id)}
|
||||
onDelete={() =>
|
||||
handleDeleteProject(project.conversation_id, project.title)
|
||||
}
|
||||
onStop={() =>
|
||||
handleStopConversation(
|
||||
project.conversation_id,
|
||||
@@ -212,8 +217,13 @@ export function ConversationPanel({ onClose }: ConversationPanelProps) {
|
||||
onConfirm={() => {
|
||||
handleConfirmDelete();
|
||||
setConfirmDeleteModalVisible(false);
|
||||
setSelectedConversationTitle(null);
|
||||
}}
|
||||
onCancel={() => setConfirmDeleteModalVisible(false)}
|
||||
onCancel={() => {
|
||||
setConfirmDeleteModalVisible(false);
|
||||
setSelectedConversationTitle(null);
|
||||
}}
|
||||
conversationTitle={selectedConversationTitle ?? undefined}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -227,6 +227,7 @@ export function ConversationName() {
|
||||
<ConfirmDeleteModal
|
||||
onConfirm={handleConfirmDelete}
|
||||
onCancel={() => setConfirmDeleteModalVisible(false)}
|
||||
conversationTitle={conversation?.title}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -606,6 +606,7 @@ export enum I18nKey {
|
||||
AUTH$SIGN_IN_WITH_IDENTITY_PROVIDER = "AUTH$SIGN_IN_WITH_IDENTITY_PROVIDER",
|
||||
WAITLIST$JOIN_WAITLIST = "WAITLIST$JOIN_WAITLIST",
|
||||
CONVERSATION$DELETE_WARNING = "CONVERSATION$DELETE_WARNING",
|
||||
CONVERSATION$DELETE_WARNING_WITH_TITLE = "CONVERSATION$DELETE_WARNING_WITH_TITLE",
|
||||
FEEDBACK$TITLE = "FEEDBACK$TITLE",
|
||||
FEEDBACK$DESCRIPTION = "FEEDBACK$DESCRIPTION",
|
||||
EXIT_PROJECT$WARNING = "EXIT_PROJECT$WARNING",
|
||||
|
||||
@@ -9695,6 +9695,22 @@
|
||||
"de": "Sind Sie sicher, dass Sie dieses Gespräch löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"uk": "Ви впевнені, що хочете видалити цю розмову? Цю дію не можна скасувати."
|
||||
},
|
||||
"CONVERSATION$DELETE_WARNING_WITH_TITLE": {
|
||||
"en": "Are you sure you want to delete the \"<title>{{title}}</title>\" conversation? This action cannot be undone.",
|
||||
"ja": "「<title>{{title}}</title>」の会話を削除してもよろしいですか?この操作は元に戻せません。",
|
||||
"zh-CN": "您确定要删除\"<title>{{title}}</title>\"对话吗?此操作无法撤消。",
|
||||
"zh-TW": "您確定要刪除「<title>{{title}}</title>」對話嗎?此操作無法撤消。",
|
||||
"ko-KR": "\"<title>{{title}}</title>\" 대화를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.",
|
||||
"no": "Er du sikker på at du vil slette samtalen \"<title>{{title}}</title>\"? Denne handlingen kan ikke angres.",
|
||||
"it": "Sei sicuro di voler eliminare la conversazione \"<title>{{title}}</title>\"? Questa azione non può essere annullata.",
|
||||
"pt": "Tem certeza de que deseja excluir a conversa \"<title>{{title}}</title>\"? Esta ação não pode ser desfeita.",
|
||||
"es": "¿Está seguro de que desea eliminar la conversación \"<title>{{title}}</title>\"? Esta acción no se puede deshacer.",
|
||||
"ar": "هل أنت متأكد أنك تريد حذف المحادثة \"<title>{{title}}</title>\"؟ لا يمكن التراجع عن هذا الإجراء.",
|
||||
"fr": "Êtes-vous sûr de vouloir supprimer la conversation « <title>{{title}}</title> » ? Cette action ne peut pas être annulée.",
|
||||
"tr": "\"<title>{{title}}</title>\" konuşmasını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.",
|
||||
"de": "Sind Sie sicher, dass Sie das Gespräch „<title>{{title}}</title>\" löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"uk": "Ви впевнені, що хочете видалити розмову «<title>{{title}}</title>»? Цю дію не можна скасувати."
|
||||
},
|
||||
"FEEDBACK$TITLE": {
|
||||
"en": "Feedback",
|
||||
"ja": "フィードバック",
|
||||
|
||||
Reference in New Issue
Block a user