diff --git a/crates/agent-gateway/web/src/components/ui/switch.tsx b/crates/agent-gateway/web/src/components/ui/switch.tsx new file mode 100644 index 000000000..ff85f65a0 --- /dev/null +++ b/crates/agent-gateway/web/src/components/ui/switch.tsx @@ -0,0 +1,25 @@ +import { Switch as SwitchPrimitive } from "@base-ui/react"; +import * as React from "react"; + +import { cn } from "../../lib/shared/utils"; + +export const Switch = React.forwardRef< + HTMLElement, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +Switch.displayName = "Switch"; diff --git a/crates/agent-gateway/web/src/i18n/config.ts b/crates/agent-gateway/web/src/i18n/config.ts index 9229fda85..74775e428 100644 --- a/crates/agent-gateway/web/src/i18n/config.ts +++ b/crates/agent-gateway/web/src/i18n/config.ts @@ -935,6 +935,8 @@ export const translations: Record> = { "settings.groupConnectivity": "连接", "settings.backToChat": "返回对话", "settings.title": "设置", + "settings.searchPlaceholder": "搜索设置…", + "settings.searchNoResults": "未找到匹配的设置", /* ── Settings Devices ── */ "settings.devicesTitle": "多客户端管理", @@ -1185,6 +1187,9 @@ export const translations: Record> = { "settings.systemProxyInvalid": "代理已启用,请填写有效的代理地址和端口;配置有效前相关请求将直接报错。", "settings.systemProxyEnableHint": "请先填写有效的代理地址和端口后再启用代理。", + "settings.systemProxyDisabled": "当前未启用,仅在需要时配置并开启。", + "settings.systemProxySettings": "代理设置", + "settings.systemProxyDone": "完成", "settings.systemProxyType": "代理类型", "settings.systemProxyHost": "代理地址", "settings.systemProxyPort": "端口", @@ -3126,6 +3131,8 @@ export const translations: Record> = { "settings.groupConnectivity": "Connectivity", "settings.backToChat": "Back to Chat", "settings.title": "Settings", + "settings.searchPlaceholder": "Search settings…", + "settings.searchNoResults": "No matching settings", /* ── Settings Devices ── */ "settings.devicesTitle": "Multi-client Management", @@ -3391,6 +3398,9 @@ export const translations: Record> = { "The proxy is enabled. Enter a valid host and port; affected requests fail until the configuration is valid.", "settings.systemProxyEnableHint": "Enter a valid proxy host and port before enabling the proxy.", + "settings.systemProxyDisabled": "Currently off. Configure and enable it only when needed.", + "settings.systemProxySettings": "Proxy settings", + "settings.systemProxyDone": "Done", "settings.systemProxyType": "Proxy type", "settings.systemProxyHost": "Proxy host", "settings.systemProxyPort": "Port", diff --git a/crates/agent-gateway/web/src/pages/SettingsPage.tsx b/crates/agent-gateway/web/src/pages/SettingsPage.tsx index 967b540a5..f26432e7e 100644 --- a/crates/agent-gateway/web/src/pages/SettingsPage.tsx +++ b/crates/agent-gateway/web/src/pages/SettingsPage.tsx @@ -8,12 +8,14 @@ import { Cpu, Key, MonitorSmartphone, + Search, Settings2, Wrench, Zap, } from "../components/icons"; import { useLocale } from "../i18n"; +import { cn } from "../lib/shared/utils"; import { AgentsSection } from "./settings/AgentsSection"; import { CronSection } from "./settings/CronSection"; import { DevicesSection } from "./settings/DevicesSection"; @@ -40,8 +42,6 @@ function getSaveIndicator(state: SettingsPageProps["saveState"], t: (key: string text: t("settings.saveError"), title: state.message, }; - case "saved": - case "idle": default: return { dotClass: "bg-emerald-500", @@ -63,24 +63,17 @@ function NavItem({ icon, label, active, onClick }: NavItemProps) { ); } @@ -137,19 +130,23 @@ export function SettingsPage(props: SettingsPageProps) { const { t } = useLocale(); const [section, setSection] = useState(initialSection); const [pendingProviderId, setPendingProviderId] = useState(initialProviderId); + const [navQuery, setNavQuery] = useState(""); - const sectionLabels: Record = { - system: t("settings.navSystem"), - systemTools: t("settings.navSystemTools"), - providers: t("settings.navProviders"), - agents: t("settings.navAgents"), - ssh: t("settings.navSsh"), - memory: t("settings.navMemory"), - hooks: t("settings.navHooks"), - cron: t("settings.navCron"), - devices: t("settings.navAgentManagement"), - remote: t("settings.navRemote"), - }; + const sectionLabels = useMemo>( + () => ({ + system: t("settings.navSystem"), + systemTools: t("settings.navSystemTools"), + providers: t("settings.navProviders"), + agents: t("settings.navAgents"), + ssh: t("settings.navSsh"), + memory: t("settings.navMemory"), + hooks: t("settings.navHooks"), + cron: t("settings.navCron"), + devices: t("settings.navAgentManagement"), + remote: t("settings.navRemote"), + }), + [t], + ); const hiddenSectionSet = useMemo(() => new Set(hiddenSections), [hiddenSections]); const navGroups = useMemo( @@ -163,6 +160,16 @@ export function SettingsPage(props: SettingsPageProps) { [hiddenSectionSet, sectionLabels, t], ); const allNavItems = useMemo(() => navGroups.flatMap((g) => g.items), [navGroups]); + const visibleNavGroups = useMemo(() => { + const query = navQuery.trim().toLocaleLowerCase(); + if (!query) return navGroups; + return navGroups + .map((group) => ({ + ...group, + items: group.items.filter((item) => item.label.toLocaleLowerCase().includes(query)), + })) + .filter((group) => group.items.length > 0); + }, [navGroups, navQuery]); useEffect(() => { setSection(initialSection); @@ -221,7 +228,7 @@ export function SettingsPage(props: SettingsPageProps) { return (
-