mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-06-16 19:10:53 +02:00
Add delete all chats option (#2515)
* Add delete all chats option * post rebase fixes * final validation * minor cleanup * move up
This commit is contained in:
parent
b5d0df90b9
commit
28598694b1
121
backend/alembic/versions/35e518e0ddf4_properly_cascade.py
Normal file
121
backend/alembic/versions/35e518e0ddf4_properly_cascade.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
"""properly_cascade
|
||||||
|
|
||||||
|
Revision ID: 35e518e0ddf4
|
||||||
|
Revises: 91a0a4d62b14
|
||||||
|
Create Date: 2024-09-20 21:24:04.891018
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "35e518e0ddf4"
|
||||||
|
down_revision = "91a0a4d62b14"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# Update chat_message foreign key constraint
|
||||||
|
op.drop_constraint(
|
||||||
|
"chat_message_chat_session_id_fkey", "chat_message", type_="foreignkey"
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
"chat_message_chat_session_id_fkey",
|
||||||
|
"chat_message",
|
||||||
|
"chat_session",
|
||||||
|
["chat_session_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update chat_message__search_doc foreign key constraints
|
||||||
|
op.drop_constraint(
|
||||||
|
"chat_message__search_doc_chat_message_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.drop_constraint(
|
||||||
|
"chat_message__search_doc_search_doc_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
|
||||||
|
op.create_foreign_key(
|
||||||
|
"chat_message__search_doc_chat_message_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
"chat_message",
|
||||||
|
["chat_message_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
"chat_message__search_doc_search_doc_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
"search_doc",
|
||||||
|
["search_doc_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add CASCADE delete for tool_call foreign key
|
||||||
|
op.drop_constraint("tool_call_message_id_fkey", "tool_call", type_="foreignkey")
|
||||||
|
op.create_foreign_key(
|
||||||
|
"tool_call_message_id_fkey",
|
||||||
|
"tool_call",
|
||||||
|
"chat_message",
|
||||||
|
["message_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# Revert chat_message foreign key constraint
|
||||||
|
op.drop_constraint(
|
||||||
|
"chat_message_chat_session_id_fkey", "chat_message", type_="foreignkey"
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
"chat_message_chat_session_id_fkey",
|
||||||
|
"chat_message",
|
||||||
|
"chat_session",
|
||||||
|
["chat_session_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Revert chat_message__search_doc foreign key constraints
|
||||||
|
op.drop_constraint(
|
||||||
|
"chat_message__search_doc_chat_message_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.drop_constraint(
|
||||||
|
"chat_message__search_doc_search_doc_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
|
||||||
|
op.create_foreign_key(
|
||||||
|
"chat_message__search_doc_chat_message_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
"chat_message",
|
||||||
|
["chat_message_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
"chat_message__search_doc_search_doc_id_fkey",
|
||||||
|
"chat_message__search_doc",
|
||||||
|
"search_doc",
|
||||||
|
["search_doc_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Revert tool_call foreign key constraint
|
||||||
|
op.drop_constraint("tool_call_message_id_fkey", "tool_call", type_="foreignkey")
|
||||||
|
op.create_foreign_key(
|
||||||
|
"tool_call_message_id_fkey",
|
||||||
|
"tool_call",
|
||||||
|
"chat_message",
|
||||||
|
["message_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
@ -316,6 +316,23 @@ def update_chat_session(
|
|||||||
return chat_session
|
return chat_session
|
||||||
|
|
||||||
|
|
||||||
|
def delete_all_chat_sessions_for_user(
|
||||||
|
user: User | None, db_session: Session, hard_delete: bool = HARD_DELETE_CHATS
|
||||||
|
) -> None:
|
||||||
|
user_id = user.id if user is not None else None
|
||||||
|
|
||||||
|
query = db_session.query(ChatSession).filter(
|
||||||
|
ChatSession.user_id == user_id, ChatSession.onyxbot_flow.is_(False)
|
||||||
|
)
|
||||||
|
|
||||||
|
if hard_delete:
|
||||||
|
query.delete(synchronize_session=False)
|
||||||
|
else:
|
||||||
|
query.update({ChatSession.deleted: True}, synchronize_session=False)
|
||||||
|
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
|
||||||
def delete_chat_session(
|
def delete_chat_session(
|
||||||
user_id: UUID | None,
|
user_id: UUID | None,
|
||||||
chat_session_id: UUID,
|
chat_session_id: UUID,
|
||||||
|
@ -1010,7 +1010,7 @@ class ChatSession(Base):
|
|||||||
"ChatFolder", back_populates="chat_sessions"
|
"ChatFolder", back_populates="chat_sessions"
|
||||||
)
|
)
|
||||||
messages: Mapped[list["ChatMessage"]] = relationship(
|
messages: Mapped[list["ChatMessage"]] = relationship(
|
||||||
"ChatMessage", back_populates="chat_session"
|
"ChatMessage", back_populates="chat_session", cascade="all, delete-orphan"
|
||||||
)
|
)
|
||||||
persona: Mapped["Persona"] = relationship("Persona")
|
persona: Mapped["Persona"] = relationship("Persona")
|
||||||
|
|
||||||
@ -1078,6 +1078,8 @@ class ChatMessage(Base):
|
|||||||
"SearchDoc",
|
"SearchDoc",
|
||||||
secondary=ChatMessage__SearchDoc.__table__,
|
secondary=ChatMessage__SearchDoc.__table__,
|
||||||
back_populates="chat_messages",
|
back_populates="chat_messages",
|
||||||
|
cascade="all, delete-orphan",
|
||||||
|
single_parent=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
tool_call: Mapped["ToolCall"] = relationship(
|
tool_call: Mapped["ToolCall"] = relationship(
|
||||||
|
@ -35,6 +35,7 @@ from onyx.configs.model_configs import LITELLM_PASS_THROUGH_HEADERS
|
|||||||
from onyx.db.chat import add_chats_to_session_from_slack_thread
|
from onyx.db.chat import add_chats_to_session_from_slack_thread
|
||||||
from onyx.db.chat import create_chat_session
|
from onyx.db.chat import create_chat_session
|
||||||
from onyx.db.chat import create_new_chat_message
|
from onyx.db.chat import create_new_chat_message
|
||||||
|
from onyx.db.chat import delete_all_chat_sessions_for_user
|
||||||
from onyx.db.chat import delete_chat_session
|
from onyx.db.chat import delete_chat_session
|
||||||
from onyx.db.chat import duplicate_chat_session_for_user_from_slack
|
from onyx.db.chat import duplicate_chat_session_for_user_from_slack
|
||||||
from onyx.db.chat import get_chat_message
|
from onyx.db.chat import get_chat_message
|
||||||
@ -280,6 +281,17 @@ def patch_chat_session(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/delete-all-chat-sessions")
|
||||||
|
def delete_all_chat_sessions(
|
||||||
|
user: User | None = Depends(current_user),
|
||||||
|
db_session: Session = Depends(get_session),
|
||||||
|
) -> None:
|
||||||
|
try:
|
||||||
|
delete_all_chat_sessions_for_user(user=user, db_session=db_session)
|
||||||
|
except ValueError as e:
|
||||||
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/delete-chat-session/{session_id}")
|
@router.delete("/delete-chat-session/{session_id}")
|
||||||
def delete_chat_session_by_id(
|
def delete_chat_session_by_id(
|
||||||
session_id: UUID,
|
session_id: UUID,
|
||||||
|
@ -11,6 +11,7 @@ from onyx.chat.models import RetrievalDocs
|
|||||||
from onyx.configs.constants import DocumentSource
|
from onyx.configs.constants import DocumentSource
|
||||||
from onyx.configs.constants import MessageType
|
from onyx.configs.constants import MessageType
|
||||||
from onyx.configs.constants import SearchFeedbackType
|
from onyx.configs.constants import SearchFeedbackType
|
||||||
|
from onyx.configs.constants import SessionType
|
||||||
from onyx.context.search.models import BaseFilters
|
from onyx.context.search.models import BaseFilters
|
||||||
from onyx.context.search.models import ChunkContext
|
from onyx.context.search.models import ChunkContext
|
||||||
from onyx.context.search.models import RerankingDetails
|
from onyx.context.search.models import RerankingDetails
|
||||||
@ -151,6 +152,10 @@ class ChatSessionUpdateRequest(BaseModel):
|
|||||||
sharing_status: ChatSessionSharedStatus
|
sharing_status: ChatSessionSharedStatus
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteAllSessionsRequest(BaseModel):
|
||||||
|
session_type: SessionType
|
||||||
|
|
||||||
|
|
||||||
class RenameChatSessionResponse(BaseModel):
|
class RenameChatSessionResponse(BaseModel):
|
||||||
new_name: str # This is only really useful if the name is generated
|
new_name: str # This is only really useful if the name is generated
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import {
|
|||||||
buildLatestMessageChain,
|
buildLatestMessageChain,
|
||||||
checkAnyAssistantHasSearch,
|
checkAnyAssistantHasSearch,
|
||||||
createChatSession,
|
createChatSession,
|
||||||
|
deleteAllChatSessions,
|
||||||
deleteChatSession,
|
deleteChatSession,
|
||||||
getCitedDocumentsFromMessage,
|
getCitedDocumentsFromMessage,
|
||||||
getHumanAndAIMessageFromMessageNumber,
|
getHumanAndAIMessageFromMessageNumber,
|
||||||
@ -1837,6 +1838,7 @@ export function ChatPage({
|
|||||||
|
|
||||||
const innerSidebarElementRef = useRef<HTMLDivElement>(null);
|
const innerSidebarElementRef = useRef<HTMLDivElement>(null);
|
||||||
const [settingsToggled, setSettingsToggled] = useState(false);
|
const [settingsToggled, setSettingsToggled] = useState(false);
|
||||||
|
const [showDeleteAllModal, setShowDeleteAllModal] = useState(false);
|
||||||
|
|
||||||
const currentPersona = alternativeAssistant || liveAssistant;
|
const currentPersona = alternativeAssistant || liveAssistant;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -1903,11 +1905,6 @@ export function ChatPage({
|
|||||||
const showShareModal = (chatSession: ChatSession) => {
|
const showShareModal = (chatSession: ChatSession) => {
|
||||||
setSharedChatSession(chatSession);
|
setSharedChatSession(chatSession);
|
||||||
};
|
};
|
||||||
const [documentSelection, setDocumentSelection] = useState(false);
|
|
||||||
// const toggleDocumentSelectionAspects = () => {
|
|
||||||
// setDocumentSelection((documentSelection) => !documentSelection);
|
|
||||||
// setShowDocSidebar(false);
|
|
||||||
// };
|
|
||||||
|
|
||||||
const toggleDocumentSidebar = () => {
|
const toggleDocumentSidebar = () => {
|
||||||
if (!documentSidebarToggled) {
|
if (!documentSidebarToggled) {
|
||||||
@ -1972,6 +1969,32 @@ export function ChatPage({
|
|||||||
|
|
||||||
<ChatPopup />
|
<ChatPopup />
|
||||||
|
|
||||||
|
{showDeleteAllModal && (
|
||||||
|
<DeleteEntityModal
|
||||||
|
entityType="All Chats"
|
||||||
|
entityName="all your chat sessions"
|
||||||
|
onClose={() => setShowDeleteAllModal(false)}
|
||||||
|
additionalDetails="This action cannot be undone. All your chat sessions will be deleted."
|
||||||
|
onSubmit={async () => {
|
||||||
|
const response = await deleteAllChatSessions("Chat");
|
||||||
|
if (response.ok) {
|
||||||
|
setShowDeleteAllModal(false);
|
||||||
|
setPopup({
|
||||||
|
message: "All your chat sessions have been deleted.",
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
|
refreshChatSessions();
|
||||||
|
router.push("/chat");
|
||||||
|
} else {
|
||||||
|
setPopup({
|
||||||
|
message: "Failed to delete all chat sessions.",
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{currentFeedback && (
|
{currentFeedback && (
|
||||||
<FeedbackModal
|
<FeedbackModal
|
||||||
feedbackType={currentFeedback[0]}
|
feedbackType={currentFeedback[0]}
|
||||||
@ -2132,6 +2155,7 @@ export function ChatPage({
|
|||||||
removeToggle={removeToggle}
|
removeToggle={removeToggle}
|
||||||
showShareModal={showShareModal}
|
showShareModal={showShareModal}
|
||||||
showDeleteModal={showDeleteModal}
|
showDeleteModal={showDeleteModal}
|
||||||
|
showDeleteAllModal={() => setShowDeleteAllModal(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -2739,6 +2763,10 @@ export function ChatPage({
|
|||||||
removeDocs={() => {
|
removeDocs={() => {
|
||||||
clearSelectedDocuments();
|
clearSelectedDocuments();
|
||||||
}}
|
}}
|
||||||
|
showDocs={() => {
|
||||||
|
setFiltersToggled(false);
|
||||||
|
setDocumentSidebarToggled(true);
|
||||||
|
}}
|
||||||
removeFilters={() => {
|
removeFilters={() => {
|
||||||
filterManager.setSelectedSources([]);
|
filterManager.setSelectedSources([]);
|
||||||
filterManager.setSelectedTags([]);
|
filterManager.setSelectedTags([]);
|
||||||
@ -2751,7 +2779,6 @@ export function ChatPage({
|
|||||||
chatState={currentSessionChatState}
|
chatState={currentSessionChatState}
|
||||||
stopGenerating={stopGenerating}
|
stopGenerating={stopGenerating}
|
||||||
openModelSettings={() => setSettingsToggled(true)}
|
openModelSettings={() => setSettingsToggled(true)}
|
||||||
showDocs={() => setDocumentSelection(true)}
|
|
||||||
selectedDocuments={selectedDocuments}
|
selectedDocuments={selectedDocuments}
|
||||||
// assistant stuff
|
// assistant stuff
|
||||||
selectedAssistant={liveAssistant}
|
selectedAssistant={liveAssistant}
|
||||||
|
@ -31,14 +31,7 @@ import { SettingsContext } from "@/components/settings/SettingsProvider";
|
|||||||
import { ChatState } from "../types";
|
import { ChatState } from "../types";
|
||||||
import UnconfiguredProviderText from "@/components/chat_search/UnconfiguredProviderText";
|
import UnconfiguredProviderText from "@/components/chat_search/UnconfiguredProviderText";
|
||||||
import { useAssistants } from "@/components/context/AssistantsContext";
|
import { useAssistants } from "@/components/context/AssistantsContext";
|
||||||
import AnimatedToggle from "@/components/search/SearchBar";
|
|
||||||
import { Popup } from "@/components/admin/connectors/Popup";
|
|
||||||
import { AssistantsTab } from "../modal/configuration/AssistantsTab";
|
|
||||||
import { IconType } from "react-icons";
|
|
||||||
import { LlmTab } from "../modal/configuration/LlmTab";
|
|
||||||
import { XIcon } from "lucide-react";
|
import { XIcon } from "lucide-react";
|
||||||
import { FilterPills } from "./FilterPills";
|
|
||||||
import { Tag } from "@/lib/types";
|
|
||||||
import FiltersDisplay from "./FilterDisplay";
|
import FiltersDisplay from "./FilterDisplay";
|
||||||
|
|
||||||
const MAX_INPUT_HEIGHT = 200;
|
const MAX_INPUT_HEIGHT = 200;
|
||||||
@ -47,7 +40,6 @@ interface ChatInputBarProps {
|
|||||||
removeFilters: () => void;
|
removeFilters: () => void;
|
||||||
removeDocs: () => void;
|
removeDocs: () => void;
|
||||||
openModelSettings: () => void;
|
openModelSettings: () => void;
|
||||||
showDocs: () => void;
|
|
||||||
showConfigureAPIKey: () => void;
|
showConfigureAPIKey: () => void;
|
||||||
selectedDocuments: OnyxDocument[];
|
selectedDocuments: OnyxDocument[];
|
||||||
message: string;
|
message: string;
|
||||||
@ -57,6 +49,7 @@ interface ChatInputBarProps {
|
|||||||
filterManager: FilterManager;
|
filterManager: FilterManager;
|
||||||
llmOverrideManager: LlmOverrideManager;
|
llmOverrideManager: LlmOverrideManager;
|
||||||
chatState: ChatState;
|
chatState: ChatState;
|
||||||
|
showDocs: () => void;
|
||||||
alternativeAssistant: Persona | null;
|
alternativeAssistant: Persona | null;
|
||||||
// assistants
|
// assistants
|
||||||
selectedAssistant: Persona;
|
selectedAssistant: Persona;
|
||||||
@ -75,8 +68,8 @@ export function ChatInputBar({
|
|||||||
removeFilters,
|
removeFilters,
|
||||||
removeDocs,
|
removeDocs,
|
||||||
openModelSettings,
|
openModelSettings,
|
||||||
showDocs,
|
|
||||||
showConfigureAPIKey,
|
showConfigureAPIKey,
|
||||||
|
showDocs,
|
||||||
selectedDocuments,
|
selectedDocuments,
|
||||||
message,
|
message,
|
||||||
setMessage,
|
setMessage,
|
||||||
@ -284,10 +277,6 @@ export function ChatInputBar({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* <div>
|
|
||||||
<SelectedFilterDisplay filterManager={filterManager} />
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
<UnconfiguredProviderText showConfigureAPIKey={showConfigureAPIKey} />
|
<UnconfiguredProviderText showConfigureAPIKey={showConfigureAPIKey} />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -278,6 +278,16 @@ export async function deleteChatSession(chatSessionId: string) {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteAllChatSessions(sessionType: "Chat" | "Search") {
|
||||||
|
const response = await fetch(`/api/chat/delete-all-chat-sessions`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
export async function* simulateLLMResponse(input: string, delay: number = 30) {
|
export async function* simulateLLMResponse(input: string, delay: number = 30) {
|
||||||
// Split the input string into tokens. This is a simple example, and in real use case, tokenization can be more complex.
|
// Split the input string into tokens. This is a simple example, and in real use case, tokenization can be more complex.
|
||||||
// Iterate over tokens and yield them one by one
|
// Iterate over tokens and yield them one by one
|
||||||
|
@ -30,6 +30,7 @@ interface HistorySidebarProps {
|
|||||||
showDeleteModal?: (chatSession: ChatSession) => void;
|
showDeleteModal?: (chatSession: ChatSession) => void;
|
||||||
stopGenerating?: () => void;
|
stopGenerating?: () => void;
|
||||||
explicitlyUntoggle: () => void;
|
explicitlyUntoggle: () => void;
|
||||||
|
showDeleteAllModal?: () => void;
|
||||||
backgroundToggled?: boolean;
|
backgroundToggled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
|
|||||||
stopGenerating = () => null,
|
stopGenerating = () => null,
|
||||||
showShareModal,
|
showShareModal,
|
||||||
showDeleteModal,
|
showDeleteModal,
|
||||||
|
showDeleteAllModal,
|
||||||
backgroundToggled,
|
backgroundToggled,
|
||||||
},
|
},
|
||||||
ref: ForwardedRef<HTMLDivElement>
|
ref: ForwardedRef<HTMLDivElement>
|
||||||
@ -176,6 +178,7 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
|
|||||||
currentChatId={currentChatId}
|
currentChatId={currentChatId}
|
||||||
folders={folders}
|
folders={folders}
|
||||||
openedFolders={openedFolders}
|
openedFolders={openedFolders}
|
||||||
|
showDeleteAllModal={showDeleteAllModal}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -9,6 +9,8 @@ import { usePopup } from "@/components/admin/connectors/Popup";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { pageType } from "./types";
|
import { pageType } from "./types";
|
||||||
|
import { FiTrash2 } from "react-icons/fi";
|
||||||
|
import { NEXT_PUBLIC_DELETE_ALL_CHATS_ENABLED } from "@/lib/constants";
|
||||||
|
|
||||||
export function PagesTab({
|
export function PagesTab({
|
||||||
page,
|
page,
|
||||||
@ -20,6 +22,7 @@ export function PagesTab({
|
|||||||
newFolderId,
|
newFolderId,
|
||||||
showShareModal,
|
showShareModal,
|
||||||
showDeleteModal,
|
showDeleteModal,
|
||||||
|
showDeleteAllModal,
|
||||||
}: {
|
}: {
|
||||||
page: pageType;
|
page: pageType;
|
||||||
existingChats?: ChatSession[];
|
existingChats?: ChatSession[];
|
||||||
@ -30,6 +33,7 @@ export function PagesTab({
|
|||||||
newFolderId: number | null;
|
newFolderId: number | null;
|
||||||
showShareModal?: (chatSession: ChatSession) => void;
|
showShareModal?: (chatSession: ChatSession) => void;
|
||||||
showDeleteModal?: (chatSession: ChatSession) => void;
|
showDeleteModal?: (chatSession: ChatSession) => void;
|
||||||
|
showDeleteAllModal?: () => void;
|
||||||
}) {
|
}) {
|
||||||
const groupedChatSessions = existingChats
|
const groupedChatSessions = existingChats
|
||||||
? groupSessionsByDateRange(existingChats)
|
? groupSessionsByDateRange(existingChats)
|
||||||
@ -63,7 +67,12 @@ export function PagesTab({
|
|||||||
const isHistoryEmpty = !existingChats || existingChats.length === 0;
|
const isHistoryEmpty = !existingChats || existingChats.length === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-1 text-text-sidebar ml-3 relative miniscroll mobile:pb-40 overflow-y-auto h-full">
|
<div className="flex flex-col relative h-full overflow-y-auto mb-1 ml-3 miniscroll mobile:pb-40">
|
||||||
|
<div
|
||||||
|
className={` flex-grow overflow-y-auto ${
|
||||||
|
NEXT_PUBLIC_DELETE_ALL_CHATS_ENABLED && "pb-20 "
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{folders && folders.length > 0 && (
|
{folders && folders.length > 0 && (
|
||||||
<div className="py-2 border-b border-border">
|
<div className="py-2 border-b border-border">
|
||||||
<div className="text-xs text-subtle flex pb-0.5 mb-1.5 mt-2 font-bold">
|
<div className="text-xs text-subtle flex pb-0.5 mb-1.5 mt-2 font-bold">
|
||||||
@ -79,6 +88,7 @@ export function PagesTab({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
onDragOver={(event) => {
|
onDragOver={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -99,9 +109,7 @@ export function PagesTab({
|
|||||||
)}
|
)}
|
||||||
{isHistoryEmpty ? (
|
{isHistoryEmpty ? (
|
||||||
<p className="text-sm mt-2 w-[250px]">
|
<p className="text-sm mt-2 w-[250px]">
|
||||||
{page === "search"
|
Try sending a message! Your chat history will appear here.
|
||||||
? "Try running a search! Your search history will appear here."
|
|
||||||
: "Try sending a message! Your chat history will appear here."}
|
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
Object.entries(groupedChatSessions).map(
|
Object.entries(groupedChatSessions).map(
|
||||||
@ -141,6 +149,18 @@ export function PagesTab({
|
|||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{showDeleteAllModal && NEXT_PUBLIC_DELETE_ALL_CHATS_ENABLED && (
|
||||||
|
<div className="absolute w-full border-t border-t-border bg-background-100 bottom-0 left-0 p-4">
|
||||||
|
<button
|
||||||
|
className="w-full py-2 px-4 text-text-600 hover:text-text-800 bg-background-125 border border-border-strong/50 shadow-sm rounded-md transition-colors duration-200 flex items-center justify-center text-sm"
|
||||||
|
onClick={showDeleteAllModal}
|
||||||
|
>
|
||||||
|
<FiTrash2 className="mr-2" size={14} />
|
||||||
|
Clear All History
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,7 @@ export const DeleteEntityModal = ({
|
|||||||
<h2 className="my-auto text-2xl font-bold">Delete {entityType}?</h2>
|
<h2 className="my-auto text-2xl font-bold">Delete {entityType}?</h2>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
Click below to confirm that you want to delete{" "}
|
Click below to confirm that you want to delete <b>{entityName}</b>
|
||||||
<b>"{entityName}"</b>
|
|
||||||
</p>
|
</p>
|
||||||
{additionalDetails && <p className="mb-4">{additionalDetails}</p>}
|
{additionalDetails && <p className="mb-4">{additionalDetails}</p>}
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
@ -75,3 +75,6 @@ export const REGISTRATION_URL =
|
|||||||
process.env.INTERNAL_URL || "http://127.0.0.1:3001";
|
process.env.INTERNAL_URL || "http://127.0.0.1:3001";
|
||||||
|
|
||||||
export const TEST_ENV = process.env.TEST_ENV?.toLowerCase() === "true";
|
export const TEST_ENV = process.env.TEST_ENV?.toLowerCase() === "true";
|
||||||
|
|
||||||
|
export const NEXT_PUBLIC_DELETE_ALL_CHATS_ENABLED =
|
||||||
|
process.env.NEXT_PUBLIC_DELETE_ALL_CHATS_ENABLED?.toLowerCase() === "true";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user