From 03e138ba585c12a2dbe8ddb6a12a43c0a174e255 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Mon, 30 Dec 2024 19:15:28 +0400 Subject: [PATCH] UI stuff --- .../shared/inputs/api-key-input.tsx | 24 +++++++++++++------ .../shared/modals/settings/settings-form.tsx | 2 +- .../src/hooks/mutation/use-save-settings.ts | 4 ++-- frontend/src/hooks/query/use-settings.ts | 5 ++-- frontend/tests/settings.spec.ts | 2 +- openhands/server/routes/settings.py | 2 +- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/shared/inputs/api-key-input.tsx b/frontend/src/components/shared/inputs/api-key-input.tsx index ea6e553adbe9..7bdafb90bd1e 100644 --- a/frontend/src/components/shared/inputs/api-key-input.tsx +++ b/frontend/src/components/shared/inputs/api-key-input.tsx @@ -1,27 +1,37 @@ -import { Input } from "@nextui-org/react"; +import { Input, Tooltip } from "@nextui-org/react"; import { useTranslation } from "react-i18next"; +import { FaCheckCircle, FaExclamationCircle } from "react-icons/fa"; import { I18nKey } from "#/i18n/declaration"; interface APIKeyInputProps { isDisabled: boolean; - defaultValue: string; + isSet: boolean; } -export function APIKeyInput({ isDisabled, defaultValue }: APIKeyInputProps) { +export function APIKeyInput({ isDisabled, isSet }: APIKeyInputProps) { const { t } = useTranslation(); return (
- + + + {showAdvancedOptions && ( diff --git a/frontend/src/hooks/mutation/use-save-settings.ts b/frontend/src/hooks/mutation/use-save-settings.ts index 062d9639d543..61b9c71136fe 100644 --- a/frontend/src/hooks/mutation/use-save-settings.ts +++ b/frontend/src/hooks/mutation/use-save-settings.ts @@ -26,8 +26,8 @@ export const useSaveSettings = () => { return useMutation({ mutationFn: saveSettingsMutationFn, - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["settings"] }); + onSuccess: async () => { + await queryClient.invalidateQueries({ queryKey: ["settings"] }); updateSettingsVersion(logout); setIsUpToDate(true); }, diff --git a/frontend/src/hooks/query/use-settings.ts b/frontend/src/hooks/query/use-settings.ts index 794895e37796..96a195cceee5 100644 --- a/frontend/src/hooks/query/use-settings.ts +++ b/frontend/src/hooks/query/use-settings.ts @@ -7,7 +7,7 @@ import OpenHands from "#/api/open-hands"; const getSettingsQueryFn = async () => { const apiSettings = await OpenHands.getSettings(); - if (apiSettings != null) { + if (apiSettings !== null) { return { LLM_MODEL: apiSettings.llm_model, LLM_BASE_URL: apiSettings.llm_base_url, @@ -15,7 +15,7 @@ const getSettingsQueryFn = async () => { LANGUAGE: apiSettings.language, CONFIRMATION_MODE: apiSettings.confirmation_mode, SECURITY_ANALYZER: apiSettings.security_analyzer, - LLM_API_KEY: "", + LLM_API_KEY: apiSettings.llm_api_key, }; } @@ -27,6 +27,7 @@ export const useSettings = () => { queryKey: ["settings"], queryFn: getSettingsQueryFn, initialData: DEFAULT_SETTINGS, + refetchOnMount: false, }); React.useEffect(() => { diff --git a/frontend/tests/settings.spec.ts b/frontend/tests/settings.spec.ts index 2f6bcd4592b5..16f5cc595825 100644 --- a/frontend/tests/settings.spec.ts +++ b/frontend/tests/settings.spec.ts @@ -21,7 +21,7 @@ const selectGpt4o = async (page: Page) => { const modelSelectElement = aiConfigModal.getByTestId("llm-model"); await modelSelectElement.click(); - const gpt4Option = page.getByText("gpt-4o"); + const gpt4Option = page.getByText("gpt-4o", { exact: true }); await gpt4Option.click(); return { diff --git a/openhands/server/routes/settings.py b/openhands/server/routes/settings.py index e5eaa7035ec7..b28f2a0b7907 100644 --- a/openhands/server/routes/settings.py +++ b/openhands/server/routes/settings.py @@ -24,7 +24,7 @@ async def load_settings( settings = await settings_store.load() if settings: # For security reasons we don't ever send the api key to the client - settings.llm_api_key = None + settings.llm_api_key = 'SET' if settings.llm_api_key else None return settings except Exception as e: logger.warning(f'Invalid token: {e}')