From cfff86cab364fdffa4ad46c3b3031816d5d9d255 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 22 May 2023 17:16:29 +0800 Subject: [PATCH] feat: implement conversation tabs in header --- src/components/ConnectionSidebar.tsx | 1 + src/components/ConversationTabsView.tsx | 131 +++++++++++++++++++++ src/components/ConversationView/Header.tsx | 62 +++++----- 3 files changed, 166 insertions(+), 28 deletions(-) create mode 100644 src/components/ConversationTabsView.tsx diff --git a/src/components/ConnectionSidebar.tsx b/src/components/ConnectionSidebar.tsx index 8f89d96..cce2a12 100644 --- a/src/components/ConnectionSidebar.tsx +++ b/src/components/ConnectionSidebar.tsx @@ -203,6 +203,7 @@ const ConnectionSidebar = () => { ) ))} + {/* TODO(steven): remove this after we finish left sidebar */}
diff --git a/src/components/ConversationTabsView.tsx b/src/components/ConversationTabsView.tsx new file mode 100644 index 0000000..eec3333 --- /dev/null +++ b/src/components/ConversationTabsView.tsx @@ -0,0 +1,131 @@ +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useConnectionStore, useConversationStore, useLayoutStore } from "@/store"; +import { Conversation } from "@/types"; +import Icon from "./Icon"; +import Dropdown, { DropdownItem } from "./kit/Dropdown"; +import UpdateConversationModal from "./UpdateConversationModal"; + +interface ConversationTabProps { + conversation: Conversation; + selected: boolean; + onClick: (conversation: Conversation) => void; + onEdit: (conversation: Conversation) => void; + onDelete: (conversation: Conversation) => void; +} + +const ConversationTab = (props: ConversationTabProps) => { + const { conversation, selected, onClick, onEdit, onDelete } = props; + const { t } = useTranslation(); + + return ( +
onClick(conversation)} + > + {conversation.title} + + + + } + > +
+ onEdit(conversation)} + > + + {t("common.edit")} + + onDelete(conversation)} + > + + {t("common.delete")} + +
+
+
+ ); +}; + +const ConversationTabsView = () => { + const { t } = useTranslation(); + const layoutStore = useLayoutStore(); + const connectionStore = useConnectionStore(); + const conversationStore = useConversationStore(); + const [updateConversationModalContext, setUpdateConversationModalContext] = useState(undefined); + const currentConnectionCtx = connectionStore.currentConnectionCtx; + const conversationList = conversationStore.conversationList.filter( + (conversation) => + conversation.connectionId === currentConnectionCtx?.connection.id && + conversation.databaseName === currentConnectionCtx?.database?.name + ); + + const handleCreateConversation = () => { + if (!currentConnectionCtx) { + conversationStore.createConversation(); + } else { + conversationStore.createConversation(currentConnectionCtx.connection.id, currentConnectionCtx.database?.name); + } + }; + + const handleConversationClick = (conversation: Conversation) => { + conversationStore.setCurrentConversationId(conversation.id); + if (layoutStore.isMobileView) { + layoutStore.toggleSidebar(false); + } + }; + + const handleEditConversation = (conversation: Conversation) => { + setUpdateConversationModalContext(conversation); + }; + + const handleDeleteConversation = (conversation: Conversation) => { + conversationStore.clearConversation((item) => item.id !== conversation.id); + if (conversationStore.currentConversationId === conversation.id) { + conversationStore.setCurrentConversationId(undefined); + } + }; + + return ( + <> +
+
+ {conversationList.map((conversation) => { + return ( + + ); + })} +
+
0 && "ml-2"}`}> + +
+
+ + {updateConversationModalContext && ( + setUpdateConversationModalContext(undefined)} conversation={updateConversationModalContext} /> + )} + + ); +}; + +export default ConversationTabsView; diff --git a/src/components/ConversationView/Header.tsx b/src/components/ConversationView/Header.tsx index 8145bc2..b8b7e65 100644 --- a/src/components/ConversationView/Header.tsx +++ b/src/components/ConversationView/Header.tsx @@ -5,6 +5,7 @@ import { hasFeature } from "@/utils"; import Icon from "../Icon"; import GitHubStarBadge from "../GitHubStarBadge"; import SchemaDrawer from "../SchemaDrawer"; +import ConversationTabsView from "../ConversationTabsView"; interface Props { className?: string; @@ -25,36 +26,41 @@ const Header = (props: Props) => { return ( <> -
-
- - {title} - -
- {title} -
- - - - {hasFeature("debug") && ( - - )} + {title} + +
+ + + + + +
+ {hasFeature("debug") && ( + + )} +
+ + {hasFeature("debug") && }
{hasFeature("debug") && showSchemaDrawer && setShowSchemaDrawer(false)} />}