From 52951dd78cb5a7ed560d0b045b2e8ea53d75b5f8 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Fri, 1 Nov 2024 11:46:11 +0800 Subject: [PATCH] feat: added sorting functionality and updated translations --- src/renderer/src/i18n/locales/en-us.json | 3 +- src/renderer/src/i18n/locales/zh-cn.json | 3 +- src/renderer/src/i18n/locales/zh-tw.json | 3 +- src/renderer/src/pages/agents/AgentsPage.tsx | 23 ++-- .../src/pages/agents/components/AgentCard.tsx | 18 ++-- .../agents/components/ManageAgentsPopup.tsx | 100 ++++++++++++++++++ .../{Agents.tsx => components/MyAgents.tsx} | 67 +++++------- 7 files changed, 153 insertions(+), 64 deletions(-) create mode 100644 src/renderer/src/pages/agents/components/ManageAgentsPopup.tsx rename src/renderer/src/pages/agents/{Agents.tsx => components/MyAgents.tsx} (66%) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 09e3e99c6a..e2ef5dae8b 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -196,7 +196,8 @@ "edit.message.empty.content": "Conversation input content cannot be empty", "edit.model.select.title": "Select Model", "edit.settings.hide_preset_messages": "Hide Preset Message", - "search.no_results": "No results found" + "search.no_results": "No results found", + "sorting.title": "Sorting" }, "minapp": { "title": "MinApp" diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index a17fd5cbd1..03e80c33c1 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -196,7 +196,8 @@ "edit.message.empty.content": "会话输入内容不能为空", "edit.model.select.title": "选择模型", "edit.settings.hide_preset_messages": "隐藏预设消息", - "search.no_results": "没有找到相关智能体" + "search.no_results": "没有找到相关智能体", + "sorting.title": "排序" }, "minapp": { "title": "小程序" diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index b2d8eab525..7770e21fec 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -196,7 +196,8 @@ "edit.message.empty.content": "會話輸入內容不能為空", "edit.model.select.title": "選擇模型", "edit.settings.hide_preset_messages": "隱藏預設消息", - "search.no_results": "沒有找到相關智能體" + "search.no_results": "沒有找到相關智能體", + "sorting.title": "排序" }, "minapp": { "title": "小程序" diff --git a/src/renderer/src/pages/agents/AgentsPage.tsx b/src/renderer/src/pages/agents/AgentsPage.tsx index 085353f1c9..97027b5a46 100644 --- a/src/renderer/src/pages/agents/AgentsPage.tsx +++ b/src/renderer/src/pages/agents/AgentsPage.tsx @@ -13,10 +13,8 @@ import ReactMarkdown from 'react-markdown' import styled from 'styled-components' import { groupTranslations } from './agentGroupTranslations' -import Agents from './Agents' -import AddAgentCard from './components/AddAgentCard' -import AddAgentPopup from './components/AddAgentPopup' import AgentCard from './components/AgentCard' +import MyAgents from './components/MyAgents' const { Title } = Typography @@ -131,12 +129,7 @@ const AgentsPage: FC = () => { {group === '我的' ? ( - <> - - AddAgentPopup.show()} /> - - - + ) : ( filteredAgentGroups[group]?.map((agent, index) => ( @@ -149,7 +142,7 @@ const AgentsPage: FC = () => { ) } }) - }, [filteredAgentGroups, getLocalizedGroupName, onAddAgentConfirm]) + }, [filteredAgentGroups, getLocalizedGroupName, onAddAgentConfirm, search]) return ( @@ -214,6 +207,7 @@ const TabContent = styled(Scrollbar)` height: calc(100vh - var(--navbar-height)); padding: 10px 10px 10px 15px; margin-right: -4px; + padding-bottom: 20px !important; overflow-x: hidden; ` @@ -240,8 +234,8 @@ const Tabs = styled(TabsAntd)` padding-right: 0 !important; } .ant-tabs-nav { - min-width: 120px; - max-width: 120px; + min-width: 140px; + max-width: 140px; } .ant-tabs-nav-list { padding: 10px 8px; @@ -253,8 +247,9 @@ const Tabs = styled(TabsAntd)` margin: 0 !important; border-radius: 20px; margin-bottom: 5px !important; - font-size: 14px; - justify-content: center; + font-size: 13px; + justify-content: left; + padding: 7px 12px !important; &:hover { color: var(--color-text) !important; background-color: var(--color-background-soft); diff --git a/src/renderer/src/pages/agents/components/AgentCard.tsx b/src/renderer/src/pages/agents/components/AgentCard.tsx index 04b8faa4e1..72fdd8e9a3 100644 --- a/src/renderer/src/pages/agents/components/AgentCard.tsx +++ b/src/renderer/src/pages/agents/components/AgentCard.tsx @@ -22,7 +22,7 @@ const AgentCard: React.FC = ({ agent, onClick, contextMenu, menuItems }) const prompt = (agent.description || agent.prompt).substring(0, 100).replace(/\\n/g, '') const content = ( - {agent.emoji && {agent.emoji}} + {emoji && {emoji}} {emoji} {menuItems && ( e.stopPropagation()}> @@ -41,7 +41,7 @@ const AgentCard: React.FC = ({ agent, onClick, contextMenu, menuItems }) }} trigger={['click']} placement="bottomRight"> - + )} @@ -112,14 +112,14 @@ const Container = styled.div` ` const EmojiContainer = styled.div` - width: 60px; - height: 60px; - min-width: 60px; - min-height: 60px; + width: 55px; + height: 55px; + min-width: 55px; + min-height: 55px; background-color: var(--color-background); border-radius: 50%; border: 4px solid var(--color-border); - margin-top: 5px; + margin-top: 8px; transition: all 0.5s ease; display: flex; align-items: center; @@ -131,7 +131,7 @@ const CardInfo = styled.div` display: flex; flex-direction: column; align-items: center; - gap: 8px; + gap: 5px; transition: all 0.5s ease; padding: 0 15px; width: 100%; @@ -177,7 +177,7 @@ const BannerBackground = styled.div` align-items: center; font-size: 500px; opacity: 0.1; - filter: blur(10px); + filter: blur(8px); z-index: 0; overflow: hidden; transition: all 0.5s ease; diff --git a/src/renderer/src/pages/agents/components/ManageAgentsPopup.tsx b/src/renderer/src/pages/agents/components/ManageAgentsPopup.tsx new file mode 100644 index 0000000000..88143a9a60 --- /dev/null +++ b/src/renderer/src/pages/agents/components/ManageAgentsPopup.tsx @@ -0,0 +1,100 @@ +import { MenuOutlined } from '@ant-design/icons' +import DragableList from '@renderer/components/DragableList' +import { Box, HStack } from '@renderer/components/Layout' +import { TopView } from '@renderer/components/TopView' +import { useAgents } from '@renderer/hooks/useAgents' +import { Empty, Modal } from 'antd' +import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import styled from 'styled-components' + +const PopupContainer: React.FC = () => { + const [open, setOpen] = useState(true) + const { t } = useTranslation() + const { agents, updateAgents } = useAgents() + + const onOk = () => { + setOpen(false) + } + + const onCancel = () => { + setOpen(false) + } + + const onClose = async () => { + ManageAgentsPopup.hide() + } + + useEffect(() => { + if (agents.length === 0) { + setOpen(false) + } + }, [agents]) + + return ( + + + {agents.length > 0 && ( + + {(item) => ( + + + {item.emoji} {item.name} + + + + + + )} + + )} + {agents.length === 0 && } + + + ) +} + +const Container = styled.div` + padding: 12px 0; + height: 50vh; + overflow-y: auto; + &::-webkit-scrollbar { + display: none; + } +` + +const AgentItem = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: 8px; + border-radius: 8px; + user-select: none; + background-color: var(--color-background-soft); + margin-bottom: 8px; + .anticon { + font-size: 16px; + color: var(--color-icon); + } + &:hover { + background-color: var(--color-background-mute); + } +` + +export default class ManageAgentsPopup { + static topviewId = 0 + static hide() { + TopView.hide('ManageAgentsPopup') + } + static show() { + TopView.show(, 'ManageAgentsPopup') + } +} diff --git a/src/renderer/src/pages/agents/Agents.tsx b/src/renderer/src/pages/agents/components/MyAgents.tsx similarity index 66% rename from src/renderer/src/pages/agents/Agents.tsx rename to src/renderer/src/pages/agents/components/MyAgents.tsx index 66aa2cc17b..845a6a6e58 100644 --- a/src/renderer/src/pages/agents/Agents.tsx +++ b/src/renderer/src/pages/agents/components/MyAgents.tsx @@ -1,23 +1,36 @@ -import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons' +import { DeleteOutlined, EditOutlined, PlusOutlined, SortAscendingOutlined } from '@ant-design/icons' import AssistantSettingsPopup from '@renderer/components/AssistantSettings' import { useAgents } from '@renderer/hooks/useAgents' import { createAssistantFromAgent } from '@renderer/services/AssistantService' import { Agent } from '@renderer/types' import { Col } from 'antd' -import { useCallback } from 'react' +import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import styled from 'styled-components' -import AgentCard from './components/AgentCard' +import AddAgentCard from './AddAgentCard' +import AddAgentPopup from './AddAgentPopup' +import AgentCard from './AgentCard' +import ManageAgentsPopup from './ManageAgentsPopup' interface Props { onClick?: (agent: Agent) => void + search?: string } -const Agents: React.FC = ({ onClick }) => { +const MyAgents: React.FC = ({ onClick, search }) => { const { t } = useTranslation() const { agents, removeAgent } = useAgents() + const filteredAgents = useMemo(() => { + if (!search?.trim()) return agents + + return agents.filter( + (agent) => + agent.name.toLowerCase().includes(search.toLowerCase()) || + agent.description?.toLowerCase().includes(search.toLowerCase()) + ) + }, [agents, search]) + const handleDelete = useCallback( (agent: Agent) => { window.modal.confirm({ @@ -31,7 +44,7 @@ const Agents: React.FC = ({ onClick }) => { return ( <> - {agents.map((agent) => { + {filteredAgents.map((agent) => { const dropdownMenuItems = [ { key: 'edit', @@ -45,6 +58,12 @@ const Agents: React.FC = ({ onClick }) => { icon: , onClick: () => createAssistantFromAgent(agent) }, + { + key: 'sort', + label: t('agents.sorting.title'), + icon: , + onClick: () => ManageAgentsPopup.show() + }, { key: 'delete', label: t('common.delete'), @@ -80,39 +99,11 @@ const Agents: React.FC = ({ onClick }) => { ) })} + + AddAgentPopup.show()} /> + ) } -const Container = styled.div` - padding: 10px 15px; - display: flex; - flex-direction: column; - min-height: calc(100vh - var(--navbar-height)); - min-width: var(--assistants-width); - max-width: var(--assistants-width); - overflow-y: auto; - overflow-x: hidden; - - &::-webkit-scrollbar { - width: 6px; - height: 6px; - } - - &::-webkit-scrollbar-track { - border-radius: 3px; - background: transparent; - } - - &::-webkit-scrollbar-thumb { - border-radius: 3px; - background: var(--color-scrollbar-thumb); - transition: all 0.2s ease-in-out; - } - - &:hover::-webkit-scrollbar-thumb { - background: var(--color-scrollbar-thumb); - } -` - -export default Agents +export default MyAgents