Download src/components/shared/modals/settings/settings-form.tsx from SaylorTwift/openhands: direct link, hf CLI and curl.
- Browser
- Download file 4.86 kB
-
https://huggingface.co/SaylorTwift/openhands/resolve/main/src/components/shared/modals/settings/settings-form.tsx
- Command line
-
hf download hf://SaylorTwift/openhands/src/components/shared/modals/settings/settings-form.tsx
-
curl -L -o settings-form.tsx https://huggingface.co/SaylorTwift/openhands/resolve/main/src/components/shared/modals/settings/settings-form.tsx
4.86 kB
| import { useTranslation } from "react-i18next"; | |
| import React from "react"; | |
| import { useTracking } from "#/hooks/use-tracking"; | |
| import { useNavigation } from "#/context/navigation-context"; | |
| import { I18nKey } from "#/i18n/declaration"; | |
| import { DangerModal } from "../confirmation-modals/danger-modal"; | |
| import { extractSettings } from "#/utils/settings-utils"; | |
| import { ModalBackdrop } from "../modal-backdrop"; | |
| import { ModelSelector } from "./model-selector"; | |
| import { Settings } from "#/types/settings"; | |
| import { BrandButton } from "#/components/features/settings/brand-button"; | |
| import { SettingsInput } from "#/components/features/settings/settings-input"; | |
| import { HelpLink } from "#/ui/help-link"; | |
| import { useSaveSettings } from "#/hooks/mutation/use-save-settings"; | |
| import { getAgentSettingValue } from "#/utils/sdk-settings-schema"; | |
| import { SETTINGS_FORM } from "#/utils/constants"; | |
| interface SettingsFormProps { | |
| settings: Settings; | |
| onClose: () => void; | |
| } | |
| export function SettingsForm({ settings, onClose }: SettingsFormProps) { | |
| const { trackSettingsSaved } = useTracking(); | |
| const { mutate: saveUserSettings } = useSaveSettings(); | |
| const { currentPath } = useNavigation(); | |
| const { t } = useTranslation("openhands"); | |
| const formRef = React.useRef<HTMLFormElement>(null); | |
| const [confirmEndSessionModalOpen, setConfirmEndSessionModalOpen] = | |
| React.useState(false); | |
| const handleFormSubmission = async (formData: FormData) => { | |
| const newSettings = extractSettings(formData); | |
| await saveUserSettings(newSettings, { | |
| onSuccess: () => { | |
| onClose(); | |
| const agentLlm = | |
| ((newSettings.agent_settings_diff as Record<string, unknown>) | |
| ?.llm as Record<string, unknown>) ?? {}; | |
| trackSettingsSaved({ | |
| llmModel: agentLlm.model, | |
| llmApiKeySet: agentLlm.api_key ? "SET" : "UNSET", | |
| searchApiKeySet: newSettings.search_api_key ? "SET" : "UNSET", | |
| remoteRuntimeResourceFactor: | |
| newSettings.remote_runtime_resource_factor, | |
| }); | |
| }, | |
| }); | |
| }; | |
| const handleConfirmEndSession = () => { | |
| const formData = new FormData(formRef.current ?? undefined); | |
| handleFormSubmission(formData); | |
| }; | |
| const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { | |
| event.preventDefault(); | |
| const formData = new FormData(event.currentTarget); | |
| if (currentPath.startsWith("/conversations/")) { | |
| setConfirmEndSessionModalOpen(true); | |
| } else { | |
| handleFormSubmission(formData); | |
| } | |
| }; | |
| const isLLMKeySet = settings.llm_api_key_set; | |
| const currentModel = getAgentSettingValue(settings, "llm.model"); | |
| return ( | |
| <div> | |
| <form | |
| ref={formRef} | |
| data-testid="settings-form" | |
| className="flex flex-col gap-6" | |
| onSubmit={handleSubmit} | |
| > | |
| <div className="flex flex-col gap-[17px]"> | |
| <ModelSelector | |
| currentModel={ | |
| typeof currentModel === "string" ? currentModel : undefined | |
| } | |
| wrapperClassName="!flex-col !gap-[17px]" | |
| labelClassName={SETTINGS_FORM.LABEL_CLASSNAME} | |
| /> | |
| <SettingsInput | |
| testId="llm-api-key-input" | |
| name="llm-api-key-input" | |
| label={t(I18nKey.SETTINGS_FORM$API_KEY)} | |
| type="password" | |
| className="w-full" | |
| // eslint-disable-next-line i18next/no-literal-string -- masked-key sentinel, not translatable | |
| placeholder={isLLMKeySet ? "<hidden>" : ""} | |
| labelClassName={SETTINGS_FORM.LABEL_CLASSNAME} | |
| /> | |
| <HelpLink | |
| testId="llm-api-key-help-anchor" | |
| text={t(I18nKey.SETTINGS$DONT_KNOW_API_KEY)} | |
| linkText={t(I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS)} | |
| href="https://docs.openhands.dev/usage/local-setup#getting-an-api-key" | |
| size="settings" | |
| linkColor="white" | |
| /> | |
| </div> | |
| <div className="flex flex-col gap-2"> | |
| <BrandButton | |
| testId="save-settings-button" | |
| type="submit" | |
| variant="primary" | |
| className="w-full" | |
| > | |
| {t(I18nKey.BUTTON$SAVE)} | |
| </BrandButton> | |
| </div> | |
| </form> | |
| {confirmEndSessionModalOpen && ( | |
| <ModalBackdrop> | |
| <DangerModal | |
| title={t(I18nKey.MODAL$END_SESSION_TITLE)} | |
| description={t(I18nKey.MODAL$END_SESSION_MESSAGE)} | |
| buttons={{ | |
| danger: { | |
| text: t(I18nKey.BUTTON$END_SESSION), | |
| onClick: handleConfirmEndSession, | |
| }, | |
| cancel: { | |
| text: t(I18nKey.BUTTON$CANCEL), | |
| onClick: () => setConfirmEndSessionModalOpen(false), | |
| }, | |
| }} | |
| /> | |
| </ModalBackdrop> | |
| )} | |
| </div> | |
| ); | |
| } | |