From 677088225dc79b570b28b4ad040845ef076b12af Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Tue, 26 Nov 2024 23:33:15 +0400 Subject: [PATCH 01/13] Refactor and move some components --- frontend/src/components/action-tooltip.tsx | 33 +++ .../analytics-consent-form-modal.tsx | 2 +- frontend/src/components/chat-interface.tsx | 4 +- .../components/chat/confirmation-buttons.tsx | 64 ----- .../src/components/confirmation-buttons.tsx | 32 +++ .../components/{form => }/custom-input.tsx | 0 frontend/src/components/feedback-form.tsx | 2 +- .../file-explorer/explorer-tree.tsx | 7 +- .../file-explorer/file-explorer.tsx | 2 +- .../components/{form => }/form-fieldset.tsx | 4 +- .../github-repositories-suggestion-box.tsx | 2 +- .../inputs/advanced-option-switch.tsx | 40 +++ .../src/components/inputs/agent-input.tsx | 46 +++ .../src/components/inputs/api-key-input.tsx | 42 +++ .../src/components/inputs/base-url-input.tsx | 30 ++ .../inputs/confirmation-mode-switch.tsx | 37 +++ .../components/inputs/custom-model-input.tsx | 36 +++ .../inputs/security-analyzers-input.tsx | 47 ++++ .../components/{buttons => }/modal-button.tsx | 0 .../modals/account-settings-modal.tsx | 6 +- .../modals/confirmation-modals/base-modal.tsx | 2 +- .../modals/connect-to-github-modal.tsx | 4 +- .../components/{form => }/settings-form.tsx | 262 +++++------------- .../components/{terminal => }/terminal.tsx | 0 .../{chat => }/typing-indicator.tsx | 6 +- frontend/src/components/waitlist-modal.tsx | 2 +- .../src/{components/chat => }/message.d.ts | 0 frontend/src/routes/_oh.tsx | 2 +- 28 files changed, 427 insertions(+), 287 deletions(-) create mode 100644 frontend/src/components/action-tooltip.tsx delete mode 100644 frontend/src/components/chat/confirmation-buttons.tsx create mode 100644 frontend/src/components/confirmation-buttons.tsx rename frontend/src/components/{form => }/custom-input.tsx (100%) rename frontend/src/components/{form => }/form-fieldset.tsx (94%) create mode 100644 frontend/src/components/inputs/advanced-option-switch.tsx create mode 100644 frontend/src/components/inputs/agent-input.tsx create mode 100644 frontend/src/components/inputs/api-key-input.tsx create mode 100644 frontend/src/components/inputs/base-url-input.tsx create mode 100644 frontend/src/components/inputs/confirmation-mode-switch.tsx create mode 100644 frontend/src/components/inputs/custom-model-input.tsx create mode 100644 frontend/src/components/inputs/security-analyzers-input.tsx rename frontend/src/components/{buttons => }/modal-button.tsx (100%) rename frontend/src/components/{form => }/settings-form.tsx (55%) rename frontend/src/components/{terminal => }/terminal.tsx (100%) rename frontend/src/components/{chat => }/typing-indicator.tsx (85%) rename frontend/src/{components/chat => }/message.d.ts (100%) diff --git a/frontend/src/components/action-tooltip.tsx b/frontend/src/components/action-tooltip.tsx new file mode 100644 index 000000000000..eb2053a7bdf4 --- /dev/null +++ b/frontend/src/components/action-tooltip.tsx @@ -0,0 +1,33 @@ +import { Tooltip } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import ConfirmIcon from "#/assets/confirm"; +import RejectIcon from "#/assets/reject"; +import { I18nKey } from "#/i18n/declaration"; + +interface ActionTooltipProps { + type: "confirm" | "reject"; + onClick: () => void; +} + +export function ActionTooltip({ type, onClick }: ActionTooltipProps) { + const { t } = useTranslation(); + + const content = + type === "confirm" + ? t(I18nKey.CHAT_INTERFACE$USER_CONFIRMED) + : t(I18nKey.CHAT_INTERFACE$USER_REJECTED); + + return ( + + + + ); +} diff --git a/frontend/src/components/analytics-consent-form-modal.tsx b/frontend/src/components/analytics-consent-form-modal.tsx index 84f336092023..f40f85e47950 100644 --- a/frontend/src/components/analytics-consent-form-modal.tsx +++ b/frontend/src/components/analytics-consent-form-modal.tsx @@ -1,6 +1,6 @@ import { ModalBackdrop } from "./modals/modal-backdrop"; import ModalBody from "./modals/modal-body"; -import ModalButton from "./buttons/modal-button"; +import ModalButton from "./modal-button"; import { BaseModalTitle, BaseModalDescription, diff --git a/frontend/src/components/chat-interface.tsx b/frontend/src/components/chat-interface.tsx index 6d12b9cc6baa..a462280e4950 100644 --- a/frontend/src/components/chat-interface.tsx +++ b/frontend/src/components/chat-interface.tsx @@ -13,8 +13,8 @@ import AgentState from "#/types/agent-state"; import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { FeedbackModal } from "./feedback-modal"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; -import TypingIndicator from "./chat/typing-indicator"; -import ConfirmationButtons from "./chat/confirmation-buttons"; +import { TypingIndicator } from "./typing-indicator"; +import { ConfirmationButtons } from "./confirmation-buttons"; import { ErrorMessage } from "./error-message"; import { ContinueButton } from "./continue-button"; import { ScrollToBottomButton } from "./scroll-to-bottom-button"; diff --git a/frontend/src/components/chat/confirmation-buttons.tsx b/frontend/src/components/chat/confirmation-buttons.tsx deleted file mode 100644 index 5e0eaf37c405..000000000000 --- a/frontend/src/components/chat/confirmation-buttons.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { Tooltip } from "@nextui-org/react"; -import { useTranslation } from "react-i18next"; -import ConfirmIcon from "#/assets/confirm"; -import RejectIcon from "#/assets/reject"; -import { I18nKey } from "#/i18n/declaration"; -import AgentState from "#/types/agent-state"; -import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; -import { useWsClient } from "#/context/ws-client-provider"; - -interface ActionTooltipProps { - type: "confirm" | "reject"; - onClick: () => void; -} - -function ActionTooltip({ type, onClick }: ActionTooltipProps) { - const { t } = useTranslation(); - - const content = - type === "confirm" - ? t(I18nKey.CHAT_INTERFACE$USER_CONFIRMED) - : t(I18nKey.CHAT_INTERFACE$USER_REJECTED); - - return ( - - - - ); -} - -function ConfirmationButtons() { - const { t } = useTranslation(); - const { send } = useWsClient(); - - const handleStateChange = (state: AgentState) => { - const event = generateAgentStateChangeEvent(state); - send(event); - }; - - return ( -
-

{t(I18nKey.CHAT_INTERFACE$USER_ASK_CONFIRMATION)}

-
- handleStateChange(AgentState.USER_CONFIRMED)} - /> - handleStateChange(AgentState.USER_REJECTED)} - /> -
-
- ); -} - -export default ConfirmationButtons; diff --git a/frontend/src/components/confirmation-buttons.tsx b/frontend/src/components/confirmation-buttons.tsx new file mode 100644 index 000000000000..368c00132c28 --- /dev/null +++ b/frontend/src/components/confirmation-buttons.tsx @@ -0,0 +1,32 @@ +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; +import AgentState from "#/types/agent-state"; +import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; +import { useWsClient } from "#/context/ws-client-provider"; +import { ActionTooltip } from "./action-tooltip"; + +export function ConfirmationButtons() { + const { t } = useTranslation(); + const { send } = useWsClient(); + + const handleStateChange = (state: AgentState) => { + const event = generateAgentStateChangeEvent(state); + send(event); + }; + + return ( +
+

{t(I18nKey.CHAT_INTERFACE$USER_ASK_CONFIRMATION)}

+
+ handleStateChange(AgentState.USER_CONFIRMED)} + /> + handleStateChange(AgentState.USER_REJECTED)} + /> +
+
+ ); +} diff --git a/frontend/src/components/form/custom-input.tsx b/frontend/src/components/custom-input.tsx similarity index 100% rename from frontend/src/components/form/custom-input.tsx rename to frontend/src/components/custom-input.tsx diff --git a/frontend/src/components/feedback-form.tsx b/frontend/src/components/feedback-form.tsx index ca3645817b43..ddeb52335580 100644 --- a/frontend/src/components/feedback-form.tsx +++ b/frontend/src/components/feedback-form.tsx @@ -1,6 +1,6 @@ import React from "react"; import hotToast from "react-hot-toast"; -import ModalButton from "./buttons/modal-button"; +import ModalButton from "./modal-button"; import { Feedback } from "#/api/open-hands.types"; import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback"; diff --git a/frontend/src/components/file-explorer/explorer-tree.tsx b/frontend/src/components/file-explorer/explorer-tree.tsx index 30a04eb3699f..01ddea816d40 100644 --- a/frontend/src/components/file-explorer/explorer-tree.tsx +++ b/frontend/src/components/file-explorer/explorer-tree.tsx @@ -7,7 +7,10 @@ interface ExplorerTreeProps { defaultOpen?: boolean; } -function ExplorerTree({ files, defaultOpen = false }: ExplorerTreeProps) { +export function ExplorerTree({ + files, + defaultOpen = false, +}: ExplorerTreeProps) { const { t } = useTranslation(); if (!files?.length) { const message = !files @@ -23,5 +26,3 @@ function ExplorerTree({ files, defaultOpen = false }: ExplorerTreeProps) { ); } - -export default ExplorerTree; diff --git a/frontend/src/components/file-explorer/file-explorer.tsx b/frontend/src/components/file-explorer/file-explorer.tsx index 5c82a7fa8482..a6ccecbe4698 100644 --- a/frontend/src/components/file-explorer/file-explorer.tsx +++ b/frontend/src/components/file-explorer/file-explorer.tsx @@ -12,7 +12,7 @@ import { twMerge } from "tailwind-merge"; import AgentState from "#/types/agent-state"; import { addAssistantMessage } from "#/state/chat-slice"; import IconButton from "../icon-button"; -import ExplorerTree from "./explorer-tree"; +import { ExplorerTree } from "./explorer-tree"; import toast from "#/utils/toast"; import { RootState } from "#/store"; import { I18nKey } from "#/i18n/declaration"; diff --git a/frontend/src/components/form/form-fieldset.tsx b/frontend/src/components/form-fieldset.tsx similarity index 94% rename from frontend/src/components/form/form-fieldset.tsx rename to frontend/src/components/form-fieldset.tsx index df40b45511f7..ef0879a77c7f 100644 --- a/frontend/src/components/form/form-fieldset.tsx +++ b/frontend/src/components/form-fieldset.tsx @@ -8,7 +8,7 @@ interface FormFieldsetProps { isClearable?: boolean; } -function FormFieldset({ +export function FormFieldset({ id, label, items, @@ -41,5 +41,3 @@ function FormFieldset({ ); } - -export default FormFieldset; diff --git a/frontend/src/components/github-repositories-suggestion-box.tsx b/frontend/src/components/github-repositories-suggestion-box.tsx index 43777c3f83d7..c74954899684 100644 --- a/frontend/src/components/github-repositories-suggestion-box.tsx +++ b/frontend/src/components/github-repositories-suggestion-box.tsx @@ -4,7 +4,7 @@ import { SuggestionBox } from "#/routes/_oh._index/suggestion-box"; import { ConnectToGitHubModal } from "./modals/connect-to-github-modal"; import { ModalBackdrop } from "./modals/modal-backdrop"; import { GitHubRepositorySelector } from "#/routes/_oh._index/github-repo-selector"; -import ModalButton from "./buttons/modal-button"; +import ModalButton from "./modal-button"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; interface GitHubRepositoriesSuggestionBoxProps { diff --git a/frontend/src/components/inputs/advanced-option-switch.tsx b/frontend/src/components/inputs/advanced-option-switch.tsx new file mode 100644 index 000000000000..9b5368b4ab65 --- /dev/null +++ b/frontend/src/components/inputs/advanced-option-switch.tsx @@ -0,0 +1,40 @@ +import { Switch } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; +import { cn } from "#/utils/utils"; + +interface AdvancedOptionSwitchProps { + isDisabled: boolean; + showAdvancedOptions: boolean; + setShowAdvancedOptions: (value: boolean) => void; +} + +export function AdvancedOptionSwitch({ + isDisabled, + showAdvancedOptions, + setShowAdvancedOptions, +}: AdvancedOptionSwitchProps) { + const { t } = useTranslation(); + + return ( + + {t(I18nKey.SETTINGS_FORM$ADVANCED_OPTIONS_LABEL)} + + ); +} diff --git a/frontend/src/components/inputs/agent-input.tsx b/frontend/src/components/inputs/agent-input.tsx new file mode 100644 index 000000000000..0dd21f4b0462 --- /dev/null +++ b/frontend/src/components/inputs/agent-input.tsx @@ -0,0 +1,46 @@ +import { Autocomplete, AutocompleteItem } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; + +interface AgentInputProps { + isDisabled: boolean; + defaultValue: string; + agents: string[]; +} + +export function AgentInput({ + isDisabled, + defaultValue, + agents, +}: AgentInputProps) { + const { t } = useTranslation(); + + return ( +
+ + + {agents.map((agent) => ( + + {agent} + + ))} + +
+ ); +} diff --git a/frontend/src/components/inputs/api-key-input.tsx b/frontend/src/components/inputs/api-key-input.tsx new file mode 100644 index 000000000000..ea6e553adbe9 --- /dev/null +++ b/frontend/src/components/inputs/api-key-input.tsx @@ -0,0 +1,42 @@ +import { Input } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; + +interface APIKeyInputProps { + isDisabled: boolean; + defaultValue: string; +} + +export function APIKeyInput({ isDisabled, defaultValue }: APIKeyInputProps) { + const { t } = useTranslation(); + + return ( +
+ + +

+ {t(I18nKey.SETTINGS_FORM$DONT_KNOW_API_KEY_LABEL)}{" "} + + {t(I18nKey.SETTINGS_FORM$CLICK_HERE_FOR_INSTRUCTIONS_LABEL)} + +

+
+ ); +} diff --git a/frontend/src/components/inputs/base-url-input.tsx b/frontend/src/components/inputs/base-url-input.tsx new file mode 100644 index 000000000000..d70d1eb9ea13 --- /dev/null +++ b/frontend/src/components/inputs/base-url-input.tsx @@ -0,0 +1,30 @@ +import { Input } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; + +interface BaseUrlInputProps { + isDisabled: boolean; + defaultValue: string; +} + +export function BaseUrlInput({ isDisabled, defaultValue }: BaseUrlInputProps) { + const { t } = useTranslation(); + + return ( +
+ + +
+ ); +} diff --git a/frontend/src/components/inputs/confirmation-mode-switch.tsx b/frontend/src/components/inputs/confirmation-mode-switch.tsx new file mode 100644 index 000000000000..39fd11ab6eb5 --- /dev/null +++ b/frontend/src/components/inputs/confirmation-mode-switch.tsx @@ -0,0 +1,37 @@ +import { Switch } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; +import { cn } from "#/utils/utils"; + +interface ConfirmationModeSwitchProps { + isDisabled: boolean; + defaultSelected: boolean; +} + +export function ConfirmationModeSwitch({ + isDisabled, + defaultSelected, +}: ConfirmationModeSwitchProps) { + const { t } = useTranslation(); + + return ( + + {t(I18nKey.SETTINGS_FORM$ENABLE_CONFIRMATION_MODE_LABEL)} + + ); +} diff --git a/frontend/src/components/inputs/custom-model-input.tsx b/frontend/src/components/inputs/custom-model-input.tsx new file mode 100644 index 000000000000..b40fd2256566 --- /dev/null +++ b/frontend/src/components/inputs/custom-model-input.tsx @@ -0,0 +1,36 @@ +import { Input } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; + +interface CustomModelInputProps { + isDisabled: boolean; + defaultValue: string; +} + +export function CustomModelInput({ + isDisabled, + defaultValue, +}: CustomModelInputProps) { + const { t } = useTranslation(); + + return ( +
+ + +
+ ); +} diff --git a/frontend/src/components/inputs/security-analyzers-input.tsx b/frontend/src/components/inputs/security-analyzers-input.tsx new file mode 100644 index 000000000000..e5e6d159cf9c --- /dev/null +++ b/frontend/src/components/inputs/security-analyzers-input.tsx @@ -0,0 +1,47 @@ +import { Autocomplete, AutocompleteItem } from "@nextui-org/react"; +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; + +interface SecurityAnalyzerInputProps { + isDisabled: boolean; + defaultValue: string; + securityAnalyzers: string[]; +} + +export function SecurityAnalyzerInput({ + isDisabled, + defaultValue, + securityAnalyzers, +}: SecurityAnalyzerInputProps) { + const { t } = useTranslation(); + + return ( +
+ + + {securityAnalyzers.map((analyzer) => ( + + {analyzer} + + ))} + +
+ ); +} diff --git a/frontend/src/components/buttons/modal-button.tsx b/frontend/src/components/modal-button.tsx similarity index 100% rename from frontend/src/components/buttons/modal-button.tsx rename to frontend/src/components/modal-button.tsx diff --git a/frontend/src/components/modals/account-settings-modal.tsx b/frontend/src/components/modals/account-settings-modal.tsx index 59b25cc0de95..76f26722d23b 100644 --- a/frontend/src/components/modals/account-settings-modal.tsx +++ b/frontend/src/components/modals/account-settings-modal.tsx @@ -5,9 +5,9 @@ import { BaseModalTitle, } from "./confirmation-modals/base-modal"; import ModalBody from "./modal-body"; -import ModalButton from "../buttons/modal-button"; -import FormFieldset from "../form/form-fieldset"; -import { CustomInput } from "../form/custom-input"; +import ModalButton from "../modal-button"; +import { FormFieldset } from "../form-fieldset"; +import { CustomInput } from "../custom-input"; import { AvailableLanguages } from "#/i18n"; import { I18nKey } from "#/i18n/declaration"; import { useAuth } from "#/context/auth-context"; diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/modals/confirmation-modals/base-modal.tsx index 3f7b6a80b533..b97db46d81c6 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/base-modal.tsx @@ -1,5 +1,5 @@ import React from "react"; -import ModalButton from "#/components/buttons/modal-button"; +import ModalButton from "#/components/modal-button"; import ModalBody from "../modal-body"; interface ButtonConfig { diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/modals/connect-to-github-modal.tsx index 0e6d52fc2517..57468cd1cafd 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/modals/connect-to-github-modal.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import ModalBody from "./modal-body"; -import { CustomInput } from "../form/custom-input"; -import ModalButton from "../buttons/modal-button"; +import { CustomInput } from "../custom-input"; +import ModalButton from "../modal-button"; import { BaseModalDescription, BaseModalTitle, diff --git a/frontend/src/components/form/settings-form.tsx b/frontend/src/components/settings-form.tsx similarity index 55% rename from frontend/src/components/form/settings-form.tsx rename to frontend/src/components/settings-form.tsx index 4a464b4cef81..2d23137fc740 100644 --- a/frontend/src/components/form/settings-form.tsx +++ b/frontend/src/components/settings-form.tsx @@ -1,12 +1,5 @@ -import { - Autocomplete, - AutocompleteItem, - Input, - Switch, -} from "@nextui-org/react"; import { useLocation } from "@remix-run/react"; import { useTranslation } from "react-i18next"; -import clsx from "clsx"; import React from "react"; import posthog from "posthog-js"; import { organizeModelsAndProviders } from "#/utils/organize-models-and-providers"; @@ -14,8 +7,8 @@ import { ModelSelector } from "#/components/modals/settings/model-selector"; import { getDefaultSettings, Settings } from "#/services/settings"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { extractModelAndProvider } from "#/utils/extract-model-and-provider"; -import ModalButton from "../buttons/modal-button"; -import { DangerModal } from "../modals/confirmation-modals/danger-modal"; +import ModalButton from "./modal-button"; +import { DangerModal } from "./modals/confirmation-modals/danger-modal"; import { I18nKey } from "#/i18n/declaration"; import { extractSettings, @@ -24,6 +17,13 @@ import { } from "#/utils/settings-utils"; import { useEndSession } from "#/hooks/use-end-session"; import { useUserPrefs } from "#/context/user-prefs-context"; +import { AdvancedOptionSwitch } from "./inputs/advanced-option-switch"; +import { CustomModelInput } from "./inputs/custom-model-input"; +import { BaseUrlInput } from "./inputs/base-url-input"; +import { AgentInput } from "./inputs/agent-input"; +import { APIKeyInput } from "./inputs/api-key-input"; +import { SecurityAnalyzerInput } from "./inputs/security-analyzers-input"; +import { ConfirmationModeSwitch } from "./inputs/confirmation-mode-switch"; interface SettingsFormProps { disabled?: boolean; @@ -50,29 +50,6 @@ export function SettingsForm({ const formRef = React.useRef(null); - const resetOngoingSession = () => { - if (location.pathname.startsWith("/app")) { - endSession(); - onClose(); - } - }; - - const handleFormSubmission = (formData: FormData) => { - const keys = Array.from(formData.keys()); - const isUsingAdvancedOptions = keys.includes("use-advanced-options"); - const newSettings = extractSettings(formData); - - saveSettings(newSettings); - saveSettingsView(isUsingAdvancedOptions ? "advanced" : "basic"); - updateSettingsVersion(); - resetOngoingSession(); - - posthog.capture("settings_saved", { - LLM_MODEL: newSettings.LLM_MODEL, - LLM_API_KEY: newSettings.LLM_API_KEY ? "SET" : "UNSET", - }); - }; - const advancedAlreadyInUse = React.useMemo(() => { if (models.length > 0) { const organizedModels = organizeModelsAndProviders(models); @@ -107,6 +84,29 @@ export function SettingsForm({ React.useState(false); const [showWarningModal, setShowWarningModal] = React.useState(false); + const resetOngoingSession = () => { + if (location.pathname.startsWith("/app")) { + endSession(); + onClose(); + } + }; + + const handleFormSubmission = (formData: FormData) => { + const keys = Array.from(formData.keys()); + const isUsingAdvancedOptions = keys.includes("use-advanced-options"); + const newSettings = extractSettings(formData); + + saveSettings(newSettings); + saveSettingsView(isUsingAdvancedOptions ? "advanced" : "basic"); + updateSettingsVersion(); + resetOngoingSession(); + + posthog.capture("settings_saved", { + LLM_MODEL: newSettings.LLM_MODEL, + LLM_API_KEY: newSettings.LLM_API_KEY ? "SET" : "UNSET", + }); + }; + const handleConfirmResetSettings = () => { saveSettings(getDefaultSettings()); resetOngoingSession(); @@ -164,66 +164,23 @@ export function SettingsForm({ onSubmit={handleSubmit} >
- - {t(I18nKey.SETTINGS_FORM$ADVANCED_OPTIONS_LABEL)} - + {showAdvancedOptions && ( <> -
- - -
-
- - -
+ + + )} @@ -235,122 +192,31 @@ export function SettingsForm({ /> )} -
- - -

- {t(I18nKey.SETTINGS_FORM$DONT_KNOW_API_KEY_LABEL)}{" "} - - {t(I18nKey.SETTINGS_FORM$CLICK_HERE_FOR_INSTRUCTIONS_LABEL)} - -

-
+ {showAdvancedOptions && ( -
- - - {agents.map((agent) => ( - - {agent} - - ))} - -
+ )} {showAdvancedOptions && ( <> -
- - - {securityAnalyzers.map((analyzer) => ( - - {analyzer} - - ))} - -
- - + + - {t(I18nKey.SETTINGS_FORM$ENABLE_CONFIRMATION_MODE_LABEL)} - + /> )}
diff --git a/frontend/src/components/terminal/terminal.tsx b/frontend/src/components/terminal.tsx similarity index 100% rename from frontend/src/components/terminal/terminal.tsx rename to frontend/src/components/terminal.tsx diff --git a/frontend/src/components/chat/typing-indicator.tsx b/frontend/src/components/typing-indicator.tsx similarity index 85% rename from frontend/src/components/chat/typing-indicator.tsx rename to frontend/src/components/typing-indicator.tsx index 528bc45c4059..013c59066c33 100644 --- a/frontend/src/components/chat/typing-indicator.tsx +++ b/frontend/src/components/typing-indicator.tsx @@ -1,6 +1,4 @@ -import React from "react"; - -function TypingIndicator(): React.ReactElement { +export function TypingIndicator() { return (
); } - -export default TypingIndicator; diff --git a/frontend/src/components/waitlist-modal.tsx b/frontend/src/components/waitlist-modal.tsx index 9f8b4f454809..736bc41459db 100644 --- a/frontend/src/components/waitlist-modal.tsx +++ b/frontend/src/components/waitlist-modal.tsx @@ -1,4 +1,4 @@ -import ModalButton from "./buttons/modal-button"; +import ModalButton from "./modal-button"; import { ModalBackdrop } from "./modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; diff --git a/frontend/src/components/chat/message.d.ts b/frontend/src/message.d.ts similarity index 100% rename from frontend/src/components/chat/message.d.ts rename to frontend/src/message.d.ts diff --git a/frontend/src/routes/_oh.tsx b/frontend/src/routes/_oh.tsx index 9a37b8b4d82b..9e5e7bbe4360 100644 --- a/frontend/src/routes/_oh.tsx +++ b/frontend/src/routes/_oh.tsx @@ -7,7 +7,7 @@ import { } from "@remix-run/react"; import { useDispatch } from "react-redux"; import CogTooth from "#/assets/cog-tooth"; -import { SettingsForm } from "#/components/form/settings-form"; +import { SettingsForm } from "#/components/settings-form"; import AccountSettingsModal from "#/components/modals/account-settings-modal"; import { DangerModal } from "#/components/modals/confirmation-modals/danger-modal"; import { LoadingSpinner } from "#/components/modals/loading-project"; From 97242b32f61b13b42aa8be7e403bed1140596b4d Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:00:25 +0400 Subject: [PATCH 02/13] Break down and refactor components --- .../__tests__/components/browser.test.tsx | 2 +- .../file-explorer/explorer-tree.test.tsx | 2 +- .../components/terminal/terminal.test.tsx | 2 +- frontend/src/components/action-button.tsx | 40 +++++++ frontend/src/components/agent-control-bar.tsx | 73 +------------ frontend/src/components/agent-status-bar.tsx | 103 ++---------------- .../components/agent-status-map.constant.ts | 64 +++++++++++ .../analytics-consent-form-modal.tsx | 2 +- frontend/src/components/avatar.tsx | 9 ++ frontend/src/components/beta-badge.tsx | 7 ++ frontend/src/components/browser-snapshot.tsx | 14 +++ frontend/src/components/browser.tsx | 23 +--- frontend/src/components/chat-input.tsx | 24 +--- frontend/src/components/chat-message.tsx | 24 +--- frontend/src/components/container.tsx | 28 +---- frontend/src/components/controls.tsx | 14 +-- .../components/copy-to-clipboard-button.tsx | 34 ++++++ .../src/components/editor-action-button.tsx | 29 +++++ frontend/src/components/editor-actions.tsx | 31 +----- .../src/components/empty-browser-message.tsx | 14 +++ .../extension-icon-map.constant.tsx | 20 ++++ .../src/components/feedback-action-button.tsx | 22 ++++ frontend/src/components/feedback-actions.tsx | 24 +--- frontend/src/components/feedback-form.tsx | 2 +- .../components/file-explorer/tree-node.tsx | 4 +- frontend/src/components/file-icons.tsx | 27 +---- frontend/src/components/folder-icon.tsx | 4 +- .../github-repositories-suggestion-box.tsx | 2 +- frontend/src/components/icon-button.tsx | 4 +- frontend/src/components/image-preview.tsx | 28 +---- .../src/components/join-waitlist-anchor.tsx | 12 ++ .../src/components/jupyter-cell-input.tsx | 22 ++++ .../src/components/jupyter-cell-output.tsx | 40 +++++++ frontend/src/components/jupyter-cell.tsx | 23 ++++ .../jupyter-scroll-to-bottom-button.tsx | 26 +++++ frontend/src/components/jupyter.tsx | 99 +---------------- frontend/src/components/modal-button.tsx | 4 +- .../modals/account-settings-form.tsx | 2 +- .../modals/confirmation-modals/base-modal.tsx | 2 +- .../modals/connect-to-github-modal.tsx | 2 +- frontend/src/components/nav-tab.tsx | 32 ++++++ frontend/src/components/refresh-button.tsx | 13 +++ frontend/src/components/remove-button.tsx | 21 ++++ frontend/src/components/security-lock.tsx | 17 +++ frontend/src/components/settings-form.tsx | 2 +- frontend/src/components/stop-button.tsx | 19 ++++ frontend/src/components/submit-button.tsx | 20 ++++ frontend/src/components/suggestion-bubble.tsx | 17 ++- frontend/src/components/terminal.tsx | 2 +- frontend/src/components/thumbnail.tsx | 21 ++++ frontend/src/components/user-avatar.tsx | 9 +- frontend/src/components/waitlist-message.tsx | 35 ++++++ frontend/src/components/waitlist-modal.tsx | 42 +------ .../src/ignore-task-state-map.constant.ts | 26 +++++ .../buttons/refresh-icon-button.tsx | 2 +- .../buttons/toggle-workspace-icon-button.tsx | 2 +- .../buttons/upload-icon-button.tsx | 2 +- .../file-explorer/file-explorer.tsx | 2 +- frontend/src/routes/_oh.app.browser.tsx | 2 +- frontend/src/routes/_oh.app.jupyter.tsx | 2 +- .../src/routes/_oh.app/chat-interface.tsx | 2 +- frontend/src/routes/_oh.app/messages.tsx | 2 +- frontend/src/routes/_oh.app/route.tsx | 2 +- .../src/routes/_oh/modals/settings-modal.tsx | 2 +- frontend/src/utils/parse-cell-content.ts | 24 ++++ 65 files changed, 694 insertions(+), 534 deletions(-) create mode 100644 frontend/src/components/action-button.tsx create mode 100644 frontend/src/components/agent-status-map.constant.ts create mode 100644 frontend/src/components/avatar.tsx create mode 100644 frontend/src/components/beta-badge.tsx create mode 100644 frontend/src/components/browser-snapshot.tsx create mode 100644 frontend/src/components/copy-to-clipboard-button.tsx create mode 100644 frontend/src/components/editor-action-button.tsx create mode 100644 frontend/src/components/empty-browser-message.tsx create mode 100644 frontend/src/components/extension-icon-map.constant.tsx create mode 100644 frontend/src/components/feedback-action-button.tsx create mode 100644 frontend/src/components/join-waitlist-anchor.tsx create mode 100644 frontend/src/components/jupyter-cell-input.tsx create mode 100644 frontend/src/components/jupyter-cell-output.tsx create mode 100644 frontend/src/components/jupyter-cell.tsx create mode 100644 frontend/src/components/jupyter-scroll-to-bottom-button.tsx create mode 100644 frontend/src/components/nav-tab.tsx create mode 100644 frontend/src/components/refresh-button.tsx create mode 100644 frontend/src/components/remove-button.tsx create mode 100644 frontend/src/components/security-lock.tsx create mode 100644 frontend/src/components/stop-button.tsx create mode 100644 frontend/src/components/submit-button.tsx create mode 100644 frontend/src/components/thumbnail.tsx create mode 100644 frontend/src/components/waitlist-message.tsx create mode 100644 frontend/src/ignore-task-state-map.constant.ts create mode 100644 frontend/src/utils/parse-cell-content.ts diff --git a/frontend/__tests__/components/browser.test.tsx b/frontend/__tests__/components/browser.test.tsx index 6d533adf1c3b..cb48f36208c6 100644 --- a/frontend/__tests__/components/browser.test.tsx +++ b/frontend/__tests__/components/browser.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { describe, it, expect } from "vitest"; import { renderWithProviders } from "../../test-utils"; -import BrowserPanel from "#/components/browser"; +import { BrowserPanel } from "#/components/browser"; describe("Browser", () => { it("renders a message if no screenshotSrc is provided", () => { diff --git a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx index a30594a1f046..8237133597c0 100644 --- a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx +++ b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { describe, afterEach, vi, it, expect } from "vitest"; -import ExplorerTree from "#/components/file-explorer/explorer-tree"; +import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; const FILES = ["file-1-1.ts", "folder-1-2"]; diff --git a/frontend/__tests__/components/terminal/terminal.test.tsx b/frontend/__tests__/components/terminal/terminal.test.tsx index d660f83639a0..5acc28e06c8b 100644 --- a/frontend/__tests__/components/terminal/terminal.test.tsx +++ b/frontend/__tests__/components/terminal/terminal.test.tsx @@ -2,7 +2,7 @@ import { act, screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { vi, describe, afterEach, it, expect } from "vitest"; import { Command, appendInput, appendOutput } from "#/state/command-slice"; -import Terminal from "#/components/terminal/terminal"; +import Terminal from "#/components/terminal"; global.ResizeObserver = vi.fn().mockImplementation(() => ({ observe: vi.fn(), diff --git a/frontend/src/components/action-button.tsx b/frontend/src/components/action-button.tsx new file mode 100644 index 000000000000..ae8f43f27f64 --- /dev/null +++ b/frontend/src/components/action-button.tsx @@ -0,0 +1,40 @@ +import { Tooltip } from "@nextui-org/react"; +import AgentState from "#/types/agent-state"; + +interface ActionButtonProps { + isDisabled?: boolean; + content: string; + action: AgentState; + handleAction: (action: AgentState) => void; + large?: boolean; +} + +export function ActionButton({ + isDisabled = false, + content, + action, + handleAction, + children, + large = false, +}: React.PropsWithChildren) { + return ( + + + + ); +} diff --git a/frontend/src/components/agent-control-bar.tsx b/frontend/src/components/agent-control-bar.tsx index a043f2a6a0a8..8713c9690e78 100644 --- a/frontend/src/components/agent-control-bar.tsx +++ b/frontend/src/components/agent-control-bar.tsx @@ -1,5 +1,3 @@ -import { Tooltip } from "@nextui-org/react"; -import React from "react"; import { useSelector } from "react-redux"; import PauseIcon from "#/assets/pause"; import PlayIcon from "#/assets/play"; @@ -7,76 +5,15 @@ import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; import { useWsClient } from "#/context/ws-client-provider"; +import { IGNORE_TASK_STATE_MAP } from "#/ignore-task-state-map.constant"; +import { ActionButton } from "./action-button"; -const IgnoreTaskStateMap: Record = { - [AgentState.PAUSED]: [ - AgentState.INIT, - AgentState.PAUSED, - AgentState.STOPPED, - AgentState.FINISHED, - AgentState.REJECTED, - AgentState.AWAITING_USER_INPUT, - AgentState.AWAITING_USER_CONFIRMATION, - ], - [AgentState.RUNNING]: [ - AgentState.INIT, - AgentState.RUNNING, - AgentState.STOPPED, - AgentState.FINISHED, - AgentState.REJECTED, - AgentState.AWAITING_USER_INPUT, - AgentState.AWAITING_USER_CONFIRMATION, - ], - [AgentState.STOPPED]: [AgentState.INIT, AgentState.STOPPED], - [AgentState.USER_CONFIRMED]: [AgentState.RUNNING], - [AgentState.USER_REJECTED]: [AgentState.RUNNING], - [AgentState.AWAITING_USER_CONFIRMATION]: [], -}; - -interface ActionButtonProps { - isDisabled?: boolean; - content: string; - action: AgentState; - handleAction: (action: AgentState) => void; - large?: boolean; -} - -function ActionButton({ - isDisabled = false, - content, - action, - handleAction, - children, - large = false, -}: React.PropsWithChildren) { - return ( - - - - ); -} - -function AgentControlBar() { +export function AgentControlBar() { const { send } = useWsClient(); const { curAgentState } = useSelector((state: RootState) => state.agent); const handleAction = (action: AgentState) => { - if (!IgnoreTaskStateMap[action].includes(curAgentState)) { + if (!IGNORE_TASK_STATE_MAP[action].includes(curAgentState)) { send(generateAgentStateChangeEvent(action)); } }; @@ -106,5 +43,3 @@ function AgentControlBar() {
); } - -export default AgentControlBar; diff --git a/frontend/src/components/agent-status-bar.tsx b/frontend/src/components/agent-status-bar.tsx index e2f12b5e63af..f0781abc4564 100644 --- a/frontend/src/components/agent-status-bar.tsx +++ b/frontend/src/components/agent-status-bar.tsx @@ -1,100 +1,19 @@ -import React, { useEffect } from "react"; +import React from "react"; import { useTranslation } from "react-i18next"; import { useSelector } from "react-redux"; import toast from "react-hot-toast"; -import { I18nKey } from "#/i18n/declaration"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; -import beep from "#/utils/beep"; +import { AGENT_STATUS_MAP } from "./agent-status-map.constant"; -enum IndicatorColor { - BLUE = "bg-blue-500", - GREEN = "bg-green-500", - ORANGE = "bg-orange-500", - YELLOW = "bg-yellow-500", - RED = "bg-red-500", - DARK_ORANGE = "bg-orange-800", -} - -function AgentStatusBar() { +export function AgentStatusBar() { const { t, i18n } = useTranslation(); const { curAgentState } = useSelector((state: RootState) => state.agent); const { curStatusMessage } = useSelector((state: RootState) => state.status); - const AgentStatusMap: { - [k: string]: { message: string; indicator: IndicatorColor }; - } = { - [AgentState.INIT]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_INIT_MESSAGE), - indicator: IndicatorColor.BLUE, - }, - [AgentState.RUNNING]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_RUNNING_MESSAGE), - indicator: IndicatorColor.GREEN, - }, - [AgentState.AWAITING_USER_INPUT]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE), - indicator: IndicatorColor.ORANGE, - }, - [AgentState.PAUSED]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_PAUSED_MESSAGE), - indicator: IndicatorColor.YELLOW, - }, - [AgentState.LOADING]: { - message: t(I18nKey.CHAT_INTERFACE$INITIALIZING_AGENT_LOADING_MESSAGE), - indicator: IndicatorColor.DARK_ORANGE, - }, - [AgentState.STOPPED]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_STOPPED_MESSAGE), - indicator: IndicatorColor.RED, - }, - [AgentState.FINISHED]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_FINISHED_MESSAGE), - indicator: IndicatorColor.GREEN, - }, - [AgentState.REJECTED]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_REJECTED_MESSAGE), - indicator: IndicatorColor.YELLOW, - }, - [AgentState.ERROR]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_ERROR_MESSAGE), - indicator: IndicatorColor.RED, - }, - [AgentState.AWAITING_USER_CONFIRMATION]: { - message: t( - I18nKey.CHAT_INTERFACE$AGENT_AWAITING_USER_CONFIRMATION_MESSAGE, - ), - indicator: IndicatorColor.ORANGE, - }, - [AgentState.USER_CONFIRMED]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_ACTION_USER_CONFIRMED_MESSAGE), - indicator: IndicatorColor.GREEN, - }, - [AgentState.USER_REJECTED]: { - message: t(I18nKey.CHAT_INTERFACE$AGENT_ACTION_USER_REJECTED_MESSAGE), - indicator: IndicatorColor.RED, - }, - }; - - // TODO: Extend the agent status, e.g.: - // - Agent is typing - // - Agent is initializing - // - Agent is thinking - // - Agent is ready - // - Agent is not available - useEffect(() => { - if ( - curAgentState === AgentState.AWAITING_USER_INPUT || - curAgentState === AgentState.ERROR || - curAgentState === AgentState.INIT - ) { - if (document.cookie.indexOf("audio") !== -1) beep(); - } - }, [curAgentState]); - const [statusMessage, setStatusMessage] = React.useState(""); - React.useEffect(() => { + const updateStatusMessage = () => { let message = curStatusMessage.message || ""; if (curStatusMessage?.id) { const id = curStatusMessage.id.trim(); @@ -109,24 +28,26 @@ function AgentStatusBar() { if (curAgentState === AgentState.LOADING && message.trim()) { setStatusMessage(message); } else { - setStatusMessage(AgentStatusMap[curAgentState].message); + setStatusMessage(AGENT_STATUS_MAP[curAgentState].message); } + }; + + React.useEffect(() => { + updateStatusMessage(); }, [curStatusMessage.id]); React.useEffect(() => { - setStatusMessage(AgentStatusMap[curAgentState].message); + setStatusMessage(AGENT_STATUS_MAP[curAgentState].message); }, [curAgentState]); return (
- {statusMessage} + {t(statusMessage)}
); } - -export default AgentStatusBar; diff --git a/frontend/src/components/agent-status-map.constant.ts b/frontend/src/components/agent-status-map.constant.ts new file mode 100644 index 000000000000..5de965a34196 --- /dev/null +++ b/frontend/src/components/agent-status-map.constant.ts @@ -0,0 +1,64 @@ +import { I18nKey } from "#/i18n/declaration"; +import AgentState from "#/types/agent-state"; + +enum IndicatorColor { + BLUE = "bg-blue-500", + GREEN = "bg-green-500", + ORANGE = "bg-orange-500", + YELLOW = "bg-yellow-500", + RED = "bg-red-500", + DARK_ORANGE = "bg-orange-800", +} + +export const AGENT_STATUS_MAP: { + [k: string]: { message: string; indicator: IndicatorColor }; +} = { + [AgentState.INIT]: { + message: I18nKey.CHAT_INTERFACE$AGENT_INIT_MESSAGE, + indicator: IndicatorColor.BLUE, + }, + [AgentState.RUNNING]: { + message: I18nKey.CHAT_INTERFACE$AGENT_RUNNING_MESSAGE, + indicator: IndicatorColor.GREEN, + }, + [AgentState.AWAITING_USER_INPUT]: { + message: I18nKey.CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE, + indicator: IndicatorColor.ORANGE, + }, + [AgentState.PAUSED]: { + message: I18nKey.CHAT_INTERFACE$AGENT_PAUSED_MESSAGE, + indicator: IndicatorColor.YELLOW, + }, + [AgentState.LOADING]: { + message: I18nKey.CHAT_INTERFACE$INITIALIZING_AGENT_LOADING_MESSAGE, + indicator: IndicatorColor.DARK_ORANGE, + }, + [AgentState.STOPPED]: { + message: I18nKey.CHAT_INTERFACE$AGENT_STOPPED_MESSAGE, + indicator: IndicatorColor.RED, + }, + [AgentState.FINISHED]: { + message: I18nKey.CHAT_INTERFACE$AGENT_FINISHED_MESSAGE, + indicator: IndicatorColor.GREEN, + }, + [AgentState.REJECTED]: { + message: I18nKey.CHAT_INTERFACE$AGENT_REJECTED_MESSAGE, + indicator: IndicatorColor.YELLOW, + }, + [AgentState.ERROR]: { + message: I18nKey.CHAT_INTERFACE$AGENT_ERROR_MESSAGE, + indicator: IndicatorColor.RED, + }, + [AgentState.AWAITING_USER_CONFIRMATION]: { + message: I18nKey.CHAT_INTERFACE$AGENT_AWAITING_USER_CONFIRMATION_MESSAGE, + indicator: IndicatorColor.ORANGE, + }, + [AgentState.USER_CONFIRMED]: { + message: I18nKey.CHAT_INTERFACE$AGENT_ACTION_USER_CONFIRMED_MESSAGE, + indicator: IndicatorColor.GREEN, + }, + [AgentState.USER_REJECTED]: { + message: I18nKey.CHAT_INTERFACE$AGENT_ACTION_USER_REJECTED_MESSAGE, + indicator: IndicatorColor.RED, + }, +}; diff --git a/frontend/src/components/analytics-consent-form-modal.tsx b/frontend/src/components/analytics-consent-form-modal.tsx index f40f85e47950..d24e4bc731a4 100644 --- a/frontend/src/components/analytics-consent-form-modal.tsx +++ b/frontend/src/components/analytics-consent-form-modal.tsx @@ -1,6 +1,6 @@ import { ModalBackdrop } from "./modals/modal-backdrop"; import ModalBody from "./modals/modal-body"; -import ModalButton from "./modal-button"; +import { ModalButton } from "./modal-button"; import { BaseModalTitle, BaseModalDescription, diff --git a/frontend/src/components/avatar.tsx b/frontend/src/components/avatar.tsx new file mode 100644 index 000000000000..394087c91052 --- /dev/null +++ b/frontend/src/components/avatar.tsx @@ -0,0 +1,9 @@ +interface AvatarProps { + src: string; +} + +export function Avatar({ src }: AvatarProps) { + return ( + user avatar + ); +} diff --git a/frontend/src/components/beta-badge.tsx b/frontend/src/components/beta-badge.tsx new file mode 100644 index 000000000000..e31903d138aa --- /dev/null +++ b/frontend/src/components/beta-badge.tsx @@ -0,0 +1,7 @@ +export function BetaBadge() { + return ( + + Beta + + ); +} diff --git a/frontend/src/components/browser-snapshot.tsx b/frontend/src/components/browser-snapshot.tsx new file mode 100644 index 000000000000..e5fa5e0cc501 --- /dev/null +++ b/frontend/src/components/browser-snapshot.tsx @@ -0,0 +1,14 @@ +interface BrowserSnaphsotProps { + src: string; +} + +export function BrowserSnapshot({ src }: BrowserSnaphsotProps) { + return ( + Browser Screenshot + ); +} diff --git a/frontend/src/components/browser.tsx b/frontend/src/components/browser.tsx index 6541ff98ff9f..00bf8e196562 100644 --- a/frontend/src/components/browser.tsx +++ b/frontend/src/components/browser.tsx @@ -1,12 +1,9 @@ -import { useTranslation } from "react-i18next"; -import { IoIosGlobe } from "react-icons/io"; import { useSelector } from "react-redux"; -import { I18nKey } from "#/i18n/declaration"; import { RootState } from "#/store"; +import { BrowserSnapshot } from "./browser-snapshot"; +import { EmptyBrowserMessage } from "./empty-browser-message"; -function BrowserPanel() { - const { t } = useTranslation(); - +export function BrowserPanel() { const { url, screenshotSrc } = useSelector( (state: RootState) => state.browser, ); @@ -23,21 +20,11 @@ function BrowserPanel() {
{screenshotSrc ? ( - Browser Screenshot + ) : ( -
- - {t(I18nKey.BROWSER$EMPTY_MESSAGE)} -
+ )}
); } - -export default BrowserPanel; diff --git a/frontend/src/components/chat-input.tsx b/frontend/src/components/chat-input.tsx index 96c27fc84d65..9c662f9300a9 100644 --- a/frontend/src/components/chat-input.tsx +++ b/frontend/src/components/chat-input.tsx @@ -1,7 +1,8 @@ import React from "react"; import TextareaAutosize from "react-textarea-autosize"; -import ArrowSendIcon from "#/icons/arrow-send.svg?react"; import { cn } from "#/utils/utils"; +import { SubmitButton } from "./submit-button"; +import { StopButton } from "./stop-button"; interface ChatInputProps { name?: string; @@ -132,27 +133,10 @@ export function ChatInput({ {showButton && (
{button === "submit" && ( - + )} {button === "stop" && ( - + )}
)} diff --git a/frontend/src/components/chat-message.tsx b/frontend/src/components/chat-message.tsx index 3f4502b40d3f..299acf1d76fc 100644 --- a/frontend/src/components/chat-message.tsx +++ b/frontend/src/components/chat-message.tsx @@ -1,11 +1,10 @@ import React from "react"; import Markdown from "react-markdown"; import remarkGfm from "remark-gfm"; -import CheckmarkIcon from "#/icons/checkmark.svg?react"; -import CopyIcon from "#/icons/copy.svg?react"; import { code } from "./markdown/code"; import { cn } from "#/utils/utils"; import { ul, ol } from "./markdown/list"; +import { CopyToClipboardButton } from "./copy-to-clipboard-button"; interface ChatMessageProps { type: "user" | "assistant"; @@ -51,23 +50,12 @@ export function ChatMessage({ type === "assistant" && "pb-4 max-w-full bg-tranparent", )} > - + mode={isCopy ? "copied" : "copy"} + /> - Beta - - ); -} +import { NavTab } from "./nav-tab"; interface ContainerProps { label?: string; @@ -38,23 +30,7 @@ export function Container({ {labels && (
{labels.map(({ label: l, to, icon, isBeta }) => ( - - clsx( - "px-2 border-b border-r border-neutral-600 bg-root-primary flex-1", - "first-of-type:rounded-tl-xl last-of-type:rounded-tr-xl last-of-type:border-r-0", - "flex items-center gap-2", - isActive && "bg-root-secondary", - ) - } - > - {icon} - {l} - {isBeta && } - + ))}
)} diff --git a/frontend/src/components/controls.tsx b/frontend/src/components/controls.tsx index 41ebc1328eac..424922b3a42c 100644 --- a/frontend/src/components/controls.tsx +++ b/frontend/src/components/controls.tsx @@ -1,11 +1,11 @@ -import { IoLockClosed } from "react-icons/io5"; import React from "react"; import { useSelector } from "react-redux"; -import AgentControlBar from "./agent-control-bar"; -import AgentStatusBar from "./agent-status-bar"; +import { AgentControlBar } from "./agent-control-bar"; +import { AgentStatusBar } from "./agent-status-bar"; import { ProjectMenuCard } from "./project-menu/ProjectMenuCard"; import { useAuth } from "#/context/auth-context"; import { RootState } from "#/store"; +import { SecurityLock } from "./security-lock"; interface ControlsProps { setSecurityOpen: (isOpen: boolean) => void; @@ -42,13 +42,7 @@ export function Controls({ {showSecurityLock && ( -
setSecurityOpen(true)} - > - -
+ setSecurityOpen(true)} /> )} diff --git a/frontend/src/components/copy-to-clipboard-button.tsx b/frontend/src/components/copy-to-clipboard-button.tsx new file mode 100644 index 000000000000..ba082f9de748 --- /dev/null +++ b/frontend/src/components/copy-to-clipboard-button.tsx @@ -0,0 +1,34 @@ +import { cn } from "#/utils/utils"; +import CheckmarkIcon from "#/icons/checkmark.svg?react"; +import CopyIcon from "#/icons/copy.svg?react"; + +interface CopyToClipboardButtonProps { + isHidden: boolean; + isDisabled: boolean; + onClick: () => void; + mode: "copy" | "copied"; +} + +export function CopyToClipboardButton({ + isHidden, + isDisabled, + onClick, + mode, +}: CopyToClipboardButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/editor-action-button.tsx b/frontend/src/components/editor-action-button.tsx new file mode 100644 index 000000000000..e5b29f0a6e73 --- /dev/null +++ b/frontend/src/components/editor-action-button.tsx @@ -0,0 +1,29 @@ +import { cn } from "#/utils/utils"; + +interface EditorActionButtonProps { + onClick: () => void; + disabled: boolean; + className: React.HTMLAttributes["className"]; +} + +export function EditorActionButton({ + onClick, + disabled, + className, + children, +}: React.PropsWithChildren) { + return ( + + ); +} diff --git a/frontend/src/components/editor-actions.tsx b/frontend/src/components/editor-actions.tsx index e66e9553e6f4..74414fa76ec6 100644 --- a/frontend/src/components/editor-actions.tsx +++ b/frontend/src/components/editor-actions.tsx @@ -1,33 +1,4 @@ -import { cn } from "@nextui-org/react"; -import { HTMLAttributes } from "react"; - -interface EditorActionButtonProps { - onClick: () => void; - disabled: boolean; - className: HTMLAttributes["className"]; -} - -function EditorActionButton({ - onClick, - disabled, - className, - children, -}: React.PropsWithChildren) { - return ( - - ); -} +import { EditorActionButton } from "./editor-action-button"; interface EditorActionsProps { onSave: () => void; diff --git a/frontend/src/components/empty-browser-message.tsx b/frontend/src/components/empty-browser-message.tsx new file mode 100644 index 000000000000..bf034bf2c171 --- /dev/null +++ b/frontend/src/components/empty-browser-message.tsx @@ -0,0 +1,14 @@ +import { useTranslation } from "react-i18next"; +import { IoIosGlobe } from "react-icons/io"; +import { I18nKey } from "#/i18n/declaration"; + +export function EmptyBrowserMessage() { + const { t } = useTranslation(); + + return ( +
+ + {t(I18nKey.BROWSER$EMPTY_MESSAGE)} +
+ ); +} diff --git a/frontend/src/components/extension-icon-map.constant.tsx b/frontend/src/components/extension-icon-map.constant.tsx new file mode 100644 index 000000000000..990a3061bd1c --- /dev/null +++ b/frontend/src/components/extension-icon-map.constant.tsx @@ -0,0 +1,20 @@ +import { DiJavascript } from "react-icons/di"; +import { + FaCss3, + FaHtml5, + FaList, + FaMarkdown, + FaNpm, + FaPython, +} from "react-icons/fa"; + +export const EXTENSION_ICON_MAP: Record = { + js: , + ts: , + py: , + css: , + json: , + npmignore: , + html: , + md: , +}; diff --git a/frontend/src/components/feedback-action-button.tsx b/frontend/src/components/feedback-action-button.tsx new file mode 100644 index 000000000000..1cd4f8f5c133 --- /dev/null +++ b/frontend/src/components/feedback-action-button.tsx @@ -0,0 +1,22 @@ +interface FeedbackActionButtonProps { + testId?: string; + onClick: () => void; + icon: React.ReactNode; +} + +export function FeedbackActionButton({ + testId, + onClick, + icon, +}: FeedbackActionButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/feedback-actions.tsx b/frontend/src/components/feedback-actions.tsx index 05a503f0bdfd..00226914e58d 100644 --- a/frontend/src/components/feedback-actions.tsx +++ b/frontend/src/components/feedback-actions.tsx @@ -1,28 +1,6 @@ import ThumbsUpIcon from "#/icons/thumbs-up.svg?react"; import ThumbDownIcon from "#/icons/thumbs-down.svg?react"; - -interface FeedbackActionButtonProps { - testId?: string; - onClick: () => void; - icon: React.ReactNode; -} - -function FeedbackActionButton({ - testId, - onClick, - icon, -}: FeedbackActionButtonProps) { - return ( - - ); -} +import { FeedbackActionButton } from "./feedback-action-button"; interface FeedbackActionsProps { onPositiveFeedback: () => void; diff --git a/frontend/src/components/feedback-form.tsx b/frontend/src/components/feedback-form.tsx index ddeb52335580..9cb622d152c0 100644 --- a/frontend/src/components/feedback-form.tsx +++ b/frontend/src/components/feedback-form.tsx @@ -1,6 +1,6 @@ import React from "react"; import hotToast from "react-hot-toast"; -import ModalButton from "./modal-button"; +import { ModalButton } from "./modal-button"; import { Feedback } from "#/api/open-hands.types"; import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback"; diff --git a/frontend/src/components/file-explorer/tree-node.tsx b/frontend/src/components/file-explorer/tree-node.tsx index 07012f2a2c18..bd390f67bb68 100644 --- a/frontend/src/components/file-explorer/tree-node.tsx +++ b/frontend/src/components/file-explorer/tree-node.tsx @@ -1,6 +1,6 @@ import React from "react"; -import FolderIcon from "../folder-icon"; -import FileIcon from "../file-icons"; +import { FolderIcon } from "../folder-icon"; +import { FileIcon } from "../file-icons"; import { useFiles } from "#/context/files"; import { cn } from "#/utils/utils"; import { useListFiles } from "#/hooks/query/use-list-files"; diff --git a/frontend/src/components/file-icons.tsx b/frontend/src/components/file-icons.tsx index 45da4eff0b92..643ac0405ca3 100644 --- a/frontend/src/components/file-icons.tsx +++ b/frontend/src/components/file-icons.tsx @@ -1,33 +1,12 @@ -import { DiJavascript } from "react-icons/di"; -import { - FaCss3, - FaFile, - FaHtml5, - FaList, - FaMarkdown, - FaNpm, - FaPython, -} from "react-icons/fa"; +import { FaFile } from "react-icons/fa"; import { getExtension } from "#/utils/utils"; - -const EXTENSION_ICON_MAP: Record = { - js: , - ts: , - py: , - css: , - json: , - npmignore: , - html: , - md: , -}; +import { EXTENSION_ICON_MAP } from "./extension-icon-map.constant"; interface FileIconProps { filename: string; } -function FileIcon({ filename }: FileIconProps) { +export function FileIcon({ filename }: FileIconProps) { const extension = getExtension(filename); return EXTENSION_ICON_MAP[extension] || ; } - -export default FileIcon; diff --git a/frontend/src/components/folder-icon.tsx b/frontend/src/components/folder-icon.tsx index 3491363ba6ed..e08597c21d19 100644 --- a/frontend/src/components/folder-icon.tsx +++ b/frontend/src/components/folder-icon.tsx @@ -4,12 +4,10 @@ interface FolderIconProps { isOpen: boolean; } -function FolderIcon({ isOpen }: FolderIconProps): JSX.Element { +export function FolderIcon({ isOpen }: FolderIconProps): JSX.Element { return isOpen ? ( ) : ( ); } - -export default FolderIcon; diff --git a/frontend/src/components/github-repositories-suggestion-box.tsx b/frontend/src/components/github-repositories-suggestion-box.tsx index c74954899684..66898c7889b4 100644 --- a/frontend/src/components/github-repositories-suggestion-box.tsx +++ b/frontend/src/components/github-repositories-suggestion-box.tsx @@ -4,7 +4,7 @@ import { SuggestionBox } from "#/routes/_oh._index/suggestion-box"; import { ConnectToGitHubModal } from "./modals/connect-to-github-modal"; import { ModalBackdrop } from "./modals/modal-backdrop"; import { GitHubRepositorySelector } from "#/routes/_oh._index/github-repo-selector"; -import ModalButton from "./modal-button"; +import { ModalButton } from "./modal-button"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; interface GitHubRepositoriesSuggestionBoxProps { diff --git a/frontend/src/components/icon-button.tsx b/frontend/src/components/icon-button.tsx index ad19a4f35ca6..66c86e2a58e3 100644 --- a/frontend/src/components/icon-button.tsx +++ b/frontend/src/components/icon-button.tsx @@ -8,7 +8,7 @@ export interface IconButtonProps { testId?: string; } -function IconButton({ +export function IconButton({ icon, onClick, ariaLabel, @@ -27,5 +27,3 @@ function IconButton({ ); } - -export default IconButton; diff --git a/frontend/src/components/image-preview.tsx b/frontend/src/components/image-preview.tsx index a8be0b24d624..dc83fc19ac3d 100644 --- a/frontend/src/components/image-preview.tsx +++ b/frontend/src/components/image-preview.tsx @@ -1,5 +1,5 @@ -import CloseIcon from "#/icons/close.svg?react"; -import { cn } from "#/utils/utils"; +import { RemoveButton } from "./remove-button"; +import { Thumbnail } from "./thumbnail"; interface ImagePreviewProps { src: string; @@ -14,28 +14,8 @@ export function ImagePreview({ }: ImagePreviewProps) { return (
- - {onRemove && ( - - )} + + {onRemove && }
); } diff --git a/frontend/src/components/join-waitlist-anchor.tsx b/frontend/src/components/join-waitlist-anchor.tsx new file mode 100644 index 000000000000..b1ca5e0223c3 --- /dev/null +++ b/frontend/src/components/join-waitlist-anchor.tsx @@ -0,0 +1,12 @@ +export function JoinWaitlistAnchor() { + return ( + + Join Waitlist + + ); +} diff --git a/frontend/src/components/jupyter-cell-input.tsx b/frontend/src/components/jupyter-cell-input.tsx new file mode 100644 index 000000000000..c69651d105d8 --- /dev/null +++ b/frontend/src/components/jupyter-cell-input.tsx @@ -0,0 +1,22 @@ +import SyntaxHighlighter from "react-syntax-highlighter"; +import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs"; + +interface JupytrerCellInputProps { + code: string; +} + +export function JupytrerCellInput({ code }: JupytrerCellInputProps) { + return ( +
+
EXECUTE
+
+        
+          {code}
+        
+      
+
+ ); +} diff --git a/frontend/src/components/jupyter-cell-output.tsx b/frontend/src/components/jupyter-cell-output.tsx new file mode 100644 index 000000000000..e1d80e68e94b --- /dev/null +++ b/frontend/src/components/jupyter-cell-output.tsx @@ -0,0 +1,40 @@ +import Markdown from "react-markdown"; +import SyntaxHighlighter from "react-syntax-highlighter"; +import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs"; +import { JupyterLine } from "#/utils/parse-cell-content"; + +interface JupyterCellOutputProps { + lines: JupyterLine[]; +} + +export function JupyterCellOutput({ lines }: JupyterCellOutputProps) { + return ( +
+
STDOUT/STDERR
+
+        {/* display the lines as plaintext or image */}
+        {lines.map((line, index) => {
+          if (line.type === "image") {
+            return (
+              
+ value}> + {line.content} + +
+ ); + } + return ( +
+ + {line.content} + +
+ ); + })} +
+
+ ); +} diff --git a/frontend/src/components/jupyter-cell.tsx b/frontend/src/components/jupyter-cell.tsx new file mode 100644 index 000000000000..a6a99837f1b7 --- /dev/null +++ b/frontend/src/components/jupyter-cell.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import { Cell } from "#/state/jupyter-slice"; +import { JupyterLine, parseCellContent } from "#/utils/parse-cell-content"; +import { JupytrerCellInput } from "./jupyter-cell-input"; +import { JupyterCellOutput } from "./jupyter-cell-output"; + +interface JupyterCellProps { + cell: Cell; +} + +export function JupyterCell({ cell }: JupyterCellProps) { + const [lines, setLines] = React.useState([]); + + React.useEffect(() => { + setLines(parseCellContent(cell.content)); + }, [cell.content]); + + if (cell.type === "input") { + return ; + } + + return ; +} diff --git a/frontend/src/components/jupyter-scroll-to-bottom-button.tsx b/frontend/src/components/jupyter-scroll-to-bottom-button.tsx new file mode 100644 index 000000000000..036cf5270b5d --- /dev/null +++ b/frontend/src/components/jupyter-scroll-to-bottom-button.tsx @@ -0,0 +1,26 @@ +import { useTranslation } from "react-i18next"; +import { VscArrowDown } from "react-icons/vsc"; +import { I18nKey } from "#/i18n/declaration"; + +interface ScrollToBottomButtonProps { + onClick: () => void; +} + +export function ScrollToBottomButton({ onClick }: ScrollToBottomButtonProps) { + const { t } = useTranslation(); + + return ( + + ); +} diff --git a/frontend/src/components/jupyter.tsx b/frontend/src/components/jupyter.tsx index 5e6915b89e91..24bb54ace28d 100644 --- a/frontend/src/components/jupyter.tsx +++ b/frontend/src/components/jupyter.tsx @@ -1,94 +1,15 @@ import React from "react"; import { useSelector } from "react-redux"; -import SyntaxHighlighter from "react-syntax-highlighter"; -import Markdown from "react-markdown"; -import { VscArrowDown } from "react-icons/vsc"; -import { useTranslation } from "react-i18next"; -import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs"; import { RootState } from "#/store"; -import { Cell } from "#/state/jupyter-slice"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; -import { I18nKey } from "#/i18n/declaration"; - -interface IJupyterCell { - cell: Cell; -} - -function JupyterCell({ cell }: IJupyterCell): JSX.Element { - const code = cell.content; - - if (cell.type === "input") { - return ( -
-
EXECUTE
-
-          
-            {code}
-          
-        
-
- ); - } - - // aggregate all the NON-image lines into a single plaintext. - const lines: { type: "plaintext" | "image"; content: string }[] = []; - let current = ""; - for (const line of code.split("\n")) { - if (line.startsWith("![image](data:image/png;base64,")) { - lines.push({ type: "plaintext", content: current }); - lines.push({ type: "image", content: line }); - current = ""; - } else { - current += `${line}\n`; - } - } - lines.push({ type: "plaintext", content: current }); - - return ( -
-
STDOUT/STDERR
-
-        {/* display the lines as plaintext or image */}
-        {lines.map((line, index) => {
-          if (line.type === "image") {
-            return (
-              
- value}> - {line.content} - -
- ); - } - return ( -
- - {line.content} - -
- ); - })} -
-
- ); -} +import { JupyterCell } from "./jupyter-cell"; +import { ScrollToBottomButton } from "./jupyter-scroll-to-bottom-button"; interface JupyterEditorProps { maxWidth: number; } -function JupyterEditor({ maxWidth }: JupyterEditorProps) { - const { t } = useTranslation(); - +export function JupyterEditor({ maxWidth }: JupyterEditorProps) { const { cells } = useSelector((state: RootState) => state.jupyter); const jupyterRef = React.useRef(null); @@ -108,21 +29,9 @@ function JupyterEditor({ maxWidth }: JupyterEditorProps) { {!hitBottom && (
- +
)} ); } - -export default JupyterEditor; diff --git a/frontend/src/components/modal-button.tsx b/frontend/src/components/modal-button.tsx index e011fef76075..706e7a481b7f 100644 --- a/frontend/src/components/modal-button.tsx +++ b/frontend/src/components/modal-button.tsx @@ -13,7 +13,7 @@ interface ModalButtonProps { intent?: string; } -function ModalButton({ +export function ModalButton({ testId, variant = "default", onClick, @@ -45,5 +45,3 @@ function ModalButton({ ); } - -export default ModalButton; diff --git a/frontend/src/components/modals/account-settings-form.tsx b/frontend/src/components/modals/account-settings-form.tsx index 41482843821b..3618544f43a9 100644 --- a/frontend/src/components/modals/account-settings-form.tsx +++ b/frontend/src/components/modals/account-settings-form.tsx @@ -5,7 +5,7 @@ import { BaseModalTitle, } from "./confirmation-modals/base-modal"; import ModalBody from "./modal-body"; -import ModalButton from "../modal-button"; +import { ModalButton } from "../modal-button"; import { FormFieldset } from "../form-fieldset"; import { CustomInput } from "../custom-input"; import { AvailableLanguages } from "#/i18n"; diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/modals/confirmation-modals/base-modal.tsx index b97db46d81c6..d46f73dbf4c0 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/base-modal.tsx @@ -1,5 +1,5 @@ import React from "react"; -import ModalButton from "#/components/modal-button"; +import { ModalButton } from "#/components/modal-button"; import ModalBody from "../modal-body"; interface ButtonConfig { diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/modals/connect-to-github-modal.tsx index 57468cd1cafd..07eeff20f4da 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/modals/connect-to-github-modal.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import ModalBody from "./modal-body"; import { CustomInput } from "../custom-input"; -import ModalButton from "../modal-button"; +import { ModalButton } from "../modal-button"; import { BaseModalDescription, BaseModalTitle, diff --git a/frontend/src/components/nav-tab.tsx b/frontend/src/components/nav-tab.tsx new file mode 100644 index 000000000000..2f8657a8f667 --- /dev/null +++ b/frontend/src/components/nav-tab.tsx @@ -0,0 +1,32 @@ +import { NavLink } from "react-router-dom"; +import { cn } from "#/utils/utils"; +import { BetaBadge } from "./beta-badge"; + +interface NavTabProps { + to: string; + label: string; + icon: React.ReactNode; + isBeta?: boolean; +} + +export function NavTab({ to, label, icon, isBeta }: NavTabProps) { + return ( + + cn( + "px-2 border-b border-r border-neutral-600 bg-root-primary flex-1", + "first-of-type:rounded-tl-xl last-of-type:rounded-tr-xl last-of-type:border-r-0", + "flex items-center gap-2", + isActive && "bg-root-secondary", + ) + } + > + {icon} + {label} + {isBeta && } + + ); +} diff --git a/frontend/src/components/refresh-button.tsx b/frontend/src/components/refresh-button.tsx new file mode 100644 index 000000000000..4fe67a0489ff --- /dev/null +++ b/frontend/src/components/refresh-button.tsx @@ -0,0 +1,13 @@ +import Refresh from "#/icons/refresh.svg?react"; + +interface RefreshButtonProps { + onClick: (event: React.MouseEvent) => void; +} + +export function RefreshButton({ onClick }: RefreshButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/remove-button.tsx b/frontend/src/components/remove-button.tsx new file mode 100644 index 000000000000..afcf2ffc8c32 --- /dev/null +++ b/frontend/src/components/remove-button.tsx @@ -0,0 +1,21 @@ +import { cn } from "#/utils/utils"; +import CloseIcon from "#/icons/close.svg?react"; + +interface RemoveButtonProps { + onClick: () => void; +} + +export function RemoveButton({ onClick }: RemoveButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/security-lock.tsx b/frontend/src/components/security-lock.tsx new file mode 100644 index 000000000000..3fe4c8010abe --- /dev/null +++ b/frontend/src/components/security-lock.tsx @@ -0,0 +1,17 @@ +import { IoLockClosed } from "react-icons/io5"; + +interface SecurityLockProps { + onClick: () => void; +} + +export function SecurityLock({ onClick }: SecurityLockProps) { + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/settings-form.tsx b/frontend/src/components/settings-form.tsx index 2d23137fc740..13f7d7f11430 100644 --- a/frontend/src/components/settings-form.tsx +++ b/frontend/src/components/settings-form.tsx @@ -7,7 +7,7 @@ import { ModelSelector } from "#/components/modals/settings/model-selector"; import { getDefaultSettings, Settings } from "#/services/settings"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { extractModelAndProvider } from "#/utils/extract-model-and-provider"; -import ModalButton from "./modal-button"; +import { ModalButton } from "./modal-button"; import { DangerModal } from "./modals/confirmation-modals/danger-modal"; import { I18nKey } from "#/i18n/declaration"; import { diff --git a/frontend/src/components/stop-button.tsx b/frontend/src/components/stop-button.tsx new file mode 100644 index 000000000000..dbb99ebd100f --- /dev/null +++ b/frontend/src/components/stop-button.tsx @@ -0,0 +1,19 @@ +interface StopButtonProps { + isDisabled?: boolean; + onClick?: () => void; +} + +export function StopButton({ isDisabled, onClick }: StopButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/submit-button.tsx b/frontend/src/components/submit-button.tsx new file mode 100644 index 000000000000..b65fa25775dd --- /dev/null +++ b/frontend/src/components/submit-button.tsx @@ -0,0 +1,20 @@ +import ArrowSendIcon from "#/icons/arrow-send.svg?react"; + +interface SubmitButtonProps { + isDisabled?: boolean; + onClick: () => void; +} + +export function SubmitButton({ isDisabled, onClick }: SubmitButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/suggestion-bubble.tsx b/frontend/src/components/suggestion-bubble.tsx index 00fc1b7d0d6b..8a227819ee67 100644 --- a/frontend/src/components/suggestion-bubble.tsx +++ b/frontend/src/components/suggestion-bubble.tsx @@ -1,5 +1,5 @@ import Lightbulb from "#/icons/lightbulb.svg?react"; -import Refresh from "#/icons/refresh.svg?react"; +import { RefreshButton } from "./refresh-button"; interface SuggestionBubbleProps { suggestion: string; @@ -12,6 +12,11 @@ export function SuggestionBubble({ onClick, onRefresh, }: SuggestionBubbleProps) { + const handleRefresh = (e: React.MouseEvent) => { + e.stopPropagation(); + onRefresh(); + }; + return (
{suggestion}
- + ); } diff --git a/frontend/src/components/terminal.tsx b/frontend/src/components/terminal.tsx index dac0dc73d8b6..bd8283b8903b 100644 --- a/frontend/src/components/terminal.tsx +++ b/frontend/src/components/terminal.tsx @@ -1,6 +1,6 @@ import { useSelector } from "react-redux"; import { RootState } from "#/store"; -import { useTerminal } from "../../hooks/use-terminal"; +import { useTerminal } from "#/hooks/use-terminal"; import "@xterm/xterm/css/xterm.css"; diff --git a/frontend/src/components/thumbnail.tsx b/frontend/src/components/thumbnail.tsx new file mode 100644 index 000000000000..5dc0818c2873 --- /dev/null +++ b/frontend/src/components/thumbnail.tsx @@ -0,0 +1,21 @@ +import { cn } from "#/utils/utils"; + +interface ThumbnailProps { + src: string; + size?: "small" | "large"; +} + +export function Thumbnail({ src, size = "small" }: ThumbnailProps) { + return ( + + ); +} diff --git a/frontend/src/components/user-avatar.tsx b/frontend/src/components/user-avatar.tsx index 17433cde463e..16dbd4206f82 100644 --- a/frontend/src/components/user-avatar.tsx +++ b/frontend/src/components/user-avatar.tsx @@ -1,6 +1,7 @@ import { LoadingSpinner } from "./modals/loading-project"; import DefaultUserAvatar from "#/icons/default-user.svg?react"; import { cn } from "#/utils/utils"; +import { Avatar } from "./avatar"; interface UserAvatarProps { onClick: () => void; @@ -19,13 +20,7 @@ export function UserAvatar({ onClick, avatarUrl, isLoading }: UserAvatarProps) { isLoading && "bg-transparent", )} > - {!isLoading && avatarUrl && ( - user avatar - )} + {!isLoading && avatarUrl && } {!isLoading && !avatarUrl && ( +

+ {content === "sign-in" && "Sign in with GitHub"} + {content === "waitlist" && "Just a little longer!"} +

+ {content === "sign-in" && ( +

+ or{" "} + + join the waitlist + {" "} + if you haven't already +

+ )} + {content === "waitlist" && ( +

+ Thanks for your patience! We're accepting new members + progressively. If you haven't joined the waitlist yet, now's + the time! +

+ )} + + ); +} diff --git a/frontend/src/components/waitlist-modal.tsx b/frontend/src/components/waitlist-modal.tsx index 736bc41459db..596961dd2529 100644 --- a/frontend/src/components/waitlist-modal.tsx +++ b/frontend/src/components/waitlist-modal.tsx @@ -1,8 +1,10 @@ -import ModalButton from "./modal-button"; +import { ModalButton } from "./modal-button"; import { ModalBackdrop } from "./modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; import ModalBody from "./modals/modal-body"; +import { JoinWaitlistAnchor } from "./join-waitlist-anchor"; +import { WaitlistMessage } from "./waitlist-message"; interface WaitlistModalProps { ghToken: string | null; @@ -14,32 +16,7 @@ export function WaitlistModal({ ghToken, githubAuthUrl }: WaitlistModalProps) { -
-

- {ghToken ? "Just a little longer!" : "Sign in with GitHub"} -

- {!ghToken && ( -

- or{" "} - - join the waitlist - {" "} - if you haven't already -

- )} - {ghToken && ( -

- Thanks for your patience! We're accepting new members - progressively. If you haven't joined the waitlist yet, - now's the time! -

- )} -
+ {!ghToken && ( )} - {ghToken && ( - - Join Waitlist - - )} + {ghToken && }
); diff --git a/frontend/src/ignore-task-state-map.constant.ts b/frontend/src/ignore-task-state-map.constant.ts new file mode 100644 index 000000000000..2fc50e7d5495 --- /dev/null +++ b/frontend/src/ignore-task-state-map.constant.ts @@ -0,0 +1,26 @@ +import AgentState from "./types/agent-state"; + +export const IGNORE_TASK_STATE_MAP: Record = { + [AgentState.PAUSED]: [ + AgentState.INIT, + AgentState.PAUSED, + AgentState.STOPPED, + AgentState.FINISHED, + AgentState.REJECTED, + AgentState.AWAITING_USER_INPUT, + AgentState.AWAITING_USER_CONFIRMATION, + ], + [AgentState.RUNNING]: [ + AgentState.INIT, + AgentState.RUNNING, + AgentState.STOPPED, + AgentState.FINISHED, + AgentState.REJECTED, + AgentState.AWAITING_USER_INPUT, + AgentState.AWAITING_USER_CONFIRMATION, + ], + [AgentState.STOPPED]: [AgentState.INIT, AgentState.STOPPED], + [AgentState.USER_CONFIRMED]: [AgentState.RUNNING], + [AgentState.USER_REJECTED]: [AgentState.RUNNING], + [AgentState.AWAITING_USER_CONFIRMATION]: [], +}; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx b/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx index d21ab4160b35..ed2035bfeba7 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosRefresh } from "react-icons/io"; -import IconButton from "#/components/icon-button"; +import { IconButton } from "#/components/icon-button"; interface RefreshIconButtonProps { onClick: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx b/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx index 5d42eeba0495..bf91586c8a47 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosArrowForward, IoIosArrowBack } from "react-icons/io"; -import IconButton from "#/components/icon-button"; +import { IconButton } from "#/components/icon-button"; interface ToggleWorkspaceIconButtonProps { onClick: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx b/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx index b10ede48d806..80c256057f66 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosCloudUpload } from "react-icons/io"; -import IconButton from "#/components/icon-button"; +import { IconButton } from "#/components/icon-button"; interface UploadIconButtonProps { onClick: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx b/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx index a7979cacd381..faf420678171 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; import AgentState from "#/types/agent-state"; -import ExplorerTree from "../../../components/file-explorer/explorer-tree"; +import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; import toast from "#/utils/toast"; import { RootState } from "#/store"; import { I18nKey } from "#/i18n/declaration"; diff --git a/frontend/src/routes/_oh.app.browser.tsx b/frontend/src/routes/_oh.app.browser.tsx index 4b4908506805..54c867e536fb 100644 --- a/frontend/src/routes/_oh.app.browser.tsx +++ b/frontend/src/routes/_oh.app.browser.tsx @@ -1,4 +1,4 @@ -import BrowserPanel from "#/components/browser"; +import { BrowserPanel } from "#/components/browser"; function Browser() { return ; diff --git a/frontend/src/routes/_oh.app.jupyter.tsx b/frontend/src/routes/_oh.app.jupyter.tsx index 71de5941366a..55f9cba62832 100644 --- a/frontend/src/routes/_oh.app.jupyter.tsx +++ b/frontend/src/routes/_oh.app.jupyter.tsx @@ -1,5 +1,5 @@ import React from "react"; -import JupyterEditor from "#/components/jupyter"; +import { JupyterEditor } from "#/components/jupyter"; function Jupyter() { const parentRef = React.useRef(null); diff --git a/frontend/src/routes/_oh.app/chat-interface.tsx b/frontend/src/routes/_oh.app/chat-interface.tsx index 8b413c550fdd..b671e2bf04e6 100644 --- a/frontend/src/routes/_oh.app/chat-interface.tsx +++ b/frontend/src/routes/_oh.app/chat-interface.tsx @@ -11,7 +11,7 @@ import AgentState from "#/types/agent-state"; import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { FeedbackModal } from "../../components/feedback-modal"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; -import TypingIndicator from "../../components/chat/typing-indicator"; +import { TypingIndicator } from "../../components/typing-indicator"; import { ContinueButton } from "../../components/continue-button"; import { ScrollToBottomButton } from "../../components/scroll-to-bottom-button"; import { useWsClient } from "#/context/ws-client-provider"; diff --git a/frontend/src/routes/_oh.app/messages.tsx b/frontend/src/routes/_oh.app/messages.tsx index 3766aac33103..aedab0a56606 100644 --- a/frontend/src/routes/_oh.app/messages.tsx +++ b/frontend/src/routes/_oh.app/messages.tsx @@ -1,5 +1,5 @@ import { ChatMessage } from "#/components/chat-message"; -import ConfirmationButtons from "#/components/chat/confirmation-buttons"; +import { ConfirmationButtons } from "#/components/confirmation-buttons"; import { ErrorMessage } from "#/components/error-message"; import { ImageCarousel } from "#/components/image-carousel"; diff --git a/frontend/src/routes/_oh.app/route.tsx b/frontend/src/routes/_oh.app/route.tsx index 5a0fc655e9c9..7a0458aad3ae 100644 --- a/frontend/src/routes/_oh.app/route.tsx +++ b/frontend/src/routes/_oh.app/route.tsx @@ -43,7 +43,7 @@ function App() { ); const Terminal = React.useMemo( - () => React.lazy(() => import("#/components/terminal/terminal")), + () => React.lazy(() => import("#/components/terminal")), [], ); diff --git a/frontend/src/routes/_oh/modals/settings-modal.tsx b/frontend/src/routes/_oh/modals/settings-modal.tsx index d09b73a33eb1..7b3917c8324d 100644 --- a/frontend/src/routes/_oh/modals/settings-modal.tsx +++ b/frontend/src/routes/_oh/modals/settings-modal.tsx @@ -1,4 +1,4 @@ -import { SettingsForm } from "#/components/form/settings-form"; +import { SettingsForm } from "#/components/settings-form"; import { LoadingSpinner } from "#/components/modals/loading-project"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { useUserPrefs } from "#/context/user-prefs-context"; diff --git a/frontend/src/utils/parse-cell-content.ts b/frontend/src/utils/parse-cell-content.ts new file mode 100644 index 000000000000..98cd1e4b6086 --- /dev/null +++ b/frontend/src/utils/parse-cell-content.ts @@ -0,0 +1,24 @@ +export type JupyterLine = { type: "plaintext" | "image"; content: string }; + +export const parseCellContent = (content: string) => { + const lines: JupyterLine[] = []; + let currentText = ""; + + for (const line of content.split("\n")) { + if (line.startsWith("![image](data:image/png;base64,")) { + if (currentText) { + lines.push({ type: "plaintext", content: currentText }); + currentText = ""; // Reset after pushing plaintext + } + lines.push({ type: "image", content: line }); + } else { + currentText += `${line}\n`; + } + } + + if (currentText) { + lines.push({ type: "plaintext", content: currentText }); + } + + return lines; +}; From 4af4c1caee50d18230ca1bd69acf51f0f12888ad Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:04:56 +0400 Subject: [PATCH 03/13] Move components --- .../file-explorer/explorer-tree.test.tsx | 2 +- .../file-explorer/tree-node.test.tsx | 2 +- .../{file-explorer => }/explorer-tree.tsx | 0 frontend/src/components/title.tsx | 24 +++++++++++++++++ .../{file-explorer => }/tree-node.tsx | 26 ++----------------- .../file-explorer/file-explorer.tsx | 2 +- 6 files changed, 29 insertions(+), 27 deletions(-) rename frontend/src/components/{file-explorer => }/explorer-tree.tsx (100%) create mode 100644 frontend/src/components/title.tsx rename frontend/src/components/{file-explorer => }/tree-node.tsx (74%) diff --git a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx index 8237133597c0..126ec197097b 100644 --- a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx +++ b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { describe, afterEach, vi, it, expect } from "vitest"; -import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; +import { ExplorerTree } from "#/components/explorer-tree"; const FILES = ["file-1-1.ts", "folder-1-2"]; diff --git a/frontend/__tests__/components/file-explorer/tree-node.test.tsx b/frontend/__tests__/components/file-explorer/tree-node.test.tsx index ebd8c029d433..5ded4e798962 100644 --- a/frontend/__tests__/components/file-explorer/tree-node.test.tsx +++ b/frontend/__tests__/components/file-explorer/tree-node.test.tsx @@ -2,7 +2,7 @@ import { screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { renderWithProviders } from "test-utils"; import { vi, describe, afterEach, it, expect } from "vitest"; -import TreeNode from "#/components/file-explorer/tree-node"; +import TreeNode from "#/components/tree-node"; import OpenHands from "#/api/open-hands"; const getFileSpy = vi.spyOn(OpenHands, "getFile"); diff --git a/frontend/src/components/file-explorer/explorer-tree.tsx b/frontend/src/components/explorer-tree.tsx similarity index 100% rename from frontend/src/components/file-explorer/explorer-tree.tsx rename to frontend/src/components/explorer-tree.tsx diff --git a/frontend/src/components/title.tsx b/frontend/src/components/title.tsx new file mode 100644 index 000000000000..e0971f878115 --- /dev/null +++ b/frontend/src/components/title.tsx @@ -0,0 +1,24 @@ +import { FolderIcon } from "./folder-icon"; +import { FileIcon } from "./file-icons"; + +interface TitleProps { + name: string; + type: "folder" | "file"; + isOpen: boolean; + onClick: () => void; +} + +export function Title({ name, type, isOpen, onClick }: TitleProps) { + return ( +
+
+ {type === "folder" && } + {type === "file" && } +
+
{name}
+
+ ); +} diff --git a/frontend/src/components/file-explorer/tree-node.tsx b/frontend/src/components/tree-node.tsx similarity index 74% rename from frontend/src/components/file-explorer/tree-node.tsx rename to frontend/src/components/tree-node.tsx index bd390f67bb68..2ec0f6495864 100644 --- a/frontend/src/components/file-explorer/tree-node.tsx +++ b/frontend/src/components/tree-node.tsx @@ -1,32 +1,10 @@ import React from "react"; -import { FolderIcon } from "../folder-icon"; -import { FileIcon } from "../file-icons"; + import { useFiles } from "#/context/files"; import { cn } from "#/utils/utils"; import { useListFiles } from "#/hooks/query/use-list-files"; import { useListFile } from "#/hooks/query/use-list-file"; - -interface TitleProps { - name: string; - type: "folder" | "file"; - isOpen: boolean; - onClick: () => void; -} - -function Title({ name, type, isOpen, onClick }: TitleProps) { - return ( -
-
- {type === "folder" && } - {type === "file" && } -
-
{name}
-
- ); -} +import { Title } from "./title"; interface TreeNodeProps { path: string; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx b/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx index faf420678171..cb6354fbe10a 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; import AgentState from "#/types/agent-state"; -import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; +import { ExplorerTree } from "#/components/explorer-tree"; import toast from "#/utils/toast"; import { RootState } from "#/store"; import { I18nKey } from "#/i18n/declaration"; From 8cd16d262bcce506517b8e0d1f1093d05ae38124 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:07:01 +0400 Subject: [PATCH 04/13] Convert default export to named export --- frontend/src/components/analytics-consent-form-modal.tsx | 2 +- frontend/src/components/feedback-modal.tsx | 2 +- frontend/src/components/modals/account-settings-form.tsx | 2 +- .../src/components/modals/confirmation-modals/base-modal.tsx | 2 +- frontend/src/components/modals/connect-to-github-modal.tsx | 2 +- frontend/src/components/modals/loading-project.tsx | 2 +- frontend/src/components/modals/modal-body.tsx | 4 +--- frontend/src/components/waitlist-modal.tsx | 2 +- 8 files changed, 8 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/analytics-consent-form-modal.tsx b/frontend/src/components/analytics-consent-form-modal.tsx index d24e4bc731a4..9fce2998c522 100644 --- a/frontend/src/components/analytics-consent-form-modal.tsx +++ b/frontend/src/components/analytics-consent-form-modal.tsx @@ -1,5 +1,5 @@ import { ModalBackdrop } from "./modals/modal-backdrop"; -import ModalBody from "./modals/modal-body"; +import { ModalBody } from "./modals/modal-body"; import { ModalButton } from "./modal-button"; import { BaseModalTitle, diff --git a/frontend/src/components/feedback-modal.tsx b/frontend/src/components/feedback-modal.tsx index e28d072fa6cc..6cc0f8fbdd8a 100644 --- a/frontend/src/components/feedback-modal.tsx +++ b/frontend/src/components/feedback-modal.tsx @@ -4,7 +4,7 @@ import { BaseModalDescription, } from "./modals/confirmation-modals/base-modal"; import { ModalBackdrop } from "./modals/modal-backdrop"; -import ModalBody from "./modals/modal-body"; +import { ModalBody } from "./modals/modal-body"; interface FeedbackModalProps { onClose: () => void; diff --git a/frontend/src/components/modals/account-settings-form.tsx b/frontend/src/components/modals/account-settings-form.tsx index 3618544f43a9..8e3ee303a13b 100644 --- a/frontend/src/components/modals/account-settings-form.tsx +++ b/frontend/src/components/modals/account-settings-form.tsx @@ -4,7 +4,7 @@ import { BaseModalDescription, BaseModalTitle, } from "./confirmation-modals/base-modal"; -import ModalBody from "./modal-body"; +import { ModalBody } from "./modal-body"; import { ModalButton } from "../modal-button"; import { FormFieldset } from "../form-fieldset"; import { CustomInput } from "../custom-input"; diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/modals/confirmation-modals/base-modal.tsx index d46f73dbf4c0..66d092915617 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/base-modal.tsx @@ -1,6 +1,6 @@ import React from "react"; import { ModalButton } from "#/components/modal-button"; -import ModalBody from "../modal-body"; +import { ModalBody } from "../modal-body"; interface ButtonConfig { text: string; diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/modals/connect-to-github-modal.tsx index 07eeff20f4da..ce85fcf233a8 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/modals/connect-to-github-modal.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import ModalBody from "./modal-body"; +import { ModalBody } from "./modal-body"; import { CustomInput } from "../custom-input"; import { ModalButton } from "../modal-button"; import { diff --git a/frontend/src/components/modals/loading-project.tsx b/frontend/src/components/modals/loading-project.tsx index c0723ccaf815..e851656d245e 100644 --- a/frontend/src/components/modals/loading-project.tsx +++ b/frontend/src/components/modals/loading-project.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import LoadingSpinnerOuter from "#/icons/loading-outer.svg?react"; import { cn } from "#/utils/utils"; -import ModalBody from "./modal-body"; +import { ModalBody } from "./modal-body"; import { I18nKey } from "#/i18n/declaration"; interface LoadingSpinnerProps { diff --git a/frontend/src/components/modals/modal-body.tsx b/frontend/src/components/modals/modal-body.tsx index 4eb835e0911f..32e107b36772 100644 --- a/frontend/src/components/modals/modal-body.tsx +++ b/frontend/src/components/modals/modal-body.tsx @@ -7,7 +7,7 @@ interface ModalBodyProps { className?: React.HTMLProps["className"]; } -function ModalBody({ testID, children, className }: ModalBodyProps) { +export function ModalBody({ testID, children, className }: ModalBodyProps) { return (
); } - -export default ModalBody; diff --git a/frontend/src/components/waitlist-modal.tsx b/frontend/src/components/waitlist-modal.tsx index 596961dd2529..05167d8e2fac 100644 --- a/frontend/src/components/waitlist-modal.tsx +++ b/frontend/src/components/waitlist-modal.tsx @@ -2,7 +2,7 @@ import { ModalButton } from "./modal-button"; import { ModalBackdrop } from "./modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; -import ModalBody from "./modals/modal-body"; +import { ModalBody } from "./modals/modal-body"; import { JoinWaitlistAnchor } from "./join-waitlist-anchor"; import { WaitlistMessage } from "./waitlist-message"; From 14e1c56e7d76e0c16ace3cae3e9006b925605d11 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 19:16:47 +0400 Subject: [PATCH 05/13] Move buttons --- frontend/src/components/agent-control-bar.tsx | 2 +- frontend/src/components/analytics-consent-form-modal.tsx | 2 +- frontend/src/components/{ => buttons}/action-button.tsx | 0 .../src/components/{ => buttons}/confirmation-buttons.tsx | 2 +- frontend/src/components/{ => buttons}/continue-button.tsx | 0 .../src/components/{ => buttons}/copy-to-clipboard-button.tsx | 0 .../src/components/{ => buttons}/editor-action-button.tsx | 0 .../src/components/{ => buttons}/feedback-action-button.tsx | 0 frontend/src/components/{ => buttons}/icon-button.tsx | 0 frontend/src/components/{ => buttons}/modal-button.tsx | 0 frontend/src/components/{ => buttons}/refresh-button.tsx | 0 frontend/src/components/{ => buttons}/remove-button.tsx | 0 frontend/src/components/{ => buttons}/scroll-button.tsx | 0 .../src/components/{ => buttons}/scroll-to-bottom-button.tsx | 0 frontend/src/components/{ => buttons}/stop-button.tsx | 0 frontend/src/components/{ => buttons}/submit-button.tsx | 0 frontend/src/components/chat-input.tsx | 4 ++-- frontend/src/components/chat-message.tsx | 2 +- frontend/src/components/editor-actions.tsx | 2 +- frontend/src/components/feedback-actions.tsx | 2 +- frontend/src/components/feedback-form.tsx | 2 +- .../src/components/github-repositories-suggestion-box.tsx | 2 +- frontend/src/components/image-preview.tsx | 2 +- frontend/src/components/modals/account-settings-form.tsx | 2 +- .../src/components/modals/confirmation-modals/base-modal.tsx | 2 +- frontend/src/components/modals/connect-to-github-modal.tsx | 2 +- frontend/src/components/settings-form.tsx | 2 +- frontend/src/components/suggestion-bubble.tsx | 2 +- frontend/src/components/waitlist-modal.tsx | 2 +- .../file-explorer/buttons/refresh-icon-button.tsx | 2 +- .../file-explorer/buttons/toggle-workspace-icon-button.tsx | 2 +- .../file-explorer/buttons/upload-icon-button.tsx | 2 +- frontend/src/routes/_oh.app/chat-interface.tsx | 4 ++-- frontend/src/routes/_oh.app/messages.tsx | 2 +- 34 files changed, 23 insertions(+), 23 deletions(-) rename frontend/src/components/{ => buttons}/action-button.tsx (100%) rename frontend/src/components/{ => buttons}/confirmation-buttons.tsx (95%) rename frontend/src/components/{ => buttons}/continue-button.tsx (100%) rename frontend/src/components/{ => buttons}/copy-to-clipboard-button.tsx (100%) rename frontend/src/components/{ => buttons}/editor-action-button.tsx (100%) rename frontend/src/components/{ => buttons}/feedback-action-button.tsx (100%) rename frontend/src/components/{ => buttons}/icon-button.tsx (100%) rename frontend/src/components/{ => buttons}/modal-button.tsx (100%) rename frontend/src/components/{ => buttons}/refresh-button.tsx (100%) rename frontend/src/components/{ => buttons}/remove-button.tsx (100%) rename frontend/src/components/{ => buttons}/scroll-button.tsx (100%) rename frontend/src/components/{ => buttons}/scroll-to-bottom-button.tsx (100%) rename frontend/src/components/{ => buttons}/stop-button.tsx (100%) rename frontend/src/components/{ => buttons}/submit-button.tsx (100%) diff --git a/frontend/src/components/agent-control-bar.tsx b/frontend/src/components/agent-control-bar.tsx index 8713c9690e78..d732c9640dfa 100644 --- a/frontend/src/components/agent-control-bar.tsx +++ b/frontend/src/components/agent-control-bar.tsx @@ -6,7 +6,7 @@ import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; import { useWsClient } from "#/context/ws-client-provider"; import { IGNORE_TASK_STATE_MAP } from "#/ignore-task-state-map.constant"; -import { ActionButton } from "./action-button"; +import { ActionButton } from "./buttons/action-button"; export function AgentControlBar() { const { send } = useWsClient(); diff --git a/frontend/src/components/analytics-consent-form-modal.tsx b/frontend/src/components/analytics-consent-form-modal.tsx index 9fce2998c522..0c188cc84d87 100644 --- a/frontend/src/components/analytics-consent-form-modal.tsx +++ b/frontend/src/components/analytics-consent-form-modal.tsx @@ -1,6 +1,6 @@ import { ModalBackdrop } from "./modals/modal-backdrop"; import { ModalBody } from "./modals/modal-body"; -import { ModalButton } from "./modal-button"; +import { ModalButton } from "./buttons/modal-button"; import { BaseModalTitle, BaseModalDescription, diff --git a/frontend/src/components/action-button.tsx b/frontend/src/components/buttons/action-button.tsx similarity index 100% rename from frontend/src/components/action-button.tsx rename to frontend/src/components/buttons/action-button.tsx diff --git a/frontend/src/components/confirmation-buttons.tsx b/frontend/src/components/buttons/confirmation-buttons.tsx similarity index 95% rename from frontend/src/components/confirmation-buttons.tsx rename to frontend/src/components/buttons/confirmation-buttons.tsx index 368c00132c28..18ad6c50e8f9 100644 --- a/frontend/src/components/confirmation-buttons.tsx +++ b/frontend/src/components/buttons/confirmation-buttons.tsx @@ -3,7 +3,7 @@ import { I18nKey } from "#/i18n/declaration"; import AgentState from "#/types/agent-state"; import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { useWsClient } from "#/context/ws-client-provider"; -import { ActionTooltip } from "./action-tooltip"; +import { ActionTooltip } from "../action-tooltip"; export function ConfirmationButtons() { const { t } = useTranslation(); diff --git a/frontend/src/components/continue-button.tsx b/frontend/src/components/buttons/continue-button.tsx similarity index 100% rename from frontend/src/components/continue-button.tsx rename to frontend/src/components/buttons/continue-button.tsx diff --git a/frontend/src/components/copy-to-clipboard-button.tsx b/frontend/src/components/buttons/copy-to-clipboard-button.tsx similarity index 100% rename from frontend/src/components/copy-to-clipboard-button.tsx rename to frontend/src/components/buttons/copy-to-clipboard-button.tsx diff --git a/frontend/src/components/editor-action-button.tsx b/frontend/src/components/buttons/editor-action-button.tsx similarity index 100% rename from frontend/src/components/editor-action-button.tsx rename to frontend/src/components/buttons/editor-action-button.tsx diff --git a/frontend/src/components/feedback-action-button.tsx b/frontend/src/components/buttons/feedback-action-button.tsx similarity index 100% rename from frontend/src/components/feedback-action-button.tsx rename to frontend/src/components/buttons/feedback-action-button.tsx diff --git a/frontend/src/components/icon-button.tsx b/frontend/src/components/buttons/icon-button.tsx similarity index 100% rename from frontend/src/components/icon-button.tsx rename to frontend/src/components/buttons/icon-button.tsx diff --git a/frontend/src/components/modal-button.tsx b/frontend/src/components/buttons/modal-button.tsx similarity index 100% rename from frontend/src/components/modal-button.tsx rename to frontend/src/components/buttons/modal-button.tsx diff --git a/frontend/src/components/refresh-button.tsx b/frontend/src/components/buttons/refresh-button.tsx similarity index 100% rename from frontend/src/components/refresh-button.tsx rename to frontend/src/components/buttons/refresh-button.tsx diff --git a/frontend/src/components/remove-button.tsx b/frontend/src/components/buttons/remove-button.tsx similarity index 100% rename from frontend/src/components/remove-button.tsx rename to frontend/src/components/buttons/remove-button.tsx diff --git a/frontend/src/components/scroll-button.tsx b/frontend/src/components/buttons/scroll-button.tsx similarity index 100% rename from frontend/src/components/scroll-button.tsx rename to frontend/src/components/buttons/scroll-button.tsx diff --git a/frontend/src/components/scroll-to-bottom-button.tsx b/frontend/src/components/buttons/scroll-to-bottom-button.tsx similarity index 100% rename from frontend/src/components/scroll-to-bottom-button.tsx rename to frontend/src/components/buttons/scroll-to-bottom-button.tsx diff --git a/frontend/src/components/stop-button.tsx b/frontend/src/components/buttons/stop-button.tsx similarity index 100% rename from frontend/src/components/stop-button.tsx rename to frontend/src/components/buttons/stop-button.tsx diff --git a/frontend/src/components/submit-button.tsx b/frontend/src/components/buttons/submit-button.tsx similarity index 100% rename from frontend/src/components/submit-button.tsx rename to frontend/src/components/buttons/submit-button.tsx diff --git a/frontend/src/components/chat-input.tsx b/frontend/src/components/chat-input.tsx index 9c662f9300a9..82e970bc331d 100644 --- a/frontend/src/components/chat-input.tsx +++ b/frontend/src/components/chat-input.tsx @@ -1,8 +1,8 @@ import React from "react"; import TextareaAutosize from "react-textarea-autosize"; import { cn } from "#/utils/utils"; -import { SubmitButton } from "./submit-button"; -import { StopButton } from "./stop-button"; +import { SubmitButton } from "./buttons/submit-button"; +import { StopButton } from "./buttons/stop-button"; interface ChatInputProps { name?: string; diff --git a/frontend/src/components/chat-message.tsx b/frontend/src/components/chat-message.tsx index 299acf1d76fc..19bbb4f81c46 100644 --- a/frontend/src/components/chat-message.tsx +++ b/frontend/src/components/chat-message.tsx @@ -4,7 +4,7 @@ import remarkGfm from "remark-gfm"; import { code } from "./markdown/code"; import { cn } from "#/utils/utils"; import { ul, ol } from "./markdown/list"; -import { CopyToClipboardButton } from "./copy-to-clipboard-button"; +import { CopyToClipboardButton } from "./buttons/copy-to-clipboard-button"; interface ChatMessageProps { type: "user" | "assistant"; diff --git a/frontend/src/components/editor-actions.tsx b/frontend/src/components/editor-actions.tsx index 74414fa76ec6..c20c22dea2b0 100644 --- a/frontend/src/components/editor-actions.tsx +++ b/frontend/src/components/editor-actions.tsx @@ -1,4 +1,4 @@ -import { EditorActionButton } from "./editor-action-button"; +import { EditorActionButton } from "./buttons/editor-action-button"; interface EditorActionsProps { onSave: () => void; diff --git a/frontend/src/components/feedback-actions.tsx b/frontend/src/components/feedback-actions.tsx index 00226914e58d..c15ee89bbb64 100644 --- a/frontend/src/components/feedback-actions.tsx +++ b/frontend/src/components/feedback-actions.tsx @@ -1,6 +1,6 @@ import ThumbsUpIcon from "#/icons/thumbs-up.svg?react"; import ThumbDownIcon from "#/icons/thumbs-down.svg?react"; -import { FeedbackActionButton } from "./feedback-action-button"; +import { FeedbackActionButton } from "./buttons/feedback-action-button"; interface FeedbackActionsProps { onPositiveFeedback: () => void; diff --git a/frontend/src/components/feedback-form.tsx b/frontend/src/components/feedback-form.tsx index 9cb622d152c0..a57517e9ca31 100644 --- a/frontend/src/components/feedback-form.tsx +++ b/frontend/src/components/feedback-form.tsx @@ -1,6 +1,6 @@ import React from "react"; import hotToast from "react-hot-toast"; -import { ModalButton } from "./modal-button"; +import { ModalButton } from "./buttons/modal-button"; import { Feedback } from "#/api/open-hands.types"; import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback"; diff --git a/frontend/src/components/github-repositories-suggestion-box.tsx b/frontend/src/components/github-repositories-suggestion-box.tsx index 66898c7889b4..98494e9774ea 100644 --- a/frontend/src/components/github-repositories-suggestion-box.tsx +++ b/frontend/src/components/github-repositories-suggestion-box.tsx @@ -4,7 +4,7 @@ import { SuggestionBox } from "#/routes/_oh._index/suggestion-box"; import { ConnectToGitHubModal } from "./modals/connect-to-github-modal"; import { ModalBackdrop } from "./modals/modal-backdrop"; import { GitHubRepositorySelector } from "#/routes/_oh._index/github-repo-selector"; -import { ModalButton } from "./modal-button"; +import { ModalButton } from "./buttons/modal-button"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; interface GitHubRepositoriesSuggestionBoxProps { diff --git a/frontend/src/components/image-preview.tsx b/frontend/src/components/image-preview.tsx index dc83fc19ac3d..4e70bc4dc4de 100644 --- a/frontend/src/components/image-preview.tsx +++ b/frontend/src/components/image-preview.tsx @@ -1,4 +1,4 @@ -import { RemoveButton } from "./remove-button"; +import { RemoveButton } from "./buttons/remove-button"; import { Thumbnail } from "./thumbnail"; interface ImagePreviewProps { diff --git a/frontend/src/components/modals/account-settings-form.tsx b/frontend/src/components/modals/account-settings-form.tsx index 8e3ee303a13b..5f1cf87445c9 100644 --- a/frontend/src/components/modals/account-settings-form.tsx +++ b/frontend/src/components/modals/account-settings-form.tsx @@ -5,7 +5,7 @@ import { BaseModalTitle, } from "./confirmation-modals/base-modal"; import { ModalBody } from "./modal-body"; -import { ModalButton } from "../modal-button"; +import { ModalButton } from "../buttons/modal-button"; import { FormFieldset } from "../form-fieldset"; import { CustomInput } from "../custom-input"; import { AvailableLanguages } from "#/i18n"; diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/modals/confirmation-modals/base-modal.tsx index 66d092915617..a2580006d8de 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/base-modal.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { ModalButton } from "#/components/modal-button"; +import { ModalButton } from "#/components/buttons/modal-button"; import { ModalBody } from "../modal-body"; interface ButtonConfig { diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/modals/connect-to-github-modal.tsx index ce85fcf233a8..34c8607a3264 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/modals/connect-to-github-modal.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import { ModalBody } from "./modal-body"; import { CustomInput } from "../custom-input"; -import { ModalButton } from "../modal-button"; +import { ModalButton } from "../buttons/modal-button"; import { BaseModalDescription, BaseModalTitle, diff --git a/frontend/src/components/settings-form.tsx b/frontend/src/components/settings-form.tsx index 13f7d7f11430..c18a188bf671 100644 --- a/frontend/src/components/settings-form.tsx +++ b/frontend/src/components/settings-form.tsx @@ -7,7 +7,7 @@ import { ModelSelector } from "#/components/modals/settings/model-selector"; import { getDefaultSettings, Settings } from "#/services/settings"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { extractModelAndProvider } from "#/utils/extract-model-and-provider"; -import { ModalButton } from "./modal-button"; +import { ModalButton } from "./buttons/modal-button"; import { DangerModal } from "./modals/confirmation-modals/danger-modal"; import { I18nKey } from "#/i18n/declaration"; import { diff --git a/frontend/src/components/suggestion-bubble.tsx b/frontend/src/components/suggestion-bubble.tsx index 8a227819ee67..bcb66f245ff8 100644 --- a/frontend/src/components/suggestion-bubble.tsx +++ b/frontend/src/components/suggestion-bubble.tsx @@ -1,5 +1,5 @@ import Lightbulb from "#/icons/lightbulb.svg?react"; -import { RefreshButton } from "./refresh-button"; +import { RefreshButton } from "./buttons/refresh-button"; interface SuggestionBubbleProps { suggestion: string; diff --git a/frontend/src/components/waitlist-modal.tsx b/frontend/src/components/waitlist-modal.tsx index 05167d8e2fac..88e13601e629 100644 --- a/frontend/src/components/waitlist-modal.tsx +++ b/frontend/src/components/waitlist-modal.tsx @@ -1,4 +1,4 @@ -import { ModalButton } from "./modal-button"; +import { ModalButton } from "./buttons/modal-button"; import { ModalBackdrop } from "./modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx b/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx index ed2035bfeba7..1db7a804d8a5 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosRefresh } from "react-icons/io"; -import { IconButton } from "#/components/icon-button"; +import { IconButton } from "#/components/buttons/icon-button"; interface RefreshIconButtonProps { onClick: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx b/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx index bf91586c8a47..9125415ac5d8 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosArrowForward, IoIosArrowBack } from "react-icons/io"; -import { IconButton } from "#/components/icon-button"; +import { IconButton } from "#/components/buttons/icon-button"; interface ToggleWorkspaceIconButtonProps { onClick: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx b/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx index 80c256057f66..342e84379317 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx +++ b/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosCloudUpload } from "react-icons/io"; -import { IconButton } from "#/components/icon-button"; +import { IconButton } from "#/components/buttons/icon-button"; interface UploadIconButtonProps { onClick: () => void; diff --git a/frontend/src/routes/_oh.app/chat-interface.tsx b/frontend/src/routes/_oh.app/chat-interface.tsx index b671e2bf04e6..76dd927cbce7 100644 --- a/frontend/src/routes/_oh.app/chat-interface.tsx +++ b/frontend/src/routes/_oh.app/chat-interface.tsx @@ -12,8 +12,8 @@ import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { FeedbackModal } from "../../components/feedback-modal"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; import { TypingIndicator } from "../../components/typing-indicator"; -import { ContinueButton } from "../../components/continue-button"; -import { ScrollToBottomButton } from "../../components/scroll-to-bottom-button"; +import { ContinueButton } from "../../components/buttons/continue-button"; +import { ScrollToBottomButton } from "../../components/buttons/scroll-to-bottom-button"; import { useWsClient } from "#/context/ws-client-provider"; import { Messages } from "./messages"; import { LoadingSpinner } from "./loading-spinner"; diff --git a/frontend/src/routes/_oh.app/messages.tsx b/frontend/src/routes/_oh.app/messages.tsx index aedab0a56606..308afec37c5c 100644 --- a/frontend/src/routes/_oh.app/messages.tsx +++ b/frontend/src/routes/_oh.app/messages.tsx @@ -1,5 +1,5 @@ import { ChatMessage } from "#/components/chat-message"; -import { ConfirmationButtons } from "#/components/confirmation-buttons"; +import { ConfirmationButtons } from "#/components/buttons/confirmation-buttons"; import { ErrorMessage } from "#/components/error-message"; import { ImageCarousel } from "#/components/image-carousel"; From 1de6276db56ac1aa5b0767f4085063afad17cf67 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 19:19:35 +0400 Subject: [PATCH 06/13] Refactor action-button --- frontend/src/components/agent-control-bar.tsx | 1 - frontend/src/components/buttons/action-button.tsx | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/frontend/src/components/agent-control-bar.tsx b/frontend/src/components/agent-control-bar.tsx index d732c9640dfa..a177ff646c22 100644 --- a/frontend/src/components/agent-control-bar.tsx +++ b/frontend/src/components/agent-control-bar.tsx @@ -36,7 +36,6 @@ export function AgentControlBar() { : AgentState.PAUSED } handleAction={handleAction} - large > {curAgentState === AgentState.PAUSED ? : } diff --git a/frontend/src/components/buttons/action-button.tsx b/frontend/src/components/buttons/action-button.tsx index ae8f43f27f64..57c9f62d1107 100644 --- a/frontend/src/components/buttons/action-button.tsx +++ b/frontend/src/components/buttons/action-button.tsx @@ -6,7 +6,6 @@ interface ActionButtonProps { content: string; action: AgentState; handleAction: (action: AgentState) => void; - large?: boolean; } export function ActionButton({ @@ -15,19 +14,13 @@ export function ActionButton({ action, handleAction, children, - large = false, }: React.PropsWithChildren) { return ( diff --git a/frontend/src/components/buttons/scroll-button.tsx b/frontend/src/components/buttons/scroll-button.tsx index 31b7f5311643..236c5ef1fb93 100644 --- a/frontend/src/components/buttons/scroll-button.tsx +++ b/frontend/src/components/buttons/scroll-button.tsx @@ -14,7 +14,7 @@ export function ScrollButton({ return ( diff --git a/frontend/src/tailwind.css b/frontend/src/tailwind.css index b5c61c956711..a48cf2cb6a6a 100644 --- a/frontend/src/tailwind.css +++ b/frontend/src/tailwind.css @@ -1,3 +1,7 @@ @tailwind base; @tailwind components; @tailwind utilities; + +.button-base { + @apply bg-neutral-700 border border-neutral-600 rounded; +} From cbf9015f0132731306060a603cabea21add61f0b Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:20:00 +0400 Subject: [PATCH 08/13] organize into directories --- .../__tests__/components/browser.test.tsx | 2 +- .../components/chat-message.test.tsx | 2 +- .../components/chat/chat-input.test.tsx | 2 +- .../components/chat/chat-interface.test.tsx | 2 +- .../components/feedback-actions.test.tsx | 2 +- .../components/feedback-form.test.tsx | 2 +- .../file-explorer/explorer-tree.test.tsx | 2 +- .../file-explorer/file-explorer.test.tsx | 2 +- .../file-explorer/tree-node.test.tsx | 2 +- .../components/image-preview.test.tsx | 2 +- .../components/interactive-chat-box.test.tsx | 2 +- .../components/suggestion-item.test.tsx | 2 +- .../__tests__/components/suggestions.test.tsx | 2 +- .../components/terminal/terminal.test.tsx | 2 +- .../components/upload-image-input.test.tsx | 2 +- .../components/user-actions.test.tsx | 2 +- .../__tests__/components/user-avatar.test.tsx | 2 +- .../src/components/account-settings-form.tsx | 138 ++++++++++++++++++ .../account-settings-modal.tsx | 0 .../analytics-consent-form-modal.tsx | 8 +- .../{ => browser}/browser-snapshot.tsx | 0 .../src/components/{ => browser}/browser.tsx | 0 .../{ => browser}/empty-browser-message.tsx | 0 .../buttons/all-hands-logo-button.tsx | 0 .../buttons/confirmation-buttons.tsx | 2 +- .../buttons/docs-button.tsx | 0 .../buttons/exit-project-button.tsx | 0 .../buttons/open-vscode-button.tsx | 0 .../buttons/refresh-icon-button.tsx | 0 .../src/components/buttons/scroll-button.tsx | 26 ---- .../buttons/settings-button.tsx | 0 .../buttons/toggle-workspace-icon-button.tsx | 0 .../buttons/upload-icon-button.tsx | 0 .../chat}/action-suggestions.tsx | 2 +- .../src/components/{ => chat}/chat-input.tsx | 4 +- .../chat}/chat-interface.tsx | 14 +- .../components/{ => chat}/chat-message.tsx | 6 +- .../chat}/chat-suggestions.tsx | 2 +- .../components/{ => chat}/error-message.tsx | 0 .../{ => chat}/interactive-chat-box.tsx | 4 +- .../_oh.app => components/chat}/messages.tsx | 6 +- .../{ => chat}/typing-indicator.tsx | 0 .../components/connect-to-github-modal.tsx | 74 ++++++++++ .../{ => controls}/agent-control-bar.tsx | 2 +- .../{ => controls}/agent-status-bar.tsx | 2 +- .../components/{ => controls}/controls.tsx | 2 +- .../{ => controls}/security-lock.tsx | 0 .../editor}/code-editor-component.tsx | 0 .../{ => editor}/editor-actions.tsx | 2 +- .../exit-project-confirmation-modal.tsx | 0 .../{ => feedback}/feedback-actions.tsx | 2 +- .../{ => feedback}/feedback-form.tsx | 2 +- .../{ => feedback}/feedback-modal.tsx | 6 +- .../file-explorer/dropzone.tsx | 0 .../{ => file-explorer}/explorer-tree.tsx | 0 .../file-explorer/file-explorer-actions.tsx | 6 +- .../file-explorer/file-explorer-header.tsx | 0 .../file-explorer/file-explorer.tsx | 4 +- .../file-icon.tsx} | 2 +- .../{ => file-explorer}/folder-icon.tsx | 0 .../components/{ => file-explorer}/title.tsx | 2 +- .../{ => file-explorer}/tree-node.tsx | 0 .../github}/github-repo-selector.tsx | 0 .../github-repositories-suggestion-box.tsx | 10 +- .../{ => images}/attach-image-label.tsx | 0 .../{ => images}/image-carousel.tsx | 0 .../components/{ => images}/image-preview.tsx | 2 +- .../src/components/{ => images}/thumbnail.tsx | 0 .../{ => images}/upload-image-input.tsx | 0 .../jupyter-scroll-to-bottom-button.tsx | 26 ---- .../{ => jupyter}/jupyter-cell-input.tsx | 0 .../{ => jupyter}/jupyter-cell-output.tsx | 0 .../components/{ => jupyter}/jupyter-cell.tsx | 0 .../src/components/{ => jupyter}/jupyter.tsx | 2 +- .../components/{ => layout}/beta-badge.tsx | 0 .../src/components/{ => layout}/container.tsx | 0 .../src/components/{ => layout}/nav-tab.tsx | 0 .../modals/account-settings-form.tsx | 4 +- .../modals/connect-to-github-modal.tsx | 2 +- .../modals => components}/settings-modal.tsx | 0 .../src/components/{ => sidebar}/avatar.tsx | 0 .../_oh => components/sidebar}/sidebar.tsx | 16 +- .../components/{ => sidebar}/user-actions.tsx | 2 +- .../components/{ => sidebar}/user-avatar.tsx | 2 +- .../import-project-suggestion-box.tsx | 0 .../suggestions}/suggestion-box.tsx | 0 .../{ => suggestions}/suggestion-bubble.tsx | 2 +- .../{ => suggestions}/suggestion-item.tsx | 0 .../{ => suggestions}/suggestions.tsx | 0 .../components/{ => terminal}/terminal.tsx | 0 .../components/{ => ui}/action-tooltip.tsx | 0 .../src/components/{ => ui}/custom-input.tsx | 0 .../src/components/{ => ui}/error-toast.tsx | 0 .../src/components/{ => ui}/form-fieldset.tsx | 0 .../ui}/hero-heading.tsx | 0 .../ui}/loading-spinner.tsx | 0 .../ui}/task-form.tsx | 10 +- .../{ => waitlist}/join-waitlist-anchor.tsx | 0 .../{ => waitlist}/waitlist-message.tsx | 0 .../{ => waitlist}/waitlist-modal.tsx | 6 +- frontend/src/routes/_oh._index/route.tsx | 8 +- frontend/src/routes/_oh.app._index/route.tsx | 6 +- frontend/src/routes/_oh.app.browser.tsx | 2 +- frontend/src/routes/_oh.app.jupyter.tsx | 2 +- frontend/src/routes/_oh.app/route.tsx | 8 +- frontend/src/routes/_oh/route.tsx | 6 +- frontend/src/utils/display-error-toast.tsx | 2 +- 107 files changed, 315 insertions(+), 155 deletions(-) create mode 100644 frontend/src/components/account-settings-form.tsx rename frontend/src/{routes/_oh/modals => components}/account-settings-modal.tsx (100%) rename frontend/src/components/{ => analytics}/analytics-consent-form-modal.tsx (88%) rename frontend/src/components/{ => browser}/browser-snapshot.tsx (100%) rename frontend/src/components/{ => browser}/browser.tsx (100%) rename frontend/src/components/{ => browser}/empty-browser-message.tsx (100%) rename frontend/src/{routes/_oh => components}/buttons/all-hands-logo-button.tsx (100%) rename frontend/src/{routes/_oh => components}/buttons/docs-button.tsx (100%) rename frontend/src/{routes/_oh => components}/buttons/exit-project-button.tsx (100%) rename frontend/src/{routes/_oh.app._index/file-explorer => components}/buttons/open-vscode-button.tsx (100%) rename frontend/src/{routes/_oh.app._index/file-explorer => components}/buttons/refresh-icon-button.tsx (100%) delete mode 100644 frontend/src/components/buttons/scroll-button.tsx rename frontend/src/{routes/_oh => components}/buttons/settings-button.tsx (100%) rename frontend/src/{routes/_oh.app._index/file-explorer => components}/buttons/toggle-workspace-icon-button.tsx (100%) rename frontend/src/{routes/_oh.app._index/file-explorer => components}/buttons/upload-icon-button.tsx (100%) rename frontend/src/{routes/_oh.app => components/chat}/action-suggestions.tsx (97%) rename frontend/src/components/{ => chat}/chat-input.tsx (97%) rename frontend/src/{routes/_oh.app => components/chat}/chat-interface.tsx (90%) rename frontend/src/components/{ => chat}/chat-message.tsx (90%) rename frontend/src/{routes/_oh.app => components/chat}/chat-suggestions.tsx (93%) rename frontend/src/components/{ => chat}/error-message.tsx (100%) rename frontend/src/components/{ => chat}/interactive-chat-box.tsx (94%) rename frontend/src/{routes/_oh.app => components/chat}/messages.tsx (84%) rename frontend/src/components/{ => chat}/typing-indicator.tsx (100%) create mode 100644 frontend/src/components/connect-to-github-modal.tsx rename frontend/src/components/{ => controls}/agent-control-bar.tsx (96%) rename frontend/src/components/{ => controls}/agent-status-bar.tsx (96%) rename frontend/src/components/{ => controls}/controls.tsx (95%) rename frontend/src/components/{ => controls}/security-lock.tsx (100%) rename frontend/src/{routes/_oh.app._index => components/editor}/code-editor-component.tsx (100%) rename frontend/src/components/{ => editor}/editor-actions.tsx (90%) rename frontend/src/{routes/_oh/modals => components}/exit-project-confirmation-modal.tsx (100%) rename frontend/src/components/{ => feedback}/feedback-actions.tsx (90%) rename frontend/src/components/{ => feedback}/feedback-form.tsx (98%) rename frontend/src/components/{ => feedback}/feedback-modal.tsx (82%) rename frontend/src/{routes/_oh.app._index => components}/file-explorer/dropzone.tsx (100%) rename frontend/src/components/{ => file-explorer}/explorer-tree.tsx (100%) rename frontend/src/{routes/_oh.app._index => components}/file-explorer/file-explorer-actions.tsx (75%) rename frontend/src/{routes/_oh.app._index => components}/file-explorer/file-explorer-header.tsx (100%) rename frontend/src/{routes/_oh.app._index => components}/file-explorer/file-explorer.tsx (97%) rename frontend/src/components/{file-icons.tsx => file-explorer/file-icon.tsx} (80%) rename frontend/src/components/{ => file-explorer}/folder-icon.tsx (100%) rename frontend/src/components/{ => file-explorer}/title.tsx (94%) rename frontend/src/components/{ => file-explorer}/tree-node.tsx (100%) rename frontend/src/{routes/_oh._index => components/github}/github-repo-selector.tsx (100%) rename frontend/src/components/{ => github}/github-repositories-suggestion-box.tsx (84%) rename frontend/src/components/{ => images}/attach-image-label.tsx (100%) rename frontend/src/components/{ => images}/image-carousel.tsx (100%) rename frontend/src/components/{ => images}/image-preview.tsx (88%) rename frontend/src/components/{ => images}/thumbnail.tsx (100%) rename frontend/src/components/{ => images}/upload-image-input.tsx (100%) delete mode 100644 frontend/src/components/jupyter-scroll-to-bottom-button.tsx rename frontend/src/components/{ => jupyter}/jupyter-cell-input.tsx (100%) rename frontend/src/components/{ => jupyter}/jupyter-cell-output.tsx (100%) rename frontend/src/components/{ => jupyter}/jupyter-cell.tsx (100%) rename frontend/src/components/{ => jupyter}/jupyter.tsx (93%) rename frontend/src/components/{ => layout}/beta-badge.tsx (100%) rename frontend/src/components/{ => layout}/container.tsx (100%) rename frontend/src/components/{ => layout}/nav-tab.tsx (100%) rename frontend/src/{routes/_oh/modals => components}/settings-modal.tsx (100%) rename frontend/src/components/{ => sidebar}/avatar.tsx (100%) rename frontend/src/{routes/_oh => components/sidebar}/sidebar.tsx (83%) rename frontend/src/components/{ => sidebar}/user-actions.tsx (92%) rename frontend/src/components/{ => sidebar}/user-avatar.tsx (93%) rename frontend/src/{routes/_oh._index => components/suggestions}/import-project-suggestion-box.tsx (100%) rename frontend/src/{routes/_oh._index => components/suggestions}/suggestion-box.tsx (100%) rename frontend/src/components/{ => suggestions}/suggestion-bubble.tsx (92%) rename frontend/src/components/{ => suggestions}/suggestion-item.tsx (100%) rename frontend/src/components/{ => suggestions}/suggestions.tsx (100%) rename frontend/src/components/{ => terminal}/terminal.tsx (100%) rename frontend/src/components/{ => ui}/action-tooltip.tsx (100%) rename frontend/src/components/{ => ui}/custom-input.tsx (100%) rename frontend/src/components/{ => ui}/error-toast.tsx (100%) rename frontend/src/components/{ => ui}/form-fieldset.tsx (100%) rename frontend/src/{routes/_oh._index => components/ui}/hero-heading.tsx (100%) rename frontend/src/{routes/_oh.app => components/ui}/loading-spinner.tsx (100%) rename frontend/src/{routes/_oh._index => components/ui}/task-form.tsx (92%) rename frontend/src/components/{ => waitlist}/join-waitlist-anchor.tsx (100%) rename frontend/src/components/{ => waitlist}/waitlist-message.tsx (100%) rename frontend/src/components/{ => waitlist}/waitlist-modal.tsx (86%) diff --git a/frontend/__tests__/components/browser.test.tsx b/frontend/__tests__/components/browser.test.tsx index cb48f36208c6..e246f06c15a9 100644 --- a/frontend/__tests__/components/browser.test.tsx +++ b/frontend/__tests__/components/browser.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { describe, it, expect } from "vitest"; import { renderWithProviders } from "../../test-utils"; -import { BrowserPanel } from "#/components/browser"; +import { BrowserPanel } from "#/components/browser/browser"; describe("Browser", () => { it("renders a message if no screenshotSrc is provided", () => { diff --git a/frontend/__tests__/components/chat-message.test.tsx b/frontend/__tests__/components/chat-message.test.tsx index ae2f7ad81335..c729ce1a15f3 100644 --- a/frontend/__tests__/components/chat-message.test.tsx +++ b/frontend/__tests__/components/chat-message.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, it, expect, test } from "vitest"; -import { ChatMessage } from "#/components/chat-message"; +import { ChatMessage } from "#/components/chat/chat-message"; describe("ChatMessage", () => { it("should render a user message", () => { diff --git a/frontend/__tests__/components/chat/chat-input.test.tsx b/frontend/__tests__/components/chat/chat-input.test.tsx index 8a5f0c3dd6b4..f0cc9ba1fca9 100644 --- a/frontend/__tests__/components/chat/chat-input.test.tsx +++ b/frontend/__tests__/components/chat/chat-input.test.tsx @@ -1,7 +1,7 @@ import userEvent from "@testing-library/user-event"; import { fireEvent, render, screen } from "@testing-library/react"; import { describe, afterEach, vi, it, expect } from "vitest"; -import { ChatInput } from "#/components/chat-input"; +import { ChatInput } from "#/components/chat/chat-input"; describe("ChatInput", () => { const onSubmitMock = vi.fn(); diff --git a/frontend/__tests__/components/chat/chat-interface.test.tsx b/frontend/__tests__/components/chat/chat-interface.test.tsx index 8596d3acd3d7..b99ea15b6d6c 100644 --- a/frontend/__tests__/components/chat/chat-interface.test.tsx +++ b/frontend/__tests__/components/chat/chat-interface.test.tsx @@ -6,7 +6,7 @@ import { addUserMessage } from "#/state/chat-slice"; import { SUGGESTIONS } from "#/utils/suggestions"; import * as ChatSlice from "#/state/chat-slice"; import { WsClientProviderStatus } from "#/context/ws-client-provider"; -import { ChatInterface } from "#/routes/_oh.app/chat-interface"; +import { ChatInterface } from "#/components/chat/chat-interface"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const renderChatInterface = (messages: (Message | ErrorMessage)[]) => diff --git a/frontend/__tests__/components/feedback-actions.test.tsx b/frontend/__tests__/components/feedback-actions.test.tsx index 48d1ce5d8913..d96747f2b996 100644 --- a/frontend/__tests__/components/feedback-actions.test.tsx +++ b/frontend/__tests__/components/feedback-actions.test.tsx @@ -1,7 +1,7 @@ import { render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { FeedbackActions } from "#/components/feedback-actions"; +import { FeedbackActions } from "#/components/feedback/feedback-actions"; describe("FeedbackActions", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/feedback-form.test.tsx b/frontend/__tests__/components/feedback-form.test.tsx index f686c45bf9eb..b42b2744befe 100644 --- a/frontend/__tests__/components/feedback-form.test.tsx +++ b/frontend/__tests__/components/feedback-form.test.tsx @@ -2,7 +2,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; import { renderWithProviders } from "test-utils"; -import { FeedbackForm } from "#/components/feedback-form"; +import { FeedbackForm } from "#/components/feedback/feedback-form"; describe("FeedbackForm", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx index 126ec197097b..8237133597c0 100644 --- a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx +++ b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { describe, afterEach, vi, it, expect } from "vitest"; -import { ExplorerTree } from "#/components/explorer-tree"; +import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; const FILES = ["file-1-1.ts", "folder-1-2"]; diff --git a/frontend/__tests__/components/file-explorer/file-explorer.test.tsx b/frontend/__tests__/components/file-explorer/file-explorer.test.tsx index 6b360520347d..a9e90294c8d3 100644 --- a/frontend/__tests__/components/file-explorer/file-explorer.test.tsx +++ b/frontend/__tests__/components/file-explorer/file-explorer.test.tsx @@ -4,8 +4,8 @@ import { renderWithProviders } from "test-utils"; import { describe, it, expect, vi, Mock, afterEach } from "vitest"; import toast from "#/utils/toast"; import AgentState from "#/types/agent-state"; -import { FileExplorer } from "#/routes/_oh.app._index/file-explorer/file-explorer"; import OpenHands from "#/api/open-hands"; +import { FileExplorer } from "#/components/file-explorer/file-explorer"; const toastSpy = vi.spyOn(toast, "error"); const uploadFilesSpy = vi.spyOn(OpenHands, "uploadFiles"); diff --git a/frontend/__tests__/components/file-explorer/tree-node.test.tsx b/frontend/__tests__/components/file-explorer/tree-node.test.tsx index 5ded4e798962..ebd8c029d433 100644 --- a/frontend/__tests__/components/file-explorer/tree-node.test.tsx +++ b/frontend/__tests__/components/file-explorer/tree-node.test.tsx @@ -2,7 +2,7 @@ import { screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { renderWithProviders } from "test-utils"; import { vi, describe, afterEach, it, expect } from "vitest"; -import TreeNode from "#/components/tree-node"; +import TreeNode from "#/components/file-explorer/tree-node"; import OpenHands from "#/api/open-hands"; const getFileSpy = vi.spyOn(OpenHands, "getFile"); diff --git a/frontend/__tests__/components/image-preview.test.tsx b/frontend/__tests__/components/image-preview.test.tsx index ba33fb1f0a86..a50675ad2e7e 100644 --- a/frontend/__tests__/components/image-preview.test.tsx +++ b/frontend/__tests__/components/image-preview.test.tsx @@ -1,7 +1,7 @@ +import { ImagePreview } from "#/components/images/image-preview"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, expect, it, vi } from "vitest"; -import { ImagePreview } from "#/components/image-preview"; describe("ImagePreview", () => { it("should render an image", () => { diff --git a/frontend/__tests__/components/interactive-chat-box.test.tsx b/frontend/__tests__/components/interactive-chat-box.test.tsx index d7e29bae86cc..8fdc13012d79 100644 --- a/frontend/__tests__/components/interactive-chat-box.test.tsx +++ b/frontend/__tests__/components/interactive-chat-box.test.tsx @@ -1,7 +1,7 @@ import { render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; -import { InteractiveChatBox } from "#/components/interactive-chat-box"; +import { InteractiveChatBox } from "#/components/chat/interactive-chat-box"; describe("InteractiveChatBox", () => { const onSubmitMock = vi.fn(); diff --git a/frontend/__tests__/components/suggestion-item.test.tsx b/frontend/__tests__/components/suggestion-item.test.tsx index 076b29ca2144..932ba7fd23e8 100644 --- a/frontend/__tests__/components/suggestion-item.test.tsx +++ b/frontend/__tests__/components/suggestion-item.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { SuggestionItem } from "#/components/suggestion-item"; +import { SuggestionItem } from "#/components/suggestions/suggestion-item"; describe("SuggestionItem", () => { const suggestionItem = { label: "suggestion1", value: "a long text value" }; diff --git a/frontend/__tests__/components/suggestions.test.tsx b/frontend/__tests__/components/suggestions.test.tsx index fcc45a6ad040..8bf715641dc9 100644 --- a/frontend/__tests__/components/suggestions.test.tsx +++ b/frontend/__tests__/components/suggestions.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { Suggestions } from "#/components/suggestions"; +import { Suggestions } from "#/components/suggestions/suggestions"; describe("Suggestions", () => { const firstSuggestion = { diff --git a/frontend/__tests__/components/terminal/terminal.test.tsx b/frontend/__tests__/components/terminal/terminal.test.tsx index 5acc28e06c8b..d660f83639a0 100644 --- a/frontend/__tests__/components/terminal/terminal.test.tsx +++ b/frontend/__tests__/components/terminal/terminal.test.tsx @@ -2,7 +2,7 @@ import { act, screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { vi, describe, afterEach, it, expect } from "vitest"; import { Command, appendInput, appendOutput } from "#/state/command-slice"; -import Terminal from "#/components/terminal"; +import Terminal from "#/components/terminal/terminal"; global.ResizeObserver = vi.fn().mockImplementation(() => ({ observe: vi.fn(), diff --git a/frontend/__tests__/components/upload-image-input.test.tsx b/frontend/__tests__/components/upload-image-input.test.tsx index 77f89ee8851a..3b2d272edc9a 100644 --- a/frontend/__tests__/components/upload-image-input.test.tsx +++ b/frontend/__tests__/components/upload-image-input.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { UploadImageInput } from "#/components/upload-image-input"; +import { UploadImageInput } from "#/components/images/upload-image-input"; describe("UploadImageInput", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/user-actions.test.tsx b/frontend/__tests__/components/user-actions.test.tsx index b9bb65d0f3c9..c16da1eb8ab5 100644 --- a/frontend/__tests__/components/user-actions.test.tsx +++ b/frontend/__tests__/components/user-actions.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import { describe, expect, it, test, vi, afterEach } from "vitest"; import userEvent from "@testing-library/user-event"; -import { UserActions } from "#/components/user-actions"; +import { UserActions } from "#/components/sidebar/user-actions"; describe("UserActions", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/user-avatar.test.tsx b/frontend/__tests__/components/user-avatar.test.tsx index 07f3d44afe41..2fef1dbf6b14 100644 --- a/frontend/__tests__/components/user-avatar.test.tsx +++ b/frontend/__tests__/components/user-avatar.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { UserAvatar } from "#/components/user-avatar"; +import { UserAvatar } from "#/components/sidebar/user-avatar"; describe("UserAvatar", () => { const onClickMock = vi.fn(); diff --git a/frontend/src/components/account-settings-form.tsx b/frontend/src/components/account-settings-form.tsx new file mode 100644 index 000000000000..6cfe1ea2ef33 --- /dev/null +++ b/frontend/src/components/account-settings-form.tsx @@ -0,0 +1,138 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { AvailableLanguages } from "#/i18n"; +import { I18nKey } from "#/i18n/declaration"; +import { useAuth } from "#/context/auth-context"; +import { useUserPrefs } from "#/context/user-prefs-context"; +import { handleCaptureConsent } from "#/utils/handle-capture-consent"; +import { CustomInput } from "./ui/custom-input"; +import { FormFieldset } from "./ui/form-fieldset"; +import { ModalButton } from "./buttons/modal-button"; +import { ModalBody } from "./modals/modal-body"; +import { + BaseModalTitle, + BaseModalDescription, +} from "./modals/confirmation-modals/base-modal"; + +interface AccountSettingsFormProps { + onClose: () => void; + selectedLanguage: string; + gitHubError: boolean; + analyticsConsent: string | null; +} + +export function AccountSettingsForm({ + onClose, + selectedLanguage, + gitHubError, + analyticsConsent, +}: AccountSettingsFormProps) { + const { gitHubToken, setGitHubToken, logout } = useAuth(); + const { saveSettings } = useUserPrefs(); + const { t } = useTranslation(); + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + + const ghToken = formData.get("ghToken")?.toString(); + const language = formData.get("language")?.toString(); + const analytics = formData.get("analytics")?.toString() === "on"; + + if (ghToken) setGitHubToken(ghToken); + + // The form returns the language label, so we need to find the corresponding + // language key to save it in the settings + if (language) { + const languageKey = AvailableLanguages.find( + ({ label }) => label === language, + )?.value; + + if (languageKey) saveSettings({ LANGUAGE: languageKey }); + } + + handleCaptureConsent(analytics); + const ANALYTICS = analytics.toString(); + localStorage.setItem("analytics-consent", ANALYTICS); + + onClose(); + }; + + return ( + +
+
+ + + ({ + key, + value: label, + }))} + /> + + + + {t(I18nKey.CONNECT_TO_GITHUB_MODAL$GET_YOUR_TOKEN)}{" "} + + {t(I18nKey.CONNECT_TO_GITHUB_MODAL$HERE)} + + + {gitHubError && ( +

+ {t(I18nKey.ACCOUNT_SETTINGS_MODAL$GITHUB_TOKEN_INVALID)} +

+ )} + {gitHubToken && !gitHubError && ( + { + logout(); + onClose(); + }} + className="text-danger self-start" + /> + )} +
+ + + +
+ + +
+
+
+ ); +} diff --git a/frontend/src/routes/_oh/modals/account-settings-modal.tsx b/frontend/src/components/account-settings-modal.tsx similarity index 100% rename from frontend/src/routes/_oh/modals/account-settings-modal.tsx rename to frontend/src/components/account-settings-modal.tsx diff --git a/frontend/src/components/analytics-consent-form-modal.tsx b/frontend/src/components/analytics/analytics-consent-form-modal.tsx similarity index 88% rename from frontend/src/components/analytics-consent-form-modal.tsx rename to frontend/src/components/analytics/analytics-consent-form-modal.tsx index 0c188cc84d87..fac48030c723 100644 --- a/frontend/src/components/analytics-consent-form-modal.tsx +++ b/frontend/src/components/analytics/analytics-consent-form-modal.tsx @@ -1,10 +1,10 @@ -import { ModalBackdrop } from "./modals/modal-backdrop"; -import { ModalBody } from "./modals/modal-body"; -import { ModalButton } from "./buttons/modal-button"; +import { ModalBackdrop } from "../modals/modal-backdrop"; +import { ModalBody } from "../modals/modal-body"; +import { ModalButton } from "../buttons/modal-button"; import { BaseModalTitle, BaseModalDescription, -} from "./modals/confirmation-modals/base-modal"; +} from "../modals/confirmation-modals/base-modal"; import { handleCaptureConsent } from "#/utils/handle-capture-consent"; interface AnalyticsConsentFormModalProps { diff --git a/frontend/src/components/browser-snapshot.tsx b/frontend/src/components/browser/browser-snapshot.tsx similarity index 100% rename from frontend/src/components/browser-snapshot.tsx rename to frontend/src/components/browser/browser-snapshot.tsx diff --git a/frontend/src/components/browser.tsx b/frontend/src/components/browser/browser.tsx similarity index 100% rename from frontend/src/components/browser.tsx rename to frontend/src/components/browser/browser.tsx diff --git a/frontend/src/components/empty-browser-message.tsx b/frontend/src/components/browser/empty-browser-message.tsx similarity index 100% rename from frontend/src/components/empty-browser-message.tsx rename to frontend/src/components/browser/empty-browser-message.tsx diff --git a/frontend/src/routes/_oh/buttons/all-hands-logo-button.tsx b/frontend/src/components/buttons/all-hands-logo-button.tsx similarity index 100% rename from frontend/src/routes/_oh/buttons/all-hands-logo-button.tsx rename to frontend/src/components/buttons/all-hands-logo-button.tsx diff --git a/frontend/src/components/buttons/confirmation-buttons.tsx b/frontend/src/components/buttons/confirmation-buttons.tsx index 18ad6c50e8f9..19e323875947 100644 --- a/frontend/src/components/buttons/confirmation-buttons.tsx +++ b/frontend/src/components/buttons/confirmation-buttons.tsx @@ -3,7 +3,7 @@ import { I18nKey } from "#/i18n/declaration"; import AgentState from "#/types/agent-state"; import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { useWsClient } from "#/context/ws-client-provider"; -import { ActionTooltip } from "../action-tooltip"; +import { ActionTooltip } from "../ui/action-tooltip"; export function ConfirmationButtons() { const { t } = useTranslation(); diff --git a/frontend/src/routes/_oh/buttons/docs-button.tsx b/frontend/src/components/buttons/docs-button.tsx similarity index 100% rename from frontend/src/routes/_oh/buttons/docs-button.tsx rename to frontend/src/components/buttons/docs-button.tsx diff --git a/frontend/src/routes/_oh/buttons/exit-project-button.tsx b/frontend/src/components/buttons/exit-project-button.tsx similarity index 100% rename from frontend/src/routes/_oh/buttons/exit-project-button.tsx rename to frontend/src/components/buttons/exit-project-button.tsx diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/open-vscode-button.tsx b/frontend/src/components/buttons/open-vscode-button.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/file-explorer/buttons/open-vscode-button.tsx rename to frontend/src/components/buttons/open-vscode-button.tsx diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx b/frontend/src/components/buttons/refresh-icon-button.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/file-explorer/buttons/refresh-icon-button.tsx rename to frontend/src/components/buttons/refresh-icon-button.tsx diff --git a/frontend/src/components/buttons/scroll-button.tsx b/frontend/src/components/buttons/scroll-button.tsx deleted file mode 100644 index 236c5ef1fb93..000000000000 --- a/frontend/src/components/buttons/scroll-button.tsx +++ /dev/null @@ -1,26 +0,0 @@ -interface ScrollButtonProps { - onClick: () => void; - icon: JSX.Element; - label: string; - disabled?: boolean; -} - -export function ScrollButton({ - onClick, - icon, - label, - disabled = false, -}: ScrollButtonProps): JSX.Element { - return ( - - ); -} diff --git a/frontend/src/routes/_oh/buttons/settings-button.tsx b/frontend/src/components/buttons/settings-button.tsx similarity index 100% rename from frontend/src/routes/_oh/buttons/settings-button.tsx rename to frontend/src/components/buttons/settings-button.tsx diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx b/frontend/src/components/buttons/toggle-workspace-icon-button.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/file-explorer/buttons/toggle-workspace-icon-button.tsx rename to frontend/src/components/buttons/toggle-workspace-icon-button.tsx diff --git a/frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx b/frontend/src/components/buttons/upload-icon-button.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/file-explorer/buttons/upload-icon-button.tsx rename to frontend/src/components/buttons/upload-icon-button.tsx diff --git a/frontend/src/routes/_oh.app/action-suggestions.tsx b/frontend/src/components/chat/action-suggestions.tsx similarity index 97% rename from frontend/src/routes/_oh.app/action-suggestions.tsx rename to frontend/src/components/chat/action-suggestions.tsx index fc9442e99606..3f89c9e43e5e 100644 --- a/frontend/src/routes/_oh.app/action-suggestions.tsx +++ b/frontend/src/components/chat/action-suggestions.tsx @@ -1,6 +1,6 @@ import posthog from "posthog-js"; import React from "react"; -import { SuggestionItem } from "#/components/suggestion-item"; +import { SuggestionItem } from "#/components/suggestions/suggestion-item"; import { useAuth } from "#/context/auth-context"; import { downloadWorkspace } from "#/utils/download-workspace"; diff --git a/frontend/src/components/chat-input.tsx b/frontend/src/components/chat/chat-input.tsx similarity index 97% rename from frontend/src/components/chat-input.tsx rename to frontend/src/components/chat/chat-input.tsx index 82e970bc331d..241c30c8b9de 100644 --- a/frontend/src/components/chat-input.tsx +++ b/frontend/src/components/chat/chat-input.tsx @@ -1,8 +1,8 @@ import React from "react"; import TextareaAutosize from "react-textarea-autosize"; import { cn } from "#/utils/utils"; -import { SubmitButton } from "./buttons/submit-button"; -import { StopButton } from "./buttons/stop-button"; +import { SubmitButton } from "../buttons/submit-button"; +import { StopButton } from "../buttons/stop-button"; interface ChatInputProps { name?: string; diff --git a/frontend/src/routes/_oh.app/chat-interface.tsx b/frontend/src/components/chat/chat-interface.tsx similarity index 90% rename from frontend/src/routes/_oh.app/chat-interface.tsx rename to frontend/src/components/chat/chat-interface.tsx index 76dd927cbce7..b1f389ba4c51 100644 --- a/frontend/src/routes/_oh.app/chat-interface.tsx +++ b/frontend/src/components/chat/chat-interface.tsx @@ -2,21 +2,21 @@ import { useDispatch, useSelector } from "react-redux"; import React from "react"; import posthog from "posthog-js"; import { convertImageToBase64 } from "#/utils/convert-image-to-base-64"; -import { FeedbackActions } from "../../components/feedback-actions"; +import { FeedbackActions } from "../feedback/feedback-actions"; import { createChatMessage } from "#/services/chat-service"; -import { InteractiveChatBox } from "../../components/interactive-chat-box"; +import { InteractiveChatBox } from "./interactive-chat-box"; import { addUserMessage } from "#/state/chat-slice"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; -import { FeedbackModal } from "../../components/feedback-modal"; +import { FeedbackModal } from "../feedback/feedback-modal"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; -import { TypingIndicator } from "../../components/typing-indicator"; -import { ContinueButton } from "../../components/buttons/continue-button"; -import { ScrollToBottomButton } from "../../components/buttons/scroll-to-bottom-button"; +import { TypingIndicator } from "./typing-indicator"; +import { ContinueButton } from "../buttons/continue-button"; +import { ScrollToBottomButton } from "../buttons/scroll-to-bottom-button"; import { useWsClient } from "#/context/ws-client-provider"; import { Messages } from "./messages"; -import { LoadingSpinner } from "./loading-spinner"; +import { LoadingSpinner } from "../ui/loading-spinner"; import { ChatSuggestions } from "./chat-suggestions"; import { ActionSuggestions } from "./action-suggestions"; diff --git a/frontend/src/components/chat-message.tsx b/frontend/src/components/chat/chat-message.tsx similarity index 90% rename from frontend/src/components/chat-message.tsx rename to frontend/src/components/chat/chat-message.tsx index 19bbb4f81c46..f479c332c8a2 100644 --- a/frontend/src/components/chat-message.tsx +++ b/frontend/src/components/chat/chat-message.tsx @@ -1,10 +1,10 @@ import React from "react"; import Markdown from "react-markdown"; import remarkGfm from "remark-gfm"; -import { code } from "./markdown/code"; +import { code } from "../markdown/code"; import { cn } from "#/utils/utils"; -import { ul, ol } from "./markdown/list"; -import { CopyToClipboardButton } from "./buttons/copy-to-clipboard-button"; +import { ul, ol } from "../markdown/list"; +import { CopyToClipboardButton } from "../buttons/copy-to-clipboard-button"; interface ChatMessageProps { type: "user" | "assistant"; diff --git a/frontend/src/routes/_oh.app/chat-suggestions.tsx b/frontend/src/components/chat/chat-suggestions.tsx similarity index 93% rename from frontend/src/routes/_oh.app/chat-suggestions.tsx rename to frontend/src/components/chat/chat-suggestions.tsx index 1f08ace538f7..ffc985443196 100644 --- a/frontend/src/routes/_oh.app/chat-suggestions.tsx +++ b/frontend/src/components/chat/chat-suggestions.tsx @@ -1,4 +1,4 @@ -import { Suggestions } from "#/components/suggestions"; +import { Suggestions } from "#/components/suggestions/suggestions"; import BuildIt from "#/icons/build-it.svg?react"; import { SUGGESTIONS } from "#/utils/suggestions"; diff --git a/frontend/src/components/error-message.tsx b/frontend/src/components/chat/error-message.tsx similarity index 100% rename from frontend/src/components/error-message.tsx rename to frontend/src/components/chat/error-message.tsx diff --git a/frontend/src/components/interactive-chat-box.tsx b/frontend/src/components/chat/interactive-chat-box.tsx similarity index 94% rename from frontend/src/components/interactive-chat-box.tsx rename to frontend/src/components/chat/interactive-chat-box.tsx index c3ab7945a64b..e96339adf0a7 100644 --- a/frontend/src/components/interactive-chat-box.tsx +++ b/frontend/src/components/chat/interactive-chat-box.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { UploadImageInput } from "./upload-image-input"; import { ChatInput } from "./chat-input"; import { cn } from "#/utils/utils"; -import { ImageCarousel } from "./image-carousel"; +import { ImageCarousel } from "../images/image-carousel"; +import { UploadImageInput } from "../images/upload-image-input"; interface InteractiveChatBoxProps { isDisabled?: boolean; diff --git a/frontend/src/routes/_oh.app/messages.tsx b/frontend/src/components/chat/messages.tsx similarity index 84% rename from frontend/src/routes/_oh.app/messages.tsx rename to frontend/src/components/chat/messages.tsx index 308afec37c5c..3c940901f792 100644 --- a/frontend/src/routes/_oh.app/messages.tsx +++ b/frontend/src/components/chat/messages.tsx @@ -1,7 +1,7 @@ -import { ChatMessage } from "#/components/chat-message"; +import { ChatMessage } from "#/components/chat/chat-message"; import { ConfirmationButtons } from "#/components/buttons/confirmation-buttons"; -import { ErrorMessage } from "#/components/error-message"; -import { ImageCarousel } from "#/components/image-carousel"; +import { ImageCarousel } from "../images/image-carousel"; +import { ErrorMessage } from "./error-message"; const isErrorMessage = ( message: Message | ErrorMessage, diff --git a/frontend/src/components/typing-indicator.tsx b/frontend/src/components/chat/typing-indicator.tsx similarity index 100% rename from frontend/src/components/typing-indicator.tsx rename to frontend/src/components/chat/typing-indicator.tsx diff --git a/frontend/src/components/connect-to-github-modal.tsx b/frontend/src/components/connect-to-github-modal.tsx new file mode 100644 index 000000000000..b145bd0eb69a --- /dev/null +++ b/frontend/src/components/connect-to-github-modal.tsx @@ -0,0 +1,74 @@ +import { useTranslation } from "react-i18next"; +import { I18nKey } from "#/i18n/declaration"; +import { useAuth } from "#/context/auth-context"; +import { CustomInput } from "./ui/custom-input"; +import { ModalButton } from "./buttons/modal-button"; +import { ModalBody } from "./modals/modal-body"; +import { + BaseModalTitle, + BaseModalDescription, +} from "./modals/confirmation-modals/base-modal"; + +interface ConnectToGitHubModalProps { + onClose: () => void; +} + +export function ConnectToGitHubModal({ onClose }: ConnectToGitHubModalProps) { + const { gitHubToken, setGitHubToken } = useAuth(); + const { t } = useTranslation(); + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const ghToken = formData.get("ghToken")?.toString(); + + if (ghToken) setGitHubToken(ghToken); + onClose(); + }; + + return ( + +
+ + + {t(I18nKey.CONNECT_TO_GITHUB_MODAL$GET_YOUR_TOKEN)}{" "} + + {t(I18nKey.CONNECT_TO_GITHUB_MODAL$HERE)} + + + } + /> +
+
+ + +
+ + +
+ +
+ ); +} diff --git a/frontend/src/components/agent-control-bar.tsx b/frontend/src/components/controls/agent-control-bar.tsx similarity index 96% rename from frontend/src/components/agent-control-bar.tsx rename to frontend/src/components/controls/agent-control-bar.tsx index a177ff646c22..ff9489f2e9d5 100644 --- a/frontend/src/components/agent-control-bar.tsx +++ b/frontend/src/components/controls/agent-control-bar.tsx @@ -6,7 +6,7 @@ import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; import { useWsClient } from "#/context/ws-client-provider"; import { IGNORE_TASK_STATE_MAP } from "#/ignore-task-state-map.constant"; -import { ActionButton } from "./buttons/action-button"; +import { ActionButton } from "../buttons/action-button"; export function AgentControlBar() { const { send } = useWsClient(); diff --git a/frontend/src/components/agent-status-bar.tsx b/frontend/src/components/controls/agent-status-bar.tsx similarity index 96% rename from frontend/src/components/agent-status-bar.tsx rename to frontend/src/components/controls/agent-status-bar.tsx index f0781abc4564..02212fe91d0e 100644 --- a/frontend/src/components/agent-status-bar.tsx +++ b/frontend/src/components/controls/agent-status-bar.tsx @@ -4,7 +4,7 @@ import { useSelector } from "react-redux"; import toast from "react-hot-toast"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; -import { AGENT_STATUS_MAP } from "./agent-status-map.constant"; +import { AGENT_STATUS_MAP } from "../agent-status-map.constant"; export function AgentStatusBar() { const { t, i18n } = useTranslation(); diff --git a/frontend/src/components/controls.tsx b/frontend/src/components/controls/controls.tsx similarity index 95% rename from frontend/src/components/controls.tsx rename to frontend/src/components/controls/controls.tsx index 424922b3a42c..d7c3fc7673e1 100644 --- a/frontend/src/components/controls.tsx +++ b/frontend/src/components/controls/controls.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useSelector } from "react-redux"; import { AgentControlBar } from "./agent-control-bar"; import { AgentStatusBar } from "./agent-status-bar"; -import { ProjectMenuCard } from "./project-menu/ProjectMenuCard"; +import { ProjectMenuCard } from "../project-menu/ProjectMenuCard"; import { useAuth } from "#/context/auth-context"; import { RootState } from "#/store"; import { SecurityLock } from "./security-lock"; diff --git a/frontend/src/components/security-lock.tsx b/frontend/src/components/controls/security-lock.tsx similarity index 100% rename from frontend/src/components/security-lock.tsx rename to frontend/src/components/controls/security-lock.tsx diff --git a/frontend/src/routes/_oh.app._index/code-editor-component.tsx b/frontend/src/components/editor/code-editor-component.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/code-editor-component.tsx rename to frontend/src/components/editor/code-editor-component.tsx diff --git a/frontend/src/components/editor-actions.tsx b/frontend/src/components/editor/editor-actions.tsx similarity index 90% rename from frontend/src/components/editor-actions.tsx rename to frontend/src/components/editor/editor-actions.tsx index c20c22dea2b0..9143e0796585 100644 --- a/frontend/src/components/editor-actions.tsx +++ b/frontend/src/components/editor/editor-actions.tsx @@ -1,4 +1,4 @@ -import { EditorActionButton } from "./buttons/editor-action-button"; +import { EditorActionButton } from "../buttons/editor-action-button"; interface EditorActionsProps { onSave: () => void; diff --git a/frontend/src/routes/_oh/modals/exit-project-confirmation-modal.tsx b/frontend/src/components/exit-project-confirmation-modal.tsx similarity index 100% rename from frontend/src/routes/_oh/modals/exit-project-confirmation-modal.tsx rename to frontend/src/components/exit-project-confirmation-modal.tsx diff --git a/frontend/src/components/feedback-actions.tsx b/frontend/src/components/feedback/feedback-actions.tsx similarity index 90% rename from frontend/src/components/feedback-actions.tsx rename to frontend/src/components/feedback/feedback-actions.tsx index c15ee89bbb64..3fdaea0b40de 100644 --- a/frontend/src/components/feedback-actions.tsx +++ b/frontend/src/components/feedback/feedback-actions.tsx @@ -1,6 +1,6 @@ import ThumbsUpIcon from "#/icons/thumbs-up.svg?react"; import ThumbDownIcon from "#/icons/thumbs-down.svg?react"; -import { FeedbackActionButton } from "./buttons/feedback-action-button"; +import { FeedbackActionButton } from "../buttons/feedback-action-button"; interface FeedbackActionsProps { onPositiveFeedback: () => void; diff --git a/frontend/src/components/feedback-form.tsx b/frontend/src/components/feedback/feedback-form.tsx similarity index 98% rename from frontend/src/components/feedback-form.tsx rename to frontend/src/components/feedback/feedback-form.tsx index a57517e9ca31..5a96b19f7265 100644 --- a/frontend/src/components/feedback-form.tsx +++ b/frontend/src/components/feedback/feedback-form.tsx @@ -1,6 +1,6 @@ import React from "react"; import hotToast from "react-hot-toast"; -import { ModalButton } from "./buttons/modal-button"; +import { ModalButton } from "../buttons/modal-button"; import { Feedback } from "#/api/open-hands.types"; import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback"; diff --git a/frontend/src/components/feedback-modal.tsx b/frontend/src/components/feedback/feedback-modal.tsx similarity index 82% rename from frontend/src/components/feedback-modal.tsx rename to frontend/src/components/feedback/feedback-modal.tsx index 6cc0f8fbdd8a..e4fbe60ff24a 100644 --- a/frontend/src/components/feedback-modal.tsx +++ b/frontend/src/components/feedback/feedback-modal.tsx @@ -2,9 +2,9 @@ import { FeedbackForm } from "./feedback-form"; import { BaseModalTitle, BaseModalDescription, -} from "./modals/confirmation-modals/base-modal"; -import { ModalBackdrop } from "./modals/modal-backdrop"; -import { ModalBody } from "./modals/modal-body"; +} from "../modals/confirmation-modals/base-modal"; +import { ModalBackdrop } from "../modals/modal-backdrop"; +import { ModalBody } from "../modals/modal-body"; interface FeedbackModalProps { onClose: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/dropzone.tsx b/frontend/src/components/file-explorer/dropzone.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/file-explorer/dropzone.tsx rename to frontend/src/components/file-explorer/dropzone.tsx diff --git a/frontend/src/components/explorer-tree.tsx b/frontend/src/components/file-explorer/explorer-tree.tsx similarity index 100% rename from frontend/src/components/explorer-tree.tsx rename to frontend/src/components/file-explorer/explorer-tree.tsx diff --git a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer-actions.tsx b/frontend/src/components/file-explorer/file-explorer-actions.tsx similarity index 75% rename from frontend/src/routes/_oh.app._index/file-explorer/file-explorer-actions.tsx rename to frontend/src/components/file-explorer/file-explorer-actions.tsx index 7fb9552ba2f3..ccf8f12a7d8d 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer-actions.tsx +++ b/frontend/src/components/file-explorer/file-explorer-actions.tsx @@ -1,7 +1,7 @@ import { cn } from "#/utils/utils"; -import { RefreshIconButton } from "./buttons/refresh-icon-button"; -import { ToggleWorkspaceIconButton } from "./buttons/toggle-workspace-icon-button"; -import { UploadIconButton } from "./buttons/upload-icon-button"; +import { RefreshIconButton } from "../buttons/refresh-icon-button"; +import { ToggleWorkspaceIconButton } from "../buttons/toggle-workspace-icon-button"; +import { UploadIconButton } from "../buttons/upload-icon-button"; interface ExplorerActionsProps { onRefresh: () => void; diff --git a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer-header.tsx b/frontend/src/components/file-explorer/file-explorer-header.tsx similarity index 100% rename from frontend/src/routes/_oh.app._index/file-explorer/file-explorer-header.tsx rename to frontend/src/components/file-explorer/file-explorer-header.tsx diff --git a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx b/frontend/src/components/file-explorer/file-explorer.tsx similarity index 97% rename from frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx rename to frontend/src/components/file-explorer/file-explorer.tsx index cb6354fbe10a..57eaf7b0cf36 100644 --- a/frontend/src/routes/_oh.app._index/file-explorer/file-explorer.tsx +++ b/frontend/src/components/file-explorer/file-explorer.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; import AgentState from "#/types/agent-state"; -import { ExplorerTree } from "#/components/explorer-tree"; +import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; import toast from "#/utils/toast"; import { RootState } from "#/store"; import { I18nKey } from "#/i18n/declaration"; @@ -10,10 +10,10 @@ import { useListFiles } from "#/hooks/query/use-list-files"; import { FileUploadSuccessResponse } from "#/api/open-hands.types"; import { useUploadFiles } from "#/hooks/mutation/use-upload-files"; import { cn } from "#/utils/utils"; -import { OpenVSCodeButton } from "./buttons/open-vscode-button"; import { Dropzone } from "./dropzone"; import { FileExplorerHeader } from "./file-explorer-header"; import { useVSCodeUrl } from "#/hooks/query/use-vscode-url"; +import { OpenVSCodeButton } from "../buttons/open-vscode-button"; interface FileExplorerProps { isOpen: boolean; diff --git a/frontend/src/components/file-icons.tsx b/frontend/src/components/file-explorer/file-icon.tsx similarity index 80% rename from frontend/src/components/file-icons.tsx rename to frontend/src/components/file-explorer/file-icon.tsx index 643ac0405ca3..5413aa323008 100644 --- a/frontend/src/components/file-icons.tsx +++ b/frontend/src/components/file-explorer/file-icon.tsx @@ -1,6 +1,6 @@ import { FaFile } from "react-icons/fa"; import { getExtension } from "#/utils/utils"; -import { EXTENSION_ICON_MAP } from "./extension-icon-map.constant"; +import { EXTENSION_ICON_MAP } from "../extension-icon-map.constant"; interface FileIconProps { filename: string; diff --git a/frontend/src/components/folder-icon.tsx b/frontend/src/components/file-explorer/folder-icon.tsx similarity index 100% rename from frontend/src/components/folder-icon.tsx rename to frontend/src/components/file-explorer/folder-icon.tsx diff --git a/frontend/src/components/title.tsx b/frontend/src/components/file-explorer/title.tsx similarity index 94% rename from frontend/src/components/title.tsx rename to frontend/src/components/file-explorer/title.tsx index e0971f878115..4206eaee4bbc 100644 --- a/frontend/src/components/title.tsx +++ b/frontend/src/components/file-explorer/title.tsx @@ -1,5 +1,5 @@ import { FolderIcon } from "./folder-icon"; -import { FileIcon } from "./file-icons"; +import { FileIcon } from "./file-icon"; interface TitleProps { name: string; diff --git a/frontend/src/components/tree-node.tsx b/frontend/src/components/file-explorer/tree-node.tsx similarity index 100% rename from frontend/src/components/tree-node.tsx rename to frontend/src/components/file-explorer/tree-node.tsx diff --git a/frontend/src/routes/_oh._index/github-repo-selector.tsx b/frontend/src/components/github/github-repo-selector.tsx similarity index 100% rename from frontend/src/routes/_oh._index/github-repo-selector.tsx rename to frontend/src/components/github/github-repo-selector.tsx diff --git a/frontend/src/components/github-repositories-suggestion-box.tsx b/frontend/src/components/github/github-repositories-suggestion-box.tsx similarity index 84% rename from frontend/src/components/github-repositories-suggestion-box.tsx rename to frontend/src/components/github/github-repositories-suggestion-box.tsx index 98494e9774ea..9a95e49a77e2 100644 --- a/frontend/src/components/github-repositories-suggestion-box.tsx +++ b/frontend/src/components/github/github-repositories-suggestion-box.tsx @@ -1,11 +1,11 @@ import React from "react"; import { isGitHubErrorReponse } from "#/api/github"; -import { SuggestionBox } from "#/routes/_oh._index/suggestion-box"; -import { ConnectToGitHubModal } from "./modals/connect-to-github-modal"; -import { ModalBackdrop } from "./modals/modal-backdrop"; -import { GitHubRepositorySelector } from "#/routes/_oh._index/github-repo-selector"; -import { ModalButton } from "./buttons/modal-button"; +import { SuggestionBox } from "#/components/suggestions/suggestion-box"; +import { ConnectToGitHubModal } from "../modals/connect-to-github-modal"; +import { ModalBackdrop } from "../modals/modal-backdrop"; +import { ModalButton } from "../buttons/modal-button"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; +import { GitHubRepositorySelector } from "./github-repo-selector"; interface GitHubRepositoriesSuggestionBoxProps { handleSubmit: () => void; diff --git a/frontend/src/components/attach-image-label.tsx b/frontend/src/components/images/attach-image-label.tsx similarity index 100% rename from frontend/src/components/attach-image-label.tsx rename to frontend/src/components/images/attach-image-label.tsx diff --git a/frontend/src/components/image-carousel.tsx b/frontend/src/components/images/image-carousel.tsx similarity index 100% rename from frontend/src/components/image-carousel.tsx rename to frontend/src/components/images/image-carousel.tsx diff --git a/frontend/src/components/image-preview.tsx b/frontend/src/components/images/image-preview.tsx similarity index 88% rename from frontend/src/components/image-preview.tsx rename to frontend/src/components/images/image-preview.tsx index 4e70bc4dc4de..54e55e1fdcf0 100644 --- a/frontend/src/components/image-preview.tsx +++ b/frontend/src/components/images/image-preview.tsx @@ -1,4 +1,4 @@ -import { RemoveButton } from "./buttons/remove-button"; +import { RemoveButton } from "../buttons/remove-button"; import { Thumbnail } from "./thumbnail"; interface ImagePreviewProps { diff --git a/frontend/src/components/thumbnail.tsx b/frontend/src/components/images/thumbnail.tsx similarity index 100% rename from frontend/src/components/thumbnail.tsx rename to frontend/src/components/images/thumbnail.tsx diff --git a/frontend/src/components/upload-image-input.tsx b/frontend/src/components/images/upload-image-input.tsx similarity index 100% rename from frontend/src/components/upload-image-input.tsx rename to frontend/src/components/images/upload-image-input.tsx diff --git a/frontend/src/components/jupyter-scroll-to-bottom-button.tsx b/frontend/src/components/jupyter-scroll-to-bottom-button.tsx deleted file mode 100644 index 036cf5270b5d..000000000000 --- a/frontend/src/components/jupyter-scroll-to-bottom-button.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { VscArrowDown } from "react-icons/vsc"; -import { I18nKey } from "#/i18n/declaration"; - -interface ScrollToBottomButtonProps { - onClick: () => void; -} - -export function ScrollToBottomButton({ onClick }: ScrollToBottomButtonProps) { - const { t } = useTranslation(); - - return ( - - ); -} diff --git a/frontend/src/components/jupyter-cell-input.tsx b/frontend/src/components/jupyter/jupyter-cell-input.tsx similarity index 100% rename from frontend/src/components/jupyter-cell-input.tsx rename to frontend/src/components/jupyter/jupyter-cell-input.tsx diff --git a/frontend/src/components/jupyter-cell-output.tsx b/frontend/src/components/jupyter/jupyter-cell-output.tsx similarity index 100% rename from frontend/src/components/jupyter-cell-output.tsx rename to frontend/src/components/jupyter/jupyter-cell-output.tsx diff --git a/frontend/src/components/jupyter-cell.tsx b/frontend/src/components/jupyter/jupyter-cell.tsx similarity index 100% rename from frontend/src/components/jupyter-cell.tsx rename to frontend/src/components/jupyter/jupyter-cell.tsx diff --git a/frontend/src/components/jupyter.tsx b/frontend/src/components/jupyter/jupyter.tsx similarity index 93% rename from frontend/src/components/jupyter.tsx rename to frontend/src/components/jupyter/jupyter.tsx index 24bb54ace28d..7fcc4d3e3145 100644 --- a/frontend/src/components/jupyter.tsx +++ b/frontend/src/components/jupyter/jupyter.tsx @@ -3,7 +3,7 @@ import { useSelector } from "react-redux"; import { RootState } from "#/store"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; import { JupyterCell } from "./jupyter-cell"; -import { ScrollToBottomButton } from "./jupyter-scroll-to-bottom-button"; +import { ScrollToBottomButton } from "../buttons/scroll-to-bottom-button"; interface JupyterEditorProps { maxWidth: number; diff --git a/frontend/src/components/beta-badge.tsx b/frontend/src/components/layout/beta-badge.tsx similarity index 100% rename from frontend/src/components/beta-badge.tsx rename to frontend/src/components/layout/beta-badge.tsx diff --git a/frontend/src/components/container.tsx b/frontend/src/components/layout/container.tsx similarity index 100% rename from frontend/src/components/container.tsx rename to frontend/src/components/layout/container.tsx diff --git a/frontend/src/components/nav-tab.tsx b/frontend/src/components/layout/nav-tab.tsx similarity index 100% rename from frontend/src/components/nav-tab.tsx rename to frontend/src/components/layout/nav-tab.tsx diff --git a/frontend/src/components/modals/account-settings-form.tsx b/frontend/src/components/modals/account-settings-form.tsx index 5f1cf87445c9..e11d82f1ecce 100644 --- a/frontend/src/components/modals/account-settings-form.tsx +++ b/frontend/src/components/modals/account-settings-form.tsx @@ -6,8 +6,8 @@ import { } from "./confirmation-modals/base-modal"; import { ModalBody } from "./modal-body"; import { ModalButton } from "../buttons/modal-button"; -import { FormFieldset } from "../form-fieldset"; -import { CustomInput } from "../custom-input"; +import { FormFieldset } from "../ui/form-fieldset"; +import { CustomInput } from "../ui/custom-input"; import { AvailableLanguages } from "#/i18n"; import { I18nKey } from "#/i18n/declaration"; import { useAuth } from "#/context/auth-context"; diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/modals/connect-to-github-modal.tsx index 34c8607a3264..84116d56bb0a 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/modals/connect-to-github-modal.tsx @@ -1,6 +1,6 @@ import { useTranslation } from "react-i18next"; import { ModalBody } from "./modal-body"; -import { CustomInput } from "../custom-input"; +import { CustomInput } from "../ui/custom-input"; import { ModalButton } from "../buttons/modal-button"; import { BaseModalDescription, diff --git a/frontend/src/routes/_oh/modals/settings-modal.tsx b/frontend/src/components/settings-modal.tsx similarity index 100% rename from frontend/src/routes/_oh/modals/settings-modal.tsx rename to frontend/src/components/settings-modal.tsx diff --git a/frontend/src/components/avatar.tsx b/frontend/src/components/sidebar/avatar.tsx similarity index 100% rename from frontend/src/components/avatar.tsx rename to frontend/src/components/sidebar/avatar.tsx diff --git a/frontend/src/routes/_oh/sidebar.tsx b/frontend/src/components/sidebar/sidebar.tsx similarity index 83% rename from frontend/src/routes/_oh/sidebar.tsx rename to frontend/src/components/sidebar/sidebar.tsx index b02974fa9e13..0655278164a5 100644 --- a/frontend/src/routes/_oh/sidebar.tsx +++ b/frontend/src/components/sidebar/sidebar.tsx @@ -1,18 +1,18 @@ import React from "react"; import { useLocation } from "react-router-dom"; import { LoadingSpinner } from "#/components/modals/loading-project"; -import { UserActions } from "#/components/user-actions"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useGitHubUser } from "#/hooks/query/use-github-user"; import { useIsAuthed } from "#/hooks/query/use-is-authed"; -import { SettingsModal } from "./modals/settings-modal"; -import { ExitProjectConfirmationModal } from "./modals/exit-project-confirmation-modal"; -import { AllHandsLogoButton } from "./buttons/all-hands-logo-button"; -import { SettingsButton } from "./buttons/settings-button"; -import { DocsButton } from "./buttons/docs-button"; -import { ExitProjectButton } from "./buttons/exit-project-button"; -import { AccountSettingsModal } from "./modals/account-settings-modal"; +import { AllHandsLogoButton } from "#/components/buttons/all-hands-logo-button"; +import { DocsButton } from "#/components/buttons/docs-button"; +import { SettingsButton } from "#/components/buttons/settings-button"; +import { AccountSettingsModal } from "#/components/account-settings-modal"; +import { ExitProjectConfirmationModal } from "#/components/exit-project-confirmation-modal"; +import { SettingsModal } from "#/components/settings-modal"; +import { UserActions } from "./user-actions"; +import { ExitProjectButton } from "../buttons/exit-project-button"; export function Sidebar() { const location = useLocation(); diff --git a/frontend/src/components/user-actions.tsx b/frontend/src/components/sidebar/user-actions.tsx similarity index 92% rename from frontend/src/components/user-actions.tsx rename to frontend/src/components/sidebar/user-actions.tsx index c3bfc4bd02e4..359c8fbbb314 100644 --- a/frontend/src/components/user-actions.tsx +++ b/frontend/src/components/sidebar/user-actions.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { AccountSettingsContextMenu } from "./context-menu/account-settings-context-menu"; import { UserAvatar } from "./user-avatar"; +import { AccountSettingsContextMenu } from "../context-menu/account-settings-context-menu"; interface UserActionsProps { onClickAccountSettings: () => void; diff --git a/frontend/src/components/user-avatar.tsx b/frontend/src/components/sidebar/user-avatar.tsx similarity index 93% rename from frontend/src/components/user-avatar.tsx rename to frontend/src/components/sidebar/user-avatar.tsx index 16dbd4206f82..9b1d260a7e79 100644 --- a/frontend/src/components/user-avatar.tsx +++ b/frontend/src/components/sidebar/user-avatar.tsx @@ -1,7 +1,7 @@ -import { LoadingSpinner } from "./modals/loading-project"; import DefaultUserAvatar from "#/icons/default-user.svg?react"; import { cn } from "#/utils/utils"; import { Avatar } from "./avatar"; +import { LoadingSpinner } from "../modals/loading-project"; interface UserAvatarProps { onClick: () => void; diff --git a/frontend/src/routes/_oh._index/import-project-suggestion-box.tsx b/frontend/src/components/suggestions/import-project-suggestion-box.tsx similarity index 100% rename from frontend/src/routes/_oh._index/import-project-suggestion-box.tsx rename to frontend/src/components/suggestions/import-project-suggestion-box.tsx diff --git a/frontend/src/routes/_oh._index/suggestion-box.tsx b/frontend/src/components/suggestions/suggestion-box.tsx similarity index 100% rename from frontend/src/routes/_oh._index/suggestion-box.tsx rename to frontend/src/components/suggestions/suggestion-box.tsx diff --git a/frontend/src/components/suggestion-bubble.tsx b/frontend/src/components/suggestions/suggestion-bubble.tsx similarity index 92% rename from frontend/src/components/suggestion-bubble.tsx rename to frontend/src/components/suggestions/suggestion-bubble.tsx index bcb66f245ff8..6a250c848361 100644 --- a/frontend/src/components/suggestion-bubble.tsx +++ b/frontend/src/components/suggestions/suggestion-bubble.tsx @@ -1,5 +1,5 @@ import Lightbulb from "#/icons/lightbulb.svg?react"; -import { RefreshButton } from "./buttons/refresh-button"; +import { RefreshButton } from "../buttons/refresh-button"; interface SuggestionBubbleProps { suggestion: string; diff --git a/frontend/src/components/suggestion-item.tsx b/frontend/src/components/suggestions/suggestion-item.tsx similarity index 100% rename from frontend/src/components/suggestion-item.tsx rename to frontend/src/components/suggestions/suggestion-item.tsx diff --git a/frontend/src/components/suggestions.tsx b/frontend/src/components/suggestions/suggestions.tsx similarity index 100% rename from frontend/src/components/suggestions.tsx rename to frontend/src/components/suggestions/suggestions.tsx diff --git a/frontend/src/components/terminal.tsx b/frontend/src/components/terminal/terminal.tsx similarity index 100% rename from frontend/src/components/terminal.tsx rename to frontend/src/components/terminal/terminal.tsx diff --git a/frontend/src/components/action-tooltip.tsx b/frontend/src/components/ui/action-tooltip.tsx similarity index 100% rename from frontend/src/components/action-tooltip.tsx rename to frontend/src/components/ui/action-tooltip.tsx diff --git a/frontend/src/components/custom-input.tsx b/frontend/src/components/ui/custom-input.tsx similarity index 100% rename from frontend/src/components/custom-input.tsx rename to frontend/src/components/ui/custom-input.tsx diff --git a/frontend/src/components/error-toast.tsx b/frontend/src/components/ui/error-toast.tsx similarity index 100% rename from frontend/src/components/error-toast.tsx rename to frontend/src/components/ui/error-toast.tsx diff --git a/frontend/src/components/form-fieldset.tsx b/frontend/src/components/ui/form-fieldset.tsx similarity index 100% rename from frontend/src/components/form-fieldset.tsx rename to frontend/src/components/ui/form-fieldset.tsx diff --git a/frontend/src/routes/_oh._index/hero-heading.tsx b/frontend/src/components/ui/hero-heading.tsx similarity index 100% rename from frontend/src/routes/_oh._index/hero-heading.tsx rename to frontend/src/components/ui/hero-heading.tsx diff --git a/frontend/src/routes/_oh.app/loading-spinner.tsx b/frontend/src/components/ui/loading-spinner.tsx similarity index 100% rename from frontend/src/routes/_oh.app/loading-spinner.tsx rename to frontend/src/components/ui/loading-spinner.tsx diff --git a/frontend/src/routes/_oh._index/task-form.tsx b/frontend/src/components/ui/task-form.tsx similarity index 92% rename from frontend/src/routes/_oh._index/task-form.tsx rename to frontend/src/components/ui/task-form.tsx index 99691d1ece00..c231c1bcbb2f 100644 --- a/frontend/src/routes/_oh._index/task-form.tsx +++ b/frontend/src/components/ui/task-form.tsx @@ -8,15 +8,15 @@ import { removeFile, setInitialQuery, } from "#/state/initial-query-slice"; -import { SuggestionBubble } from "#/components/suggestion-bubble"; +import { SuggestionBubble } from "#/components/suggestions/suggestion-bubble"; import { SUGGESTIONS } from "#/utils/suggestions"; import { convertImageToBase64 } from "#/utils/convert-image-to-base-64"; -import { ChatInput } from "#/components/chat-input"; -import { UploadImageInput } from "#/components/upload-image-input"; -import { ImageCarousel } from "#/components/image-carousel"; +import { ChatInput } from "#/components/chat/chat-input"; import { getRandomKey } from "#/utils/get-random-key"; -import { AttachImageLabel } from "#/components/attach-image-label"; import { cn } from "#/utils/utils"; +import { AttachImageLabel } from "../images/attach-image-label"; +import { ImageCarousel } from "../images/image-carousel"; +import { UploadImageInput } from "../images/upload-image-input"; export const TaskForm = React.forwardRef((_, ref) => { const dispatch = useDispatch(); diff --git a/frontend/src/components/join-waitlist-anchor.tsx b/frontend/src/components/waitlist/join-waitlist-anchor.tsx similarity index 100% rename from frontend/src/components/join-waitlist-anchor.tsx rename to frontend/src/components/waitlist/join-waitlist-anchor.tsx diff --git a/frontend/src/components/waitlist-message.tsx b/frontend/src/components/waitlist/waitlist-message.tsx similarity index 100% rename from frontend/src/components/waitlist-message.tsx rename to frontend/src/components/waitlist/waitlist-message.tsx diff --git a/frontend/src/components/waitlist-modal.tsx b/frontend/src/components/waitlist/waitlist-modal.tsx similarity index 86% rename from frontend/src/components/waitlist-modal.tsx rename to frontend/src/components/waitlist/waitlist-modal.tsx index 88e13601e629..a924da5d4641 100644 --- a/frontend/src/components/waitlist-modal.tsx +++ b/frontend/src/components/waitlist/waitlist-modal.tsx @@ -1,8 +1,8 @@ -import { ModalButton } from "./buttons/modal-button"; -import { ModalBackdrop } from "./modals/modal-backdrop"; +import { ModalButton } from "../buttons/modal-button"; +import { ModalBackdrop } from "../modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; -import { ModalBody } from "./modals/modal-body"; +import { ModalBody } from "../modals/modal-body"; import { JoinWaitlistAnchor } from "./join-waitlist-anchor"; import { WaitlistMessage } from "./waitlist-message"; diff --git a/frontend/src/routes/_oh._index/route.tsx b/frontend/src/routes/_oh._index/route.tsx index 3e5db919c0f0..1f2a0631e32a 100644 --- a/frontend/src/routes/_oh._index/route.tsx +++ b/frontend/src/routes/_oh._index/route.tsx @@ -1,17 +1,17 @@ import { useLocation, useNavigate } from "@remix-run/react"; import React from "react"; import { useDispatch } from "react-redux"; -import { TaskForm } from "./task-form"; -import { HeroHeading } from "./hero-heading"; +import { TaskForm } from "../../components/ui/task-form"; +import { HeroHeading } from "../../components/ui/hero-heading"; import { setImportedProjectZip } from "#/state/initial-query-slice"; -import { GitHubRepositoriesSuggestionBox } from "#/components/github-repositories-suggestion-box"; import { convertZipToBase64 } from "#/utils/convert-zip-to-base64"; import { useUserRepositories } from "#/hooks/query/use-user-repositories"; import { useGitHubUser } from "#/hooks/query/use-github-user"; import { useGitHubAuthUrl } from "#/hooks/use-github-auth-url"; import { useConfig } from "#/hooks/query/use-config"; import { useAuth } from "#/context/auth-context"; -import { ImportProjectSuggestionBox } from "./import-project-suggestion-box"; +import { ImportProjectSuggestionBox } from "../../components/suggestions/import-project-suggestion-box"; +import { GitHubRepositoriesSuggestionBox } from "#/components/github/github-repositories-suggestion-box"; function Home() { const { token, gitHubToken } = useAuth(); diff --git a/frontend/src/routes/_oh.app._index/route.tsx b/frontend/src/routes/_oh.app._index/route.tsx index 99f583ecf74e..1f69e93bdd85 100644 --- a/frontend/src/routes/_oh.app._index/route.tsx +++ b/frontend/src/routes/_oh.app._index/route.tsx @@ -5,12 +5,12 @@ import { editor } from "monaco-editor"; import { EditorProps } from "@monaco-editor/react"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; -import { FileExplorer } from "#/routes/_oh.app._index/file-explorer/file-explorer"; -import CodeEditorComponent from "./code-editor-component"; +import CodeEditorComponent from "../../components/editor/code-editor-component"; import { useFiles } from "#/context/files"; -import { EditorActions } from "#/components/editor-actions"; import { useSaveFile } from "#/hooks/mutation/use-save-file"; import { ASSET_FILE_TYPES } from "./constants"; +import { EditorActions } from "#/components/editor/editor-actions"; +import { FileExplorer } from "#/components/file-explorer/file-explorer"; export function ErrorBoundary() { const error = useRouteError(); diff --git a/frontend/src/routes/_oh.app.browser.tsx b/frontend/src/routes/_oh.app.browser.tsx index 54c867e536fb..5a4654ebb345 100644 --- a/frontend/src/routes/_oh.app.browser.tsx +++ b/frontend/src/routes/_oh.app.browser.tsx @@ -1,4 +1,4 @@ -import { BrowserPanel } from "#/components/browser"; +import { BrowserPanel } from "#/components/browser/browser"; function Browser() { return ; diff --git a/frontend/src/routes/_oh.app.jupyter.tsx b/frontend/src/routes/_oh.app.jupyter.tsx index 55f9cba62832..807ee53b6126 100644 --- a/frontend/src/routes/_oh.app.jupyter.tsx +++ b/frontend/src/routes/_oh.app.jupyter.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { JupyterEditor } from "#/components/jupyter"; +import { JupyterEditor } from "#/components/jupyter/jupyter"; function Jupyter() { const parentRef = React.useRef(null); diff --git a/frontend/src/routes/_oh.app/route.tsx b/frontend/src/routes/_oh.app/route.tsx index 7a0458aad3ae..22901a820a60 100644 --- a/frontend/src/routes/_oh.app/route.tsx +++ b/frontend/src/routes/_oh.app/route.tsx @@ -3,9 +3,8 @@ import React from "react"; import { Outlet } from "@remix-run/react"; import { useDispatch, useSelector } from "react-redux"; import Security from "#/components/modals/security/security"; -import { Controls } from "#/components/controls"; +import { Controls } from "#/components/controls/controls"; import { RootState } from "#/store"; -import { Container } from "#/components/container"; import { clearMessages } from "#/state/chat-slice"; import { clearTerminal } from "#/state/command-slice"; import { useEffectOnce } from "#/utils/use-effect-once"; @@ -14,13 +13,14 @@ import GlobeIcon from "#/icons/globe.svg?react"; import ListIcon from "#/icons/list-type-number.svg?react"; import { clearJupyter } from "#/state/jupyter-slice"; import { FilesProvider } from "#/context/files"; -import { ChatInterface } from "./chat-interface"; +import { ChatInterface } from "../../components/chat/chat-interface"; import { WsClientProvider } from "#/context/ws-client-provider"; import { EventHandler } from "./event-handler"; import { useLatestRepoCommit } from "#/hooks/query/use-latest-repo-commit"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useConversationConfig } from "#/hooks/query/use-conversation-config"; +import { Container } from "#/components/layout/container"; function App() { const { token, gitHubToken } = useAuth(); @@ -43,7 +43,7 @@ function App() { ); const Terminal = React.useMemo( - () => React.lazy(() => import("#/components/terminal")), + () => React.lazy(() => import("#/components/terminal/terminal")), [], ); diff --git a/frontend/src/routes/_oh/route.tsx b/frontend/src/routes/_oh/route.tsx index 328c271add97..1cf58367ae1d 100644 --- a/frontend/src/routes/_oh/route.tsx +++ b/frontend/src/routes/_oh/route.tsx @@ -1,14 +1,14 @@ import React from "react"; import { useRouteError, isRouteErrorResponse, Outlet } from "@remix-run/react"; import i18n from "#/i18n"; -import { WaitlistModal } from "#/components/waitlist-modal"; -import { AnalyticsConsentFormModal } from "#/components/analytics-consent-form-modal"; +import { WaitlistModal } from "#/components/waitlist/waitlist-modal"; import { useGitHubAuthUrl } from "#/hooks/use-github-auth-url"; import { useIsAuthed } from "#/hooks/query/use-is-authed"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; -import { Sidebar } from "./sidebar"; import { useConfig } from "#/hooks/query/use-config"; +import { AnalyticsConsentFormModal } from "#/components/analytics/analytics-consent-form-modal"; +import { Sidebar } from "#/components/sidebar/sidebar"; export function ErrorBoundary() { const error = useRouteError(); diff --git a/frontend/src/utils/display-error-toast.tsx b/frontend/src/utils/display-error-toast.tsx index d5952d979cd0..67485eb982c9 100644 --- a/frontend/src/utils/display-error-toast.tsx +++ b/frontend/src/utils/display-error-toast.tsx @@ -1,5 +1,5 @@ import toast from "react-hot-toast"; -import { ErrorToast } from "#/components/error-toast"; +import { ErrorToast } from "#/components/ui/error-toast"; export const displayErrorToast = (error: string) => toast((t) => , { From 7e396013c2948de696c84c2e9fc572542c2ffdbc Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:49:52 +0400 Subject: [PATCH 09/13] Nest features --- frontend/__tests__/components/browser.test.tsx | 2 +- .../__tests__/components/chat-message.test.tsx | 2 +- .../components/chat/chat-input.test.tsx | 2 +- .../components/chat/chat-interface.test.tsx | 2 +- .../account-settings-context-menu.test.tsx | 2 +- .../context-menu/context-menu-list-item.test.tsx | 2 +- .../components/feedback-actions.test.tsx | 2 +- .../__tests__/components/feedback-form.test.tsx | 2 +- .../file-explorer/explorer-tree.test.tsx | 2 +- .../file-explorer/file-explorer.test.tsx | 2 +- .../components/file-explorer/tree-node.test.tsx | 2 +- .../__tests__/components/image-preview.test.tsx | 2 +- .../components/interactive-chat-box.test.tsx | 2 +- .../components/suggestion-item.test.tsx | 2 +- .../__tests__/components/suggestions.test.tsx | 2 +- .../components/terminal/terminal.test.tsx | 2 +- .../components/upload-image-input.test.tsx | 2 +- .../__tests__/components/user-actions.test.tsx | 2 +- .../__tests__/components/user-avatar.test.tsx | 2 +- .../src/components/account-settings-form.tsx | 2 +- .../src/components/connect-to-github-modal.tsx | 2 +- .../analytics/analytics-consent-form-modal.tsx | 8 ++++---- .../{ => features}/browser/browser-snapshot.tsx | 0 .../{ => features}/browser/browser.tsx | 0 .../browser/empty-browser-message.tsx | 0 .../{ => features}/chat/action-suggestions.tsx | 2 +- .../{ => features}/chat/chat-input.tsx | 4 ++-- .../{ => features}/chat/chat-interface.tsx | 6 +++--- .../{ => features}/chat/chat-message.tsx | 2 +- .../{ => features}/chat/chat-suggestions.tsx | 2 +- .../{ => features}/chat/error-message.tsx | 0 .../{ => features}/chat/interactive-chat-box.tsx | 0 .../components/{ => features}/chat/messages.tsx | 4 ++-- .../{ => features}/chat/typing-indicator.tsx | 0 .../account-settings-context-menu.tsx | 0 .../context-menu/context-menu-list-item.tsx | 0 .../context-menu/context-menu-separator.tsx | 0 .../{ => features}/context-menu/context-menu.tsx | 0 .../controls/agent-control-bar.tsx | 2 +- .../{ => features}/controls/agent-status-bar.tsx | 2 +- .../{ => features}/controls/controls.tsx | 0 .../{ => features}/controls/security-lock.tsx | 0 .../editor/code-editor-component.tsx | 0 .../{ => features}/editor/editor-actions.tsx | 2 +- .../{ => features}/feedback/feedback-actions.tsx | 2 +- .../{ => features}/feedback/feedback-form.tsx | 2 +- .../{ => features}/feedback/feedback-modal.tsx | 6 +++--- .../{ => features}/file-explorer/dropzone.tsx | 0 .../file-explorer/explorer-tree.tsx | 0 .../file-explorer/file-explorer-actions.tsx | 6 +++--- .../file-explorer/file-explorer-header.tsx | 0 .../file-explorer/file-explorer.tsx | 4 ++-- .../{ => features}/file-explorer/file-icon.tsx | 2 +- .../file-explorer/filename.tsx} | 4 ++-- .../{ => features}/file-explorer/folder-icon.tsx | 0 .../{ => features}/file-explorer/tree-node.tsx | 4 ++-- .../github/github-repo-selector.tsx | 0 .../github-repositories-suggestion-box.tsx | 8 ++++---- .../{ => features}/images/attach-image-label.tsx | 0 .../{ => features}/images/image-carousel.tsx | 0 .../{ => features}/images/image-preview.tsx | 2 +- .../{ => features}/images/thumbnail.tsx | 0 .../{ => features}/images/upload-image-input.tsx | 0 .../jupyter/jupyter-cell-input.tsx | 0 .../jupyter/jupyter-cell-output.tsx | 0 .../{ => features}/jupyter/jupyter-cell.tsx | 0 .../{ => features}/jupyter/jupyter.tsx | 2 +- .../components/{ => features}/markdown/code.tsx | 0 .../components/{ => features}/markdown/list.tsx | 0 .../project-menu/ProjectMenuCard.tsx | 6 +++--- .../project-menu-details-placeholder.tsx | 0 .../project-menu/project-menu-details.tsx | 0 .../project.menu-card-context-menu.tsx | 0 .../components/{ => features}/sidebar/avatar.tsx | 0 .../{ => features}/sidebar/sidebar.tsx | 8 ++++---- .../{ => features}/sidebar/user-actions.tsx | 0 .../{ => features}/sidebar/user-avatar.tsx | 2 +- .../import-project-suggestion-box.tsx | 0 .../suggestions/suggestion-box.tsx | 0 .../suggestions/suggestion-bubble.tsx | 2 +- .../suggestions/suggestion-item.tsx | 0 .../{ => features}/suggestions/suggestions.tsx | 0 .../{ => features}/terminal/terminal.tsx | 0 .../waitlist/join-waitlist-anchor.tsx | 0 .../{ => features}/waitlist/waitlist-message.tsx | 0 .../{ => features}/waitlist/waitlist-modal.tsx | 2 +- .../components/modals/account-settings-form.tsx | 2 +- .../modals/confirmation-modals/base-modal.tsx | 2 +- .../modals/connect-to-github-modal.tsx | 2 +- frontend/src/components/settings-form.tsx | 16 ++++++++-------- .../{ => ui}/buttons/action-button.tsx | 0 .../{ => ui}/buttons/all-hands-logo-button.tsx | 0 .../{ => ui}/buttons/confirmation-buttons.tsx | 2 +- .../{ => ui}/buttons/continue-button.tsx | 0 .../buttons/copy-to-clipboard-button.tsx | 0 .../components/{ => ui}/buttons/docs-button.tsx | 0 .../{ => ui}/buttons/editor-action-button.tsx | 0 .../{ => ui}/buttons/exit-project-button.tsx | 0 .../{ => ui}/buttons/feedback-action-button.tsx | 0 .../components/{ => ui}/buttons/icon-button.tsx | 0 .../components/{ => ui}/buttons/modal-button.tsx | 0 .../{ => ui}/buttons/open-vscode-button.tsx | 0 .../{ => ui}/buttons/refresh-button.tsx | 0 .../{ => ui}/buttons/refresh-icon-button.tsx | 2 +- .../{ => ui}/buttons/remove-button.tsx | 0 .../{ => ui}/buttons/scroll-to-bottom-button.tsx | 0 .../{ => ui}/buttons/settings-button.tsx | 0 .../components/{ => ui}/buttons/stop-button.tsx | 0 .../{ => ui}/buttons/submit-button.tsx | 0 .../buttons/toggle-workspace-icon-button.tsx | 2 +- .../{ => ui}/buttons/upload-icon-button.tsx | 2 +- .../{ => ui}/inputs/advanced-option-switch.tsx | 0 .../components/{ => ui}/inputs/agent-input.tsx | 0 .../components/{ => ui}/inputs/api-key-input.tsx | 0 .../{ => ui}/inputs/base-url-input.tsx | 0 .../{ => ui}/inputs/confirmation-mode-switch.tsx | 0 .../{ => ui}/inputs/custom-model-input.tsx | 0 .../{ => ui}/inputs/security-analyzers-input.tsx | 0 frontend/src/components/ui/task-form.tsx | 10 +++++----- frontend/src/routes/_oh._index/route.tsx | 4 ++-- frontend/src/routes/_oh.app._index/route.tsx | 6 +++--- frontend/src/routes/_oh.app.browser.tsx | 2 +- frontend/src/routes/_oh.app.jupyter.tsx | 2 +- frontend/src/routes/_oh.app/route.tsx | 6 +++--- frontend/src/routes/_oh/route.tsx | 4 ++-- 125 files changed, 101 insertions(+), 101 deletions(-) rename frontend/src/components/{ => features}/analytics/analytics-consent-form-modal.tsx (87%) rename frontend/src/components/{ => features}/browser/browser-snapshot.tsx (100%) rename frontend/src/components/{ => features}/browser/browser.tsx (100%) rename frontend/src/components/{ => features}/browser/empty-browser-message.tsx (100%) rename frontend/src/components/{ => features}/chat/action-suggestions.tsx (96%) rename frontend/src/components/{ => features}/chat/chat-input.tsx (97%) rename frontend/src/components/{ => features}/chat/chat-interface.tsx (96%) rename frontend/src/components/{ => features}/chat/chat-message.tsx (95%) rename frontend/src/components/{ => features}/chat/chat-suggestions.tsx (92%) rename frontend/src/components/{ => features}/chat/error-message.tsx (100%) rename frontend/src/components/{ => features}/chat/interactive-chat-box.tsx (100%) rename frontend/src/components/{ => features}/chat/messages.tsx (86%) rename frontend/src/components/{ => features}/chat/typing-indicator.tsx (100%) rename frontend/src/components/{ => features}/context-menu/account-settings-context-menu.tsx (100%) rename frontend/src/components/{ => features}/context-menu/context-menu-list-item.tsx (100%) rename frontend/src/components/{ => features}/context-menu/context-menu-separator.tsx (100%) rename frontend/src/components/{ => features}/context-menu/context-menu.tsx (100%) rename frontend/src/components/{ => features}/controls/agent-control-bar.tsx (95%) rename frontend/src/components/{ => features}/controls/agent-status-bar.tsx (96%) rename frontend/src/components/{ => features}/controls/controls.tsx (100%) rename frontend/src/components/{ => features}/controls/security-lock.tsx (100%) rename frontend/src/components/{ => features}/editor/code-editor-component.tsx (100%) rename frontend/src/components/{ => features}/editor/editor-actions.tsx (89%) rename frontend/src/components/{ => features}/feedback/feedback-actions.tsx (90%) rename frontend/src/components/{ => features}/feedback/feedback-form.tsx (98%) rename frontend/src/components/{ => features}/feedback/feedback-modal.tsx (81%) rename frontend/src/components/{ => features}/file-explorer/dropzone.tsx (100%) rename frontend/src/components/{ => features}/file-explorer/explorer-tree.tsx (100%) rename frontend/src/components/{ => features}/file-explorer/file-explorer-actions.tsx (74%) rename frontend/src/components/{ => features}/file-explorer/file-explorer-header.tsx (100%) rename frontend/src/components/{ => features}/file-explorer/file-explorer.tsx (96%) rename frontend/src/components/{ => features}/file-explorer/file-icon.tsx (80%) rename frontend/src/components/{file-explorer/title.tsx => features/file-explorer/filename.tsx} (86%) rename frontend/src/components/{ => features}/file-explorer/folder-icon.tsx (100%) rename frontend/src/components/{ => features}/file-explorer/tree-node.tsx (97%) rename frontend/src/components/{ => features}/github/github-repo-selector.tsx (100%) rename frontend/src/components/{ => features}/github/github-repositories-suggestion-box.tsx (87%) rename frontend/src/components/{ => features}/images/attach-image-label.tsx (100%) rename frontend/src/components/{ => features}/images/image-carousel.tsx (100%) rename frontend/src/components/{ => features}/images/image-preview.tsx (87%) rename frontend/src/components/{ => features}/images/thumbnail.tsx (100%) rename frontend/src/components/{ => features}/images/upload-image-input.tsx (100%) rename frontend/src/components/{ => features}/jupyter/jupyter-cell-input.tsx (100%) rename frontend/src/components/{ => features}/jupyter/jupyter-cell-output.tsx (100%) rename frontend/src/components/{ => features}/jupyter/jupyter-cell.tsx (100%) rename frontend/src/components/{ => features}/jupyter/jupyter.tsx (93%) rename frontend/src/components/{ => features}/markdown/code.tsx (100%) rename frontend/src/components/{ => features}/markdown/list.tsx (100%) rename frontend/src/components/{ => features}/project-menu/ProjectMenuCard.tsx (94%) rename frontend/src/components/{ => features}/project-menu/project-menu-details-placeholder.tsx (100%) rename frontend/src/components/{ => features}/project-menu/project-menu-details.tsx (100%) rename frontend/src/components/{ => features}/project-menu/project.menu-card-context-menu.tsx (100%) rename frontend/src/components/{ => features}/sidebar/avatar.tsx (100%) rename frontend/src/components/{ => features}/sidebar/sidebar.tsx (91%) rename frontend/src/components/{ => features}/sidebar/user-actions.tsx (100%) rename frontend/src/components/{ => features}/sidebar/user-avatar.tsx (93%) rename frontend/src/components/{ => features}/suggestions/import-project-suggestion-box.tsx (100%) rename frontend/src/components/{ => features}/suggestions/suggestion-box.tsx (100%) rename frontend/src/components/{ => features}/suggestions/suggestion-bubble.tsx (92%) rename frontend/src/components/{ => features}/suggestions/suggestion-item.tsx (100%) rename frontend/src/components/{ => features}/suggestions/suggestions.tsx (100%) rename frontend/src/components/{ => features}/terminal/terminal.tsx (100%) rename frontend/src/components/{ => features}/waitlist/join-waitlist-anchor.tsx (100%) rename frontend/src/components/{ => features}/waitlist/waitlist-message.tsx (100%) rename frontend/src/components/{ => features}/waitlist/waitlist-modal.tsx (95%) rename frontend/src/components/{ => ui}/buttons/action-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/all-hands-logo-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/confirmation-buttons.tsx (94%) rename frontend/src/components/{ => ui}/buttons/continue-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/copy-to-clipboard-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/docs-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/editor-action-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/exit-project-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/feedback-action-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/icon-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/modal-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/open-vscode-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/refresh-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/refresh-icon-button.tsx (87%) rename frontend/src/components/{ => ui}/buttons/remove-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/scroll-to-bottom-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/settings-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/stop-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/submit-button.tsx (100%) rename frontend/src/components/{ => ui}/buttons/toggle-workspace-icon-button.tsx (91%) rename frontend/src/components/{ => ui}/buttons/upload-icon-button.tsx (87%) rename frontend/src/components/{ => ui}/inputs/advanced-option-switch.tsx (100%) rename frontend/src/components/{ => ui}/inputs/agent-input.tsx (100%) rename frontend/src/components/{ => ui}/inputs/api-key-input.tsx (100%) rename frontend/src/components/{ => ui}/inputs/base-url-input.tsx (100%) rename frontend/src/components/{ => ui}/inputs/confirmation-mode-switch.tsx (100%) rename frontend/src/components/{ => ui}/inputs/custom-model-input.tsx (100%) rename frontend/src/components/{ => ui}/inputs/security-analyzers-input.tsx (100%) diff --git a/frontend/__tests__/components/browser.test.tsx b/frontend/__tests__/components/browser.test.tsx index e246f06c15a9..9b9f0fa3ba47 100644 --- a/frontend/__tests__/components/browser.test.tsx +++ b/frontend/__tests__/components/browser.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { describe, it, expect } from "vitest"; import { renderWithProviders } from "../../test-utils"; -import { BrowserPanel } from "#/components/browser/browser"; +import { BrowserPanel } from "#/components/features/browser/browser"; describe("Browser", () => { it("renders a message if no screenshotSrc is provided", () => { diff --git a/frontend/__tests__/components/chat-message.test.tsx b/frontend/__tests__/components/chat-message.test.tsx index c729ce1a15f3..9b3156ee54fe 100644 --- a/frontend/__tests__/components/chat-message.test.tsx +++ b/frontend/__tests__/components/chat-message.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, it, expect, test } from "vitest"; -import { ChatMessage } from "#/components/chat/chat-message"; +import { ChatMessage } from "#/components/features/chat/chat-message"; describe("ChatMessage", () => { it("should render a user message", () => { diff --git a/frontend/__tests__/components/chat/chat-input.test.tsx b/frontend/__tests__/components/chat/chat-input.test.tsx index f0cc9ba1fca9..51cbe4df6674 100644 --- a/frontend/__tests__/components/chat/chat-input.test.tsx +++ b/frontend/__tests__/components/chat/chat-input.test.tsx @@ -1,7 +1,7 @@ import userEvent from "@testing-library/user-event"; import { fireEvent, render, screen } from "@testing-library/react"; import { describe, afterEach, vi, it, expect } from "vitest"; -import { ChatInput } from "#/components/chat/chat-input"; +import { ChatInput } from "#/components/features/chat/chat-input"; describe("ChatInput", () => { const onSubmitMock = vi.fn(); diff --git a/frontend/__tests__/components/chat/chat-interface.test.tsx b/frontend/__tests__/components/chat/chat-interface.test.tsx index b99ea15b6d6c..e3e35a209f29 100644 --- a/frontend/__tests__/components/chat/chat-interface.test.tsx +++ b/frontend/__tests__/components/chat/chat-interface.test.tsx @@ -6,7 +6,7 @@ import { addUserMessage } from "#/state/chat-slice"; import { SUGGESTIONS } from "#/utils/suggestions"; import * as ChatSlice from "#/state/chat-slice"; import { WsClientProviderStatus } from "#/context/ws-client-provider"; -import { ChatInterface } from "#/components/chat/chat-interface"; +import { ChatInterface } from "#/components/features/chat/chat-interface"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const renderChatInterface = (messages: (Message | ErrorMessage)[]) => diff --git a/frontend/__tests__/components/context-menu/account-settings-context-menu.test.tsx b/frontend/__tests__/components/context-menu/account-settings-context-menu.test.tsx index 57c2aea3724d..ad5b6a0a3443 100644 --- a/frontend/__tests__/components/context-menu/account-settings-context-menu.test.tsx +++ b/frontend/__tests__/components/context-menu/account-settings-context-menu.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, test, vi } from "vitest"; -import { AccountSettingsContextMenu } from "#/components/context-menu/account-settings-context-menu"; +import { AccountSettingsContextMenu } from "#/components/features/context-menu/account-settings-context-menu"; describe("AccountSettingsContextMenu", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/context-menu/context-menu-list-item.test.tsx b/frontend/__tests__/components/context-menu/context-menu-list-item.test.tsx index 9f72aada2a24..55e19e099228 100644 --- a/frontend/__tests__/components/context-menu/context-menu-list-item.test.tsx +++ b/frontend/__tests__/components/context-menu/context-menu-list-item.test.tsx @@ -1,7 +1,7 @@ import { describe, it, expect, vi } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { ContextMenuListItem } from "#/components/context-menu/context-menu-list-item"; +import { ContextMenuListItem } from "#/components/features/context-menu/context-menu-list-item"; describe("ContextMenuListItem", () => { it("should render the component with the children", () => { diff --git a/frontend/__tests__/components/feedback-actions.test.tsx b/frontend/__tests__/components/feedback-actions.test.tsx index d96747f2b996..c4f8170eea33 100644 --- a/frontend/__tests__/components/feedback-actions.test.tsx +++ b/frontend/__tests__/components/feedback-actions.test.tsx @@ -1,7 +1,7 @@ import { render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { FeedbackActions } from "#/components/feedback/feedback-actions"; +import { FeedbackActions } from "#/components/features/feedback/feedback-actions"; describe("FeedbackActions", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/feedback-form.test.tsx b/frontend/__tests__/components/feedback-form.test.tsx index b42b2744befe..19d49737faa9 100644 --- a/frontend/__tests__/components/feedback-form.test.tsx +++ b/frontend/__tests__/components/feedback-form.test.tsx @@ -2,7 +2,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; import { renderWithProviders } from "test-utils"; -import { FeedbackForm } from "#/components/feedback/feedback-form"; +import { FeedbackForm } from "#/components/features/feedback/feedback-form"; describe("FeedbackForm", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx index 8237133597c0..84c1e911ac28 100644 --- a/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx +++ b/frontend/__tests__/components/file-explorer/explorer-tree.test.tsx @@ -1,7 +1,7 @@ import { screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { describe, afterEach, vi, it, expect } from "vitest"; -import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; +import { ExplorerTree } from "#/components/features/file-explorer/explorer-tree"; const FILES = ["file-1-1.ts", "folder-1-2"]; diff --git a/frontend/__tests__/components/file-explorer/file-explorer.test.tsx b/frontend/__tests__/components/file-explorer/file-explorer.test.tsx index a9e90294c8d3..5a68fa67876e 100644 --- a/frontend/__tests__/components/file-explorer/file-explorer.test.tsx +++ b/frontend/__tests__/components/file-explorer/file-explorer.test.tsx @@ -5,7 +5,7 @@ import { describe, it, expect, vi, Mock, afterEach } from "vitest"; import toast from "#/utils/toast"; import AgentState from "#/types/agent-state"; import OpenHands from "#/api/open-hands"; -import { FileExplorer } from "#/components/file-explorer/file-explorer"; +import { FileExplorer } from "#/components/features/file-explorer/file-explorer"; const toastSpy = vi.spyOn(toast, "error"); const uploadFilesSpy = vi.spyOn(OpenHands, "uploadFiles"); diff --git a/frontend/__tests__/components/file-explorer/tree-node.test.tsx b/frontend/__tests__/components/file-explorer/tree-node.test.tsx index ebd8c029d433..5756df921d2e 100644 --- a/frontend/__tests__/components/file-explorer/tree-node.test.tsx +++ b/frontend/__tests__/components/file-explorer/tree-node.test.tsx @@ -2,7 +2,7 @@ import { screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { renderWithProviders } from "test-utils"; import { vi, describe, afterEach, it, expect } from "vitest"; -import TreeNode from "#/components/file-explorer/tree-node"; +import TreeNode from "#/components/features/file-explorer/tree-node"; import OpenHands from "#/api/open-hands"; const getFileSpy = vi.spyOn(OpenHands, "getFile"); diff --git a/frontend/__tests__/components/image-preview.test.tsx b/frontend/__tests__/components/image-preview.test.tsx index a50675ad2e7e..39d2f089fb9b 100644 --- a/frontend/__tests__/components/image-preview.test.tsx +++ b/frontend/__tests__/components/image-preview.test.tsx @@ -1,4 +1,4 @@ -import { ImagePreview } from "#/components/images/image-preview"; +import { ImagePreview } from "#/components/features/images/image-preview"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, expect, it, vi } from "vitest"; diff --git a/frontend/__tests__/components/interactive-chat-box.test.tsx b/frontend/__tests__/components/interactive-chat-box.test.tsx index 8fdc13012d79..fa0d3a1b8e30 100644 --- a/frontend/__tests__/components/interactive-chat-box.test.tsx +++ b/frontend/__tests__/components/interactive-chat-box.test.tsx @@ -1,7 +1,7 @@ import { render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; -import { InteractiveChatBox } from "#/components/chat/interactive-chat-box"; +import { InteractiveChatBox } from "#/components/features/chat/interactive-chat-box"; describe("InteractiveChatBox", () => { const onSubmitMock = vi.fn(); diff --git a/frontend/__tests__/components/suggestion-item.test.tsx b/frontend/__tests__/components/suggestion-item.test.tsx index 932ba7fd23e8..23d2aaa41e5b 100644 --- a/frontend/__tests__/components/suggestion-item.test.tsx +++ b/frontend/__tests__/components/suggestion-item.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { SuggestionItem } from "#/components/suggestions/suggestion-item"; +import { SuggestionItem } from "#/components/features/suggestions/suggestion-item"; describe("SuggestionItem", () => { const suggestionItem = { label: "suggestion1", value: "a long text value" }; diff --git a/frontend/__tests__/components/suggestions.test.tsx b/frontend/__tests__/components/suggestions.test.tsx index 8bf715641dc9..33290819c3bc 100644 --- a/frontend/__tests__/components/suggestions.test.tsx +++ b/frontend/__tests__/components/suggestions.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { Suggestions } from "#/components/suggestions/suggestions"; +import { Suggestions } from "#/components/features/suggestions/suggestions"; describe("Suggestions", () => { const firstSuggestion = { diff --git a/frontend/__tests__/components/terminal/terminal.test.tsx b/frontend/__tests__/components/terminal/terminal.test.tsx index d660f83639a0..055aa4433c96 100644 --- a/frontend/__tests__/components/terminal/terminal.test.tsx +++ b/frontend/__tests__/components/terminal/terminal.test.tsx @@ -2,7 +2,7 @@ import { act, screen } from "@testing-library/react"; import { renderWithProviders } from "test-utils"; import { vi, describe, afterEach, it, expect } from "vitest"; import { Command, appendInput, appendOutput } from "#/state/command-slice"; -import Terminal from "#/components/terminal/terminal"; +import Terminal from "#/components/features/terminal/terminal"; global.ResizeObserver = vi.fn().mockImplementation(() => ({ observe: vi.fn(), diff --git a/frontend/__tests__/components/upload-image-input.test.tsx b/frontend/__tests__/components/upload-image-input.test.tsx index 3b2d272edc9a..e95b80c9697b 100644 --- a/frontend/__tests__/components/upload-image-input.test.tsx +++ b/frontend/__tests__/components/upload-image-input.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { UploadImageInput } from "#/components/images/upload-image-input"; +import { UploadImageInput } from "#/components/features/images/upload-image-input"; describe("UploadImageInput", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/user-actions.test.tsx b/frontend/__tests__/components/user-actions.test.tsx index c16da1eb8ab5..a83b88a38923 100644 --- a/frontend/__tests__/components/user-actions.test.tsx +++ b/frontend/__tests__/components/user-actions.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import { describe, expect, it, test, vi, afterEach } from "vitest"; import userEvent from "@testing-library/user-event"; -import { UserActions } from "#/components/sidebar/user-actions"; +import { UserActions } from "#/components/features/sidebar/user-actions"; describe("UserActions", () => { const user = userEvent.setup(); diff --git a/frontend/__tests__/components/user-avatar.test.tsx b/frontend/__tests__/components/user-avatar.test.tsx index 2fef1dbf6b14..076eb75b49bf 100644 --- a/frontend/__tests__/components/user-avatar.test.tsx +++ b/frontend/__tests__/components/user-avatar.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { UserAvatar } from "#/components/sidebar/user-avatar"; +import { UserAvatar } from "#/components/features/sidebar/user-avatar"; describe("UserAvatar", () => { const onClickMock = vi.fn(); diff --git a/frontend/src/components/account-settings-form.tsx b/frontend/src/components/account-settings-form.tsx index 6cfe1ea2ef33..aa11558fa50e 100644 --- a/frontend/src/components/account-settings-form.tsx +++ b/frontend/src/components/account-settings-form.tsx @@ -7,7 +7,7 @@ import { useUserPrefs } from "#/context/user-prefs-context"; import { handleCaptureConsent } from "#/utils/handle-capture-consent"; import { CustomInput } from "./ui/custom-input"; import { FormFieldset } from "./ui/form-fieldset"; -import { ModalButton } from "./buttons/modal-button"; +import { ModalButton } from "./ui/buttons/modal-button"; import { ModalBody } from "./modals/modal-body"; import { BaseModalTitle, diff --git a/frontend/src/components/connect-to-github-modal.tsx b/frontend/src/components/connect-to-github-modal.tsx index b145bd0eb69a..74b2ff642823 100644 --- a/frontend/src/components/connect-to-github-modal.tsx +++ b/frontend/src/components/connect-to-github-modal.tsx @@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next"; import { I18nKey } from "#/i18n/declaration"; import { useAuth } from "#/context/auth-context"; import { CustomInput } from "./ui/custom-input"; -import { ModalButton } from "./buttons/modal-button"; +import { ModalButton } from "./ui/buttons/modal-button"; import { ModalBody } from "./modals/modal-body"; import { BaseModalTitle, diff --git a/frontend/src/components/analytics/analytics-consent-form-modal.tsx b/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx similarity index 87% rename from frontend/src/components/analytics/analytics-consent-form-modal.tsx rename to frontend/src/components/features/analytics/analytics-consent-form-modal.tsx index fac48030c723..0946a2880fc9 100644 --- a/frontend/src/components/analytics/analytics-consent-form-modal.tsx +++ b/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx @@ -1,10 +1,10 @@ -import { ModalBackdrop } from "../modals/modal-backdrop"; -import { ModalBody } from "../modals/modal-body"; -import { ModalButton } from "../buttons/modal-button"; +import { ModalBackdrop } from "../../modals/modal-backdrop"; +import { ModalBody } from "../../modals/modal-body"; +import { ModalButton } from "../../ui/buttons/modal-button"; import { BaseModalTitle, BaseModalDescription, -} from "../modals/confirmation-modals/base-modal"; +} from "../../modals/confirmation-modals/base-modal"; import { handleCaptureConsent } from "#/utils/handle-capture-consent"; interface AnalyticsConsentFormModalProps { diff --git a/frontend/src/components/browser/browser-snapshot.tsx b/frontend/src/components/features/browser/browser-snapshot.tsx similarity index 100% rename from frontend/src/components/browser/browser-snapshot.tsx rename to frontend/src/components/features/browser/browser-snapshot.tsx diff --git a/frontend/src/components/browser/browser.tsx b/frontend/src/components/features/browser/browser.tsx similarity index 100% rename from frontend/src/components/browser/browser.tsx rename to frontend/src/components/features/browser/browser.tsx diff --git a/frontend/src/components/browser/empty-browser-message.tsx b/frontend/src/components/features/browser/empty-browser-message.tsx similarity index 100% rename from frontend/src/components/browser/empty-browser-message.tsx rename to frontend/src/components/features/browser/empty-browser-message.tsx diff --git a/frontend/src/components/chat/action-suggestions.tsx b/frontend/src/components/features/chat/action-suggestions.tsx similarity index 96% rename from frontend/src/components/chat/action-suggestions.tsx rename to frontend/src/components/features/chat/action-suggestions.tsx index 3f89c9e43e5e..28feab537b83 100644 --- a/frontend/src/components/chat/action-suggestions.tsx +++ b/frontend/src/components/features/chat/action-suggestions.tsx @@ -1,6 +1,6 @@ import posthog from "posthog-js"; import React from "react"; -import { SuggestionItem } from "#/components/suggestions/suggestion-item"; +import { SuggestionItem } from "#/components/features/suggestions/suggestion-item"; import { useAuth } from "#/context/auth-context"; import { downloadWorkspace } from "#/utils/download-workspace"; diff --git a/frontend/src/components/chat/chat-input.tsx b/frontend/src/components/features/chat/chat-input.tsx similarity index 97% rename from frontend/src/components/chat/chat-input.tsx rename to frontend/src/components/features/chat/chat-input.tsx index 241c30c8b9de..af5be4d8336f 100644 --- a/frontend/src/components/chat/chat-input.tsx +++ b/frontend/src/components/features/chat/chat-input.tsx @@ -1,8 +1,8 @@ import React from "react"; import TextareaAutosize from "react-textarea-autosize"; import { cn } from "#/utils/utils"; -import { SubmitButton } from "../buttons/submit-button"; -import { StopButton } from "../buttons/stop-button"; +import { SubmitButton } from "../../ui/buttons/submit-button"; +import { StopButton } from "../../ui/buttons/stop-button"; interface ChatInputProps { name?: string; diff --git a/frontend/src/components/chat/chat-interface.tsx b/frontend/src/components/features/chat/chat-interface.tsx similarity index 96% rename from frontend/src/components/chat/chat-interface.tsx rename to frontend/src/components/features/chat/chat-interface.tsx index b1f389ba4c51..33eb3cb47551 100644 --- a/frontend/src/components/chat/chat-interface.tsx +++ b/frontend/src/components/features/chat/chat-interface.tsx @@ -12,11 +12,11 @@ import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { FeedbackModal } from "../feedback/feedback-modal"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; import { TypingIndicator } from "./typing-indicator"; -import { ContinueButton } from "../buttons/continue-button"; -import { ScrollToBottomButton } from "../buttons/scroll-to-bottom-button"; +import { ContinueButton } from "../../ui/buttons/continue-button"; +import { ScrollToBottomButton } from "../../ui/buttons/scroll-to-bottom-button"; import { useWsClient } from "#/context/ws-client-provider"; import { Messages } from "./messages"; -import { LoadingSpinner } from "../ui/loading-spinner"; +import { LoadingSpinner } from "../../ui/loading-spinner"; import { ChatSuggestions } from "./chat-suggestions"; import { ActionSuggestions } from "./action-suggestions"; diff --git a/frontend/src/components/chat/chat-message.tsx b/frontend/src/components/features/chat/chat-message.tsx similarity index 95% rename from frontend/src/components/chat/chat-message.tsx rename to frontend/src/components/features/chat/chat-message.tsx index f479c332c8a2..96e530e5e527 100644 --- a/frontend/src/components/chat/chat-message.tsx +++ b/frontend/src/components/features/chat/chat-message.tsx @@ -4,7 +4,7 @@ import remarkGfm from "remark-gfm"; import { code } from "../markdown/code"; import { cn } from "#/utils/utils"; import { ul, ol } from "../markdown/list"; -import { CopyToClipboardButton } from "../buttons/copy-to-clipboard-button"; +import { CopyToClipboardButton } from "../../ui/buttons/copy-to-clipboard-button"; interface ChatMessageProps { type: "user" | "assistant"; diff --git a/frontend/src/components/chat/chat-suggestions.tsx b/frontend/src/components/features/chat/chat-suggestions.tsx similarity index 92% rename from frontend/src/components/chat/chat-suggestions.tsx rename to frontend/src/components/features/chat/chat-suggestions.tsx index ffc985443196..794602aa2e3d 100644 --- a/frontend/src/components/chat/chat-suggestions.tsx +++ b/frontend/src/components/features/chat/chat-suggestions.tsx @@ -1,4 +1,4 @@ -import { Suggestions } from "#/components/suggestions/suggestions"; +import { Suggestions } from "#/components/features/suggestions/suggestions"; import BuildIt from "#/icons/build-it.svg?react"; import { SUGGESTIONS } from "#/utils/suggestions"; diff --git a/frontend/src/components/chat/error-message.tsx b/frontend/src/components/features/chat/error-message.tsx similarity index 100% rename from frontend/src/components/chat/error-message.tsx rename to frontend/src/components/features/chat/error-message.tsx diff --git a/frontend/src/components/chat/interactive-chat-box.tsx b/frontend/src/components/features/chat/interactive-chat-box.tsx similarity index 100% rename from frontend/src/components/chat/interactive-chat-box.tsx rename to frontend/src/components/features/chat/interactive-chat-box.tsx diff --git a/frontend/src/components/chat/messages.tsx b/frontend/src/components/features/chat/messages.tsx similarity index 86% rename from frontend/src/components/chat/messages.tsx rename to frontend/src/components/features/chat/messages.tsx index 3c940901f792..8307238eac08 100644 --- a/frontend/src/components/chat/messages.tsx +++ b/frontend/src/components/features/chat/messages.tsx @@ -1,5 +1,5 @@ -import { ChatMessage } from "#/components/chat/chat-message"; -import { ConfirmationButtons } from "#/components/buttons/confirmation-buttons"; +import { ChatMessage } from "#/components/features/chat/chat-message"; +import { ConfirmationButtons } from "#/components/ui/buttons/confirmation-buttons"; import { ImageCarousel } from "../images/image-carousel"; import { ErrorMessage } from "./error-message"; diff --git a/frontend/src/components/chat/typing-indicator.tsx b/frontend/src/components/features/chat/typing-indicator.tsx similarity index 100% rename from frontend/src/components/chat/typing-indicator.tsx rename to frontend/src/components/features/chat/typing-indicator.tsx diff --git a/frontend/src/components/context-menu/account-settings-context-menu.tsx b/frontend/src/components/features/context-menu/account-settings-context-menu.tsx similarity index 100% rename from frontend/src/components/context-menu/account-settings-context-menu.tsx rename to frontend/src/components/features/context-menu/account-settings-context-menu.tsx diff --git a/frontend/src/components/context-menu/context-menu-list-item.tsx b/frontend/src/components/features/context-menu/context-menu-list-item.tsx similarity index 100% rename from frontend/src/components/context-menu/context-menu-list-item.tsx rename to frontend/src/components/features/context-menu/context-menu-list-item.tsx diff --git a/frontend/src/components/context-menu/context-menu-separator.tsx b/frontend/src/components/features/context-menu/context-menu-separator.tsx similarity index 100% rename from frontend/src/components/context-menu/context-menu-separator.tsx rename to frontend/src/components/features/context-menu/context-menu-separator.tsx diff --git a/frontend/src/components/context-menu/context-menu.tsx b/frontend/src/components/features/context-menu/context-menu.tsx similarity index 100% rename from frontend/src/components/context-menu/context-menu.tsx rename to frontend/src/components/features/context-menu/context-menu.tsx diff --git a/frontend/src/components/controls/agent-control-bar.tsx b/frontend/src/components/features/controls/agent-control-bar.tsx similarity index 95% rename from frontend/src/components/controls/agent-control-bar.tsx rename to frontend/src/components/features/controls/agent-control-bar.tsx index ff9489f2e9d5..cb8e6009327f 100644 --- a/frontend/src/components/controls/agent-control-bar.tsx +++ b/frontend/src/components/features/controls/agent-control-bar.tsx @@ -6,7 +6,7 @@ import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; import { useWsClient } from "#/context/ws-client-provider"; import { IGNORE_TASK_STATE_MAP } from "#/ignore-task-state-map.constant"; -import { ActionButton } from "../buttons/action-button"; +import { ActionButton } from "../../ui/buttons/action-button"; export function AgentControlBar() { const { send } = useWsClient(); diff --git a/frontend/src/components/controls/agent-status-bar.tsx b/frontend/src/components/features/controls/agent-status-bar.tsx similarity index 96% rename from frontend/src/components/controls/agent-status-bar.tsx rename to frontend/src/components/features/controls/agent-status-bar.tsx index 02212fe91d0e..62511897151b 100644 --- a/frontend/src/components/controls/agent-status-bar.tsx +++ b/frontend/src/components/features/controls/agent-status-bar.tsx @@ -4,7 +4,7 @@ import { useSelector } from "react-redux"; import toast from "react-hot-toast"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; -import { AGENT_STATUS_MAP } from "../agent-status-map.constant"; +import { AGENT_STATUS_MAP } from "../../agent-status-map.constant"; export function AgentStatusBar() { const { t, i18n } = useTranslation(); diff --git a/frontend/src/components/controls/controls.tsx b/frontend/src/components/features/controls/controls.tsx similarity index 100% rename from frontend/src/components/controls/controls.tsx rename to frontend/src/components/features/controls/controls.tsx diff --git a/frontend/src/components/controls/security-lock.tsx b/frontend/src/components/features/controls/security-lock.tsx similarity index 100% rename from frontend/src/components/controls/security-lock.tsx rename to frontend/src/components/features/controls/security-lock.tsx diff --git a/frontend/src/components/editor/code-editor-component.tsx b/frontend/src/components/features/editor/code-editor-component.tsx similarity index 100% rename from frontend/src/components/editor/code-editor-component.tsx rename to frontend/src/components/features/editor/code-editor-component.tsx diff --git a/frontend/src/components/editor/editor-actions.tsx b/frontend/src/components/features/editor/editor-actions.tsx similarity index 89% rename from frontend/src/components/editor/editor-actions.tsx rename to frontend/src/components/features/editor/editor-actions.tsx index 9143e0796585..28e375c58573 100644 --- a/frontend/src/components/editor/editor-actions.tsx +++ b/frontend/src/components/features/editor/editor-actions.tsx @@ -1,4 +1,4 @@ -import { EditorActionButton } from "../buttons/editor-action-button"; +import { EditorActionButton } from "../../ui/buttons/editor-action-button"; interface EditorActionsProps { onSave: () => void; diff --git a/frontend/src/components/feedback/feedback-actions.tsx b/frontend/src/components/features/feedback/feedback-actions.tsx similarity index 90% rename from frontend/src/components/feedback/feedback-actions.tsx rename to frontend/src/components/features/feedback/feedback-actions.tsx index 3fdaea0b40de..386c04c7d734 100644 --- a/frontend/src/components/feedback/feedback-actions.tsx +++ b/frontend/src/components/features/feedback/feedback-actions.tsx @@ -1,6 +1,6 @@ import ThumbsUpIcon from "#/icons/thumbs-up.svg?react"; import ThumbDownIcon from "#/icons/thumbs-down.svg?react"; -import { FeedbackActionButton } from "../buttons/feedback-action-button"; +import { FeedbackActionButton } from "../../ui/buttons/feedback-action-button"; interface FeedbackActionsProps { onPositiveFeedback: () => void; diff --git a/frontend/src/components/feedback/feedback-form.tsx b/frontend/src/components/features/feedback/feedback-form.tsx similarity index 98% rename from frontend/src/components/feedback/feedback-form.tsx rename to frontend/src/components/features/feedback/feedback-form.tsx index 5a96b19f7265..6e2009c82623 100644 --- a/frontend/src/components/feedback/feedback-form.tsx +++ b/frontend/src/components/features/feedback/feedback-form.tsx @@ -1,6 +1,6 @@ import React from "react"; import hotToast from "react-hot-toast"; -import { ModalButton } from "../buttons/modal-button"; +import { ModalButton } from "../../ui/buttons/modal-button"; import { Feedback } from "#/api/open-hands.types"; import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback"; diff --git a/frontend/src/components/feedback/feedback-modal.tsx b/frontend/src/components/features/feedback/feedback-modal.tsx similarity index 81% rename from frontend/src/components/feedback/feedback-modal.tsx rename to frontend/src/components/features/feedback/feedback-modal.tsx index e4fbe60ff24a..509343e4d544 100644 --- a/frontend/src/components/feedback/feedback-modal.tsx +++ b/frontend/src/components/features/feedback/feedback-modal.tsx @@ -2,9 +2,9 @@ import { FeedbackForm } from "./feedback-form"; import { BaseModalTitle, BaseModalDescription, -} from "../modals/confirmation-modals/base-modal"; -import { ModalBackdrop } from "../modals/modal-backdrop"; -import { ModalBody } from "../modals/modal-body"; +} from "../../modals/confirmation-modals/base-modal"; +import { ModalBackdrop } from "../../modals/modal-backdrop"; +import { ModalBody } from "../../modals/modal-body"; interface FeedbackModalProps { onClose: () => void; diff --git a/frontend/src/components/file-explorer/dropzone.tsx b/frontend/src/components/features/file-explorer/dropzone.tsx similarity index 100% rename from frontend/src/components/file-explorer/dropzone.tsx rename to frontend/src/components/features/file-explorer/dropzone.tsx diff --git a/frontend/src/components/file-explorer/explorer-tree.tsx b/frontend/src/components/features/file-explorer/explorer-tree.tsx similarity index 100% rename from frontend/src/components/file-explorer/explorer-tree.tsx rename to frontend/src/components/features/file-explorer/explorer-tree.tsx diff --git a/frontend/src/components/file-explorer/file-explorer-actions.tsx b/frontend/src/components/features/file-explorer/file-explorer-actions.tsx similarity index 74% rename from frontend/src/components/file-explorer/file-explorer-actions.tsx rename to frontend/src/components/features/file-explorer/file-explorer-actions.tsx index ccf8f12a7d8d..847b8682f2dd 100644 --- a/frontend/src/components/file-explorer/file-explorer-actions.tsx +++ b/frontend/src/components/features/file-explorer/file-explorer-actions.tsx @@ -1,7 +1,7 @@ import { cn } from "#/utils/utils"; -import { RefreshIconButton } from "../buttons/refresh-icon-button"; -import { ToggleWorkspaceIconButton } from "../buttons/toggle-workspace-icon-button"; -import { UploadIconButton } from "../buttons/upload-icon-button"; +import { RefreshIconButton } from "../../ui/buttons/refresh-icon-button"; +import { ToggleWorkspaceIconButton } from "../../ui/buttons/toggle-workspace-icon-button"; +import { UploadIconButton } from "../../ui/buttons/upload-icon-button"; interface ExplorerActionsProps { onRefresh: () => void; diff --git a/frontend/src/components/file-explorer/file-explorer-header.tsx b/frontend/src/components/features/file-explorer/file-explorer-header.tsx similarity index 100% rename from frontend/src/components/file-explorer/file-explorer-header.tsx rename to frontend/src/components/features/file-explorer/file-explorer-header.tsx diff --git a/frontend/src/components/file-explorer/file-explorer.tsx b/frontend/src/components/features/file-explorer/file-explorer.tsx similarity index 96% rename from frontend/src/components/file-explorer/file-explorer.tsx rename to frontend/src/components/features/file-explorer/file-explorer.tsx index 57eaf7b0cf36..47c04c99172d 100644 --- a/frontend/src/components/file-explorer/file-explorer.tsx +++ b/frontend/src/components/features/file-explorer/file-explorer.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; import AgentState from "#/types/agent-state"; -import { ExplorerTree } from "#/components/file-explorer/explorer-tree"; +import { ExplorerTree } from "#/components/features/file-explorer/explorer-tree"; import toast from "#/utils/toast"; import { RootState } from "#/store"; import { I18nKey } from "#/i18n/declaration"; @@ -13,7 +13,7 @@ import { cn } from "#/utils/utils"; import { Dropzone } from "./dropzone"; import { FileExplorerHeader } from "./file-explorer-header"; import { useVSCodeUrl } from "#/hooks/query/use-vscode-url"; -import { OpenVSCodeButton } from "../buttons/open-vscode-button"; +import { OpenVSCodeButton } from "../../ui/buttons/open-vscode-button"; interface FileExplorerProps { isOpen: boolean; diff --git a/frontend/src/components/file-explorer/file-icon.tsx b/frontend/src/components/features/file-explorer/file-icon.tsx similarity index 80% rename from frontend/src/components/file-explorer/file-icon.tsx rename to frontend/src/components/features/file-explorer/file-icon.tsx index 5413aa323008..bd6486a03558 100644 --- a/frontend/src/components/file-explorer/file-icon.tsx +++ b/frontend/src/components/features/file-explorer/file-icon.tsx @@ -1,6 +1,6 @@ import { FaFile } from "react-icons/fa"; import { getExtension } from "#/utils/utils"; -import { EXTENSION_ICON_MAP } from "../extension-icon-map.constant"; +import { EXTENSION_ICON_MAP } from "../../extension-icon-map.constant"; interface FileIconProps { filename: string; diff --git a/frontend/src/components/file-explorer/title.tsx b/frontend/src/components/features/file-explorer/filename.tsx similarity index 86% rename from frontend/src/components/file-explorer/title.tsx rename to frontend/src/components/features/file-explorer/filename.tsx index 4206eaee4bbc..c89596c86ddf 100644 --- a/frontend/src/components/file-explorer/title.tsx +++ b/frontend/src/components/features/file-explorer/filename.tsx @@ -1,14 +1,14 @@ import { FolderIcon } from "./folder-icon"; import { FileIcon } from "./file-icon"; -interface TitleProps { +interface FilenameProps { name: string; type: "folder" | "file"; isOpen: boolean; onClick: () => void; } -export function Title({ name, type, isOpen, onClick }: TitleProps) { +export function Filename({ name, type, isOpen, onClick }: FilenameProps) { return (
- void; diff --git a/frontend/src/components/suggestions/import-project-suggestion-box.tsx b/frontend/src/components/features/suggestions/import-project-suggestion-box.tsx similarity index 100% rename from frontend/src/components/suggestions/import-project-suggestion-box.tsx rename to frontend/src/components/features/suggestions/import-project-suggestion-box.tsx diff --git a/frontend/src/components/suggestions/suggestion-box.tsx b/frontend/src/components/features/suggestions/suggestion-box.tsx similarity index 100% rename from frontend/src/components/suggestions/suggestion-box.tsx rename to frontend/src/components/features/suggestions/suggestion-box.tsx diff --git a/frontend/src/components/suggestions/suggestion-bubble.tsx b/frontend/src/components/features/suggestions/suggestion-bubble.tsx similarity index 92% rename from frontend/src/components/suggestions/suggestion-bubble.tsx rename to frontend/src/components/features/suggestions/suggestion-bubble.tsx index 6a250c848361..611a207ebd8c 100644 --- a/frontend/src/components/suggestions/suggestion-bubble.tsx +++ b/frontend/src/components/features/suggestions/suggestion-bubble.tsx @@ -1,5 +1,5 @@ import Lightbulb from "#/icons/lightbulb.svg?react"; -import { RefreshButton } from "../buttons/refresh-button"; +import { RefreshButton } from "../../ui/buttons/refresh-button"; interface SuggestionBubbleProps { suggestion: string; diff --git a/frontend/src/components/suggestions/suggestion-item.tsx b/frontend/src/components/features/suggestions/suggestion-item.tsx similarity index 100% rename from frontend/src/components/suggestions/suggestion-item.tsx rename to frontend/src/components/features/suggestions/suggestion-item.tsx diff --git a/frontend/src/components/suggestions/suggestions.tsx b/frontend/src/components/features/suggestions/suggestions.tsx similarity index 100% rename from frontend/src/components/suggestions/suggestions.tsx rename to frontend/src/components/features/suggestions/suggestions.tsx diff --git a/frontend/src/components/terminal/terminal.tsx b/frontend/src/components/features/terminal/terminal.tsx similarity index 100% rename from frontend/src/components/terminal/terminal.tsx rename to frontend/src/components/features/terminal/terminal.tsx diff --git a/frontend/src/components/waitlist/join-waitlist-anchor.tsx b/frontend/src/components/features/waitlist/join-waitlist-anchor.tsx similarity index 100% rename from frontend/src/components/waitlist/join-waitlist-anchor.tsx rename to frontend/src/components/features/waitlist/join-waitlist-anchor.tsx diff --git a/frontend/src/components/waitlist/waitlist-message.tsx b/frontend/src/components/features/waitlist/waitlist-message.tsx similarity index 100% rename from frontend/src/components/waitlist/waitlist-message.tsx rename to frontend/src/components/features/waitlist/waitlist-message.tsx diff --git a/frontend/src/components/waitlist/waitlist-modal.tsx b/frontend/src/components/features/waitlist/waitlist-modal.tsx similarity index 95% rename from frontend/src/components/waitlist/waitlist-modal.tsx rename to frontend/src/components/features/waitlist/waitlist-modal.tsx index a924da5d4641..9ebf46a13704 100644 --- a/frontend/src/components/waitlist/waitlist-modal.tsx +++ b/frontend/src/components/features/waitlist/waitlist-modal.tsx @@ -1,4 +1,4 @@ -import { ModalButton } from "../buttons/modal-button"; +import { ModalButton } from "../ui/buttons/modal-button"; import { ModalBackdrop } from "../modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; diff --git a/frontend/src/components/modals/account-settings-form.tsx b/frontend/src/components/modals/account-settings-form.tsx index e11d82f1ecce..026f26495d2c 100644 --- a/frontend/src/components/modals/account-settings-form.tsx +++ b/frontend/src/components/modals/account-settings-form.tsx @@ -5,7 +5,7 @@ import { BaseModalTitle, } from "./confirmation-modals/base-modal"; import { ModalBody } from "./modal-body"; -import { ModalButton } from "../buttons/modal-button"; +import { ModalButton } from "../ui/buttons/modal-button"; import { FormFieldset } from "../ui/form-fieldset"; import { CustomInput } from "../ui/custom-input"; import { AvailableLanguages } from "#/i18n"; diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/modals/confirmation-modals/base-modal.tsx index a2580006d8de..8dad0bda5305 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/base-modal.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { ModalButton } from "#/components/buttons/modal-button"; +import { ModalButton } from "#/components/ui/buttons/modal-button"; import { ModalBody } from "../modal-body"; interface ButtonConfig { diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/modals/connect-to-github-modal.tsx index 84116d56bb0a..d5fb63817b69 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/modals/connect-to-github-modal.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import { ModalBody } from "./modal-body"; import { CustomInput } from "../ui/custom-input"; -import { ModalButton } from "../buttons/modal-button"; +import { ModalButton } from "../ui/buttons/modal-button"; import { BaseModalDescription, BaseModalTitle, diff --git a/frontend/src/components/settings-form.tsx b/frontend/src/components/settings-form.tsx index c18a188bf671..71db93b5bc80 100644 --- a/frontend/src/components/settings-form.tsx +++ b/frontend/src/components/settings-form.tsx @@ -7,7 +7,7 @@ import { ModelSelector } from "#/components/modals/settings/model-selector"; import { getDefaultSettings, Settings } from "#/services/settings"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { extractModelAndProvider } from "#/utils/extract-model-and-provider"; -import { ModalButton } from "./buttons/modal-button"; +import { ModalButton } from "./ui/buttons/modal-button"; import { DangerModal } from "./modals/confirmation-modals/danger-modal"; import { I18nKey } from "#/i18n/declaration"; import { @@ -17,13 +17,13 @@ import { } from "#/utils/settings-utils"; import { useEndSession } from "#/hooks/use-end-session"; import { useUserPrefs } from "#/context/user-prefs-context"; -import { AdvancedOptionSwitch } from "./inputs/advanced-option-switch"; -import { CustomModelInput } from "./inputs/custom-model-input"; -import { BaseUrlInput } from "./inputs/base-url-input"; -import { AgentInput } from "./inputs/agent-input"; -import { APIKeyInput } from "./inputs/api-key-input"; -import { SecurityAnalyzerInput } from "./inputs/security-analyzers-input"; -import { ConfirmationModeSwitch } from "./inputs/confirmation-mode-switch"; +import { AdvancedOptionSwitch } from "./ui/inputs/advanced-option-switch"; +import { CustomModelInput } from "./ui/inputs/custom-model-input"; +import { BaseUrlInput } from "./ui/inputs/base-url-input"; +import { AgentInput } from "./ui/inputs/agent-input"; +import { APIKeyInput } from "./ui/inputs/api-key-input"; +import { SecurityAnalyzerInput } from "./ui/inputs/security-analyzers-input"; +import { ConfirmationModeSwitch } from "./ui/inputs/confirmation-mode-switch"; interface SettingsFormProps { disabled?: boolean; diff --git a/frontend/src/components/buttons/action-button.tsx b/frontend/src/components/ui/buttons/action-button.tsx similarity index 100% rename from frontend/src/components/buttons/action-button.tsx rename to frontend/src/components/ui/buttons/action-button.tsx diff --git a/frontend/src/components/buttons/all-hands-logo-button.tsx b/frontend/src/components/ui/buttons/all-hands-logo-button.tsx similarity index 100% rename from frontend/src/components/buttons/all-hands-logo-button.tsx rename to frontend/src/components/ui/buttons/all-hands-logo-button.tsx diff --git a/frontend/src/components/buttons/confirmation-buttons.tsx b/frontend/src/components/ui/buttons/confirmation-buttons.tsx similarity index 94% rename from frontend/src/components/buttons/confirmation-buttons.tsx rename to frontend/src/components/ui/buttons/confirmation-buttons.tsx index 19e323875947..18ad6c50e8f9 100644 --- a/frontend/src/components/buttons/confirmation-buttons.tsx +++ b/frontend/src/components/ui/buttons/confirmation-buttons.tsx @@ -3,7 +3,7 @@ import { I18nKey } from "#/i18n/declaration"; import AgentState from "#/types/agent-state"; import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { useWsClient } from "#/context/ws-client-provider"; -import { ActionTooltip } from "../ui/action-tooltip"; +import { ActionTooltip } from "../action-tooltip"; export function ConfirmationButtons() { const { t } = useTranslation(); diff --git a/frontend/src/components/buttons/continue-button.tsx b/frontend/src/components/ui/buttons/continue-button.tsx similarity index 100% rename from frontend/src/components/buttons/continue-button.tsx rename to frontend/src/components/ui/buttons/continue-button.tsx diff --git a/frontend/src/components/buttons/copy-to-clipboard-button.tsx b/frontend/src/components/ui/buttons/copy-to-clipboard-button.tsx similarity index 100% rename from frontend/src/components/buttons/copy-to-clipboard-button.tsx rename to frontend/src/components/ui/buttons/copy-to-clipboard-button.tsx diff --git a/frontend/src/components/buttons/docs-button.tsx b/frontend/src/components/ui/buttons/docs-button.tsx similarity index 100% rename from frontend/src/components/buttons/docs-button.tsx rename to frontend/src/components/ui/buttons/docs-button.tsx diff --git a/frontend/src/components/buttons/editor-action-button.tsx b/frontend/src/components/ui/buttons/editor-action-button.tsx similarity index 100% rename from frontend/src/components/buttons/editor-action-button.tsx rename to frontend/src/components/ui/buttons/editor-action-button.tsx diff --git a/frontend/src/components/buttons/exit-project-button.tsx b/frontend/src/components/ui/buttons/exit-project-button.tsx similarity index 100% rename from frontend/src/components/buttons/exit-project-button.tsx rename to frontend/src/components/ui/buttons/exit-project-button.tsx diff --git a/frontend/src/components/buttons/feedback-action-button.tsx b/frontend/src/components/ui/buttons/feedback-action-button.tsx similarity index 100% rename from frontend/src/components/buttons/feedback-action-button.tsx rename to frontend/src/components/ui/buttons/feedback-action-button.tsx diff --git a/frontend/src/components/buttons/icon-button.tsx b/frontend/src/components/ui/buttons/icon-button.tsx similarity index 100% rename from frontend/src/components/buttons/icon-button.tsx rename to frontend/src/components/ui/buttons/icon-button.tsx diff --git a/frontend/src/components/buttons/modal-button.tsx b/frontend/src/components/ui/buttons/modal-button.tsx similarity index 100% rename from frontend/src/components/buttons/modal-button.tsx rename to frontend/src/components/ui/buttons/modal-button.tsx diff --git a/frontend/src/components/buttons/open-vscode-button.tsx b/frontend/src/components/ui/buttons/open-vscode-button.tsx similarity index 100% rename from frontend/src/components/buttons/open-vscode-button.tsx rename to frontend/src/components/ui/buttons/open-vscode-button.tsx diff --git a/frontend/src/components/buttons/refresh-button.tsx b/frontend/src/components/ui/buttons/refresh-button.tsx similarity index 100% rename from frontend/src/components/buttons/refresh-button.tsx rename to frontend/src/components/ui/buttons/refresh-button.tsx diff --git a/frontend/src/components/buttons/refresh-icon-button.tsx b/frontend/src/components/ui/buttons/refresh-icon-button.tsx similarity index 87% rename from frontend/src/components/buttons/refresh-icon-button.tsx rename to frontend/src/components/ui/buttons/refresh-icon-button.tsx index 1db7a804d8a5..c66d344e9fdc 100644 --- a/frontend/src/components/buttons/refresh-icon-button.tsx +++ b/frontend/src/components/ui/buttons/refresh-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosRefresh } from "react-icons/io"; -import { IconButton } from "#/components/buttons/icon-button"; +import { IconButton } from "#/components/ui/buttons/icon-button"; interface RefreshIconButtonProps { onClick: () => void; diff --git a/frontend/src/components/buttons/remove-button.tsx b/frontend/src/components/ui/buttons/remove-button.tsx similarity index 100% rename from frontend/src/components/buttons/remove-button.tsx rename to frontend/src/components/ui/buttons/remove-button.tsx diff --git a/frontend/src/components/buttons/scroll-to-bottom-button.tsx b/frontend/src/components/ui/buttons/scroll-to-bottom-button.tsx similarity index 100% rename from frontend/src/components/buttons/scroll-to-bottom-button.tsx rename to frontend/src/components/ui/buttons/scroll-to-bottom-button.tsx diff --git a/frontend/src/components/buttons/settings-button.tsx b/frontend/src/components/ui/buttons/settings-button.tsx similarity index 100% rename from frontend/src/components/buttons/settings-button.tsx rename to frontend/src/components/ui/buttons/settings-button.tsx diff --git a/frontend/src/components/buttons/stop-button.tsx b/frontend/src/components/ui/buttons/stop-button.tsx similarity index 100% rename from frontend/src/components/buttons/stop-button.tsx rename to frontend/src/components/ui/buttons/stop-button.tsx diff --git a/frontend/src/components/buttons/submit-button.tsx b/frontend/src/components/ui/buttons/submit-button.tsx similarity index 100% rename from frontend/src/components/buttons/submit-button.tsx rename to frontend/src/components/ui/buttons/submit-button.tsx diff --git a/frontend/src/components/buttons/toggle-workspace-icon-button.tsx b/frontend/src/components/ui/buttons/toggle-workspace-icon-button.tsx similarity index 91% rename from frontend/src/components/buttons/toggle-workspace-icon-button.tsx rename to frontend/src/components/ui/buttons/toggle-workspace-icon-button.tsx index 9125415ac5d8..038ecb3d3675 100644 --- a/frontend/src/components/buttons/toggle-workspace-icon-button.tsx +++ b/frontend/src/components/ui/buttons/toggle-workspace-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosArrowForward, IoIosArrowBack } from "react-icons/io"; -import { IconButton } from "#/components/buttons/icon-button"; +import { IconButton } from "#/components/ui/buttons/icon-button"; interface ToggleWorkspaceIconButtonProps { onClick: () => void; diff --git a/frontend/src/components/buttons/upload-icon-button.tsx b/frontend/src/components/ui/buttons/upload-icon-button.tsx similarity index 87% rename from frontend/src/components/buttons/upload-icon-button.tsx rename to frontend/src/components/ui/buttons/upload-icon-button.tsx index 342e84379317..923e7be1b124 100644 --- a/frontend/src/components/buttons/upload-icon-button.tsx +++ b/frontend/src/components/ui/buttons/upload-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosCloudUpload } from "react-icons/io"; -import { IconButton } from "#/components/buttons/icon-button"; +import { IconButton } from "#/components/ui/buttons/icon-button"; interface UploadIconButtonProps { onClick: () => void; diff --git a/frontend/src/components/inputs/advanced-option-switch.tsx b/frontend/src/components/ui/inputs/advanced-option-switch.tsx similarity index 100% rename from frontend/src/components/inputs/advanced-option-switch.tsx rename to frontend/src/components/ui/inputs/advanced-option-switch.tsx diff --git a/frontend/src/components/inputs/agent-input.tsx b/frontend/src/components/ui/inputs/agent-input.tsx similarity index 100% rename from frontend/src/components/inputs/agent-input.tsx rename to frontend/src/components/ui/inputs/agent-input.tsx diff --git a/frontend/src/components/inputs/api-key-input.tsx b/frontend/src/components/ui/inputs/api-key-input.tsx similarity index 100% rename from frontend/src/components/inputs/api-key-input.tsx rename to frontend/src/components/ui/inputs/api-key-input.tsx diff --git a/frontend/src/components/inputs/base-url-input.tsx b/frontend/src/components/ui/inputs/base-url-input.tsx similarity index 100% rename from frontend/src/components/inputs/base-url-input.tsx rename to frontend/src/components/ui/inputs/base-url-input.tsx diff --git a/frontend/src/components/inputs/confirmation-mode-switch.tsx b/frontend/src/components/ui/inputs/confirmation-mode-switch.tsx similarity index 100% rename from frontend/src/components/inputs/confirmation-mode-switch.tsx rename to frontend/src/components/ui/inputs/confirmation-mode-switch.tsx diff --git a/frontend/src/components/inputs/custom-model-input.tsx b/frontend/src/components/ui/inputs/custom-model-input.tsx similarity index 100% rename from frontend/src/components/inputs/custom-model-input.tsx rename to frontend/src/components/ui/inputs/custom-model-input.tsx diff --git a/frontend/src/components/inputs/security-analyzers-input.tsx b/frontend/src/components/ui/inputs/security-analyzers-input.tsx similarity index 100% rename from frontend/src/components/inputs/security-analyzers-input.tsx rename to frontend/src/components/ui/inputs/security-analyzers-input.tsx diff --git a/frontend/src/components/ui/task-form.tsx b/frontend/src/components/ui/task-form.tsx index c231c1bcbb2f..3fcf6fc1f75a 100644 --- a/frontend/src/components/ui/task-form.tsx +++ b/frontend/src/components/ui/task-form.tsx @@ -8,15 +8,15 @@ import { removeFile, setInitialQuery, } from "#/state/initial-query-slice"; -import { SuggestionBubble } from "#/components/suggestions/suggestion-bubble"; +import { SuggestionBubble } from "#/components/features/suggestions/suggestion-bubble"; import { SUGGESTIONS } from "#/utils/suggestions"; import { convertImageToBase64 } from "#/utils/convert-image-to-base-64"; -import { ChatInput } from "#/components/chat/chat-input"; +import { ChatInput } from "#/components/features/chat/chat-input"; import { getRandomKey } from "#/utils/get-random-key"; import { cn } from "#/utils/utils"; -import { AttachImageLabel } from "../images/attach-image-label"; -import { ImageCarousel } from "../images/image-carousel"; -import { UploadImageInput } from "../images/upload-image-input"; +import { AttachImageLabel } from "../features/images/attach-image-label"; +import { ImageCarousel } from "../features/images/image-carousel"; +import { UploadImageInput } from "../features/images/upload-image-input"; export const TaskForm = React.forwardRef<HTMLFormElement>((_, ref) => { const dispatch = useDispatch(); diff --git a/frontend/src/routes/_oh._index/route.tsx b/frontend/src/routes/_oh._index/route.tsx index 1f2a0631e32a..1687ab7f092b 100644 --- a/frontend/src/routes/_oh._index/route.tsx +++ b/frontend/src/routes/_oh._index/route.tsx @@ -10,8 +10,8 @@ import { useGitHubUser } from "#/hooks/query/use-github-user"; import { useGitHubAuthUrl } from "#/hooks/use-github-auth-url"; import { useConfig } from "#/hooks/query/use-config"; import { useAuth } from "#/context/auth-context"; -import { ImportProjectSuggestionBox } from "../../components/suggestions/import-project-suggestion-box"; -import { GitHubRepositoriesSuggestionBox } from "#/components/github/github-repositories-suggestion-box"; +import { ImportProjectSuggestionBox } from "../../components/features/suggestions/import-project-suggestion-box"; +import { GitHubRepositoriesSuggestionBox } from "#/components/features/github/github-repositories-suggestion-box"; function Home() { const { token, gitHubToken } = useAuth(); diff --git a/frontend/src/routes/_oh.app._index/route.tsx b/frontend/src/routes/_oh.app._index/route.tsx index 1f69e93bdd85..169665100535 100644 --- a/frontend/src/routes/_oh.app._index/route.tsx +++ b/frontend/src/routes/_oh.app._index/route.tsx @@ -5,12 +5,12 @@ import { editor } from "monaco-editor"; import { EditorProps } from "@monaco-editor/react"; import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; -import CodeEditorComponent from "../../components/editor/code-editor-component"; +import CodeEditorComponent from "../../components/features/editor/code-editor-component"; import { useFiles } from "#/context/files"; import { useSaveFile } from "#/hooks/mutation/use-save-file"; import { ASSET_FILE_TYPES } from "./constants"; -import { EditorActions } from "#/components/editor/editor-actions"; -import { FileExplorer } from "#/components/file-explorer/file-explorer"; +import { EditorActions } from "#/components/features/editor/editor-actions"; +import { FileExplorer } from "#/components/features/file-explorer/file-explorer"; export function ErrorBoundary() { const error = useRouteError(); diff --git a/frontend/src/routes/_oh.app.browser.tsx b/frontend/src/routes/_oh.app.browser.tsx index 5a4654ebb345..3c953c00ea03 100644 --- a/frontend/src/routes/_oh.app.browser.tsx +++ b/frontend/src/routes/_oh.app.browser.tsx @@ -1,4 +1,4 @@ -import { BrowserPanel } from "#/components/browser/browser"; +import { BrowserPanel } from "#/components/features/browser/browser"; function Browser() { return <BrowserPanel />; diff --git a/frontend/src/routes/_oh.app.jupyter.tsx b/frontend/src/routes/_oh.app.jupyter.tsx index 807ee53b6126..6565ad2c31f6 100644 --- a/frontend/src/routes/_oh.app.jupyter.tsx +++ b/frontend/src/routes/_oh.app.jupyter.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { JupyterEditor } from "#/components/jupyter/jupyter"; +import { JupyterEditor } from "#/components/features/jupyter/jupyter"; function Jupyter() { const parentRef = React.useRef<HTMLDivElement>(null); diff --git a/frontend/src/routes/_oh.app/route.tsx b/frontend/src/routes/_oh.app/route.tsx index 22901a820a60..6f307a563011 100644 --- a/frontend/src/routes/_oh.app/route.tsx +++ b/frontend/src/routes/_oh.app/route.tsx @@ -3,7 +3,7 @@ import React from "react"; import { Outlet } from "@remix-run/react"; import { useDispatch, useSelector } from "react-redux"; import Security from "#/components/modals/security/security"; -import { Controls } from "#/components/controls/controls"; +import { Controls } from "#/components/features/controls/controls"; import { RootState } from "#/store"; import { clearMessages } from "#/state/chat-slice"; import { clearTerminal } from "#/state/command-slice"; @@ -13,7 +13,7 @@ import GlobeIcon from "#/icons/globe.svg?react"; import ListIcon from "#/icons/list-type-number.svg?react"; import { clearJupyter } from "#/state/jupyter-slice"; import { FilesProvider } from "#/context/files"; -import { ChatInterface } from "../../components/chat/chat-interface"; +import { ChatInterface } from "../../components/features/chat/chat-interface"; import { WsClientProvider } from "#/context/ws-client-provider"; import { EventHandler } from "./event-handler"; import { useLatestRepoCommit } from "#/hooks/query/use-latest-repo-commit"; @@ -43,7 +43,7 @@ function App() { ); const Terminal = React.useMemo( - () => React.lazy(() => import("#/components/terminal/terminal")), + () => React.lazy(() => import("#/components/features/terminal/terminal")), [], ); diff --git a/frontend/src/routes/_oh/route.tsx b/frontend/src/routes/_oh/route.tsx index 1cf58367ae1d..9918c3f1d7c6 100644 --- a/frontend/src/routes/_oh/route.tsx +++ b/frontend/src/routes/_oh/route.tsx @@ -7,8 +7,8 @@ import { useIsAuthed } from "#/hooks/query/use-is-authed"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useConfig } from "#/hooks/query/use-config"; -import { AnalyticsConsentFormModal } from "#/components/analytics/analytics-consent-form-modal"; -import { Sidebar } from "#/components/sidebar/sidebar"; +import { AnalyticsConsentFormModal } from "#/components/features/analytics/analytics-consent-form-modal"; +import { Sidebar } from "#/components/features/sidebar/sidebar"; export function ErrorBoundary() { const error = useRouteError(); From 4240a0acd363ec2756e3b8d11c51b508ea610be1 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:51:42 +0400 Subject: [PATCH 10/13] Fix imports --- .../src/components/features/waitlist/waitlist-modal.tsx | 6 +++--- frontend/src/routes/_oh/route.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/features/waitlist/waitlist-modal.tsx b/frontend/src/components/features/waitlist/waitlist-modal.tsx index 9ebf46a13704..546697ed6daf 100644 --- a/frontend/src/components/features/waitlist/waitlist-modal.tsx +++ b/frontend/src/components/features/waitlist/waitlist-modal.tsx @@ -1,10 +1,10 @@ -import { ModalButton } from "../ui/buttons/modal-button"; -import { ModalBackdrop } from "../modals/modal-backdrop"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; -import { ModalBody } from "../modals/modal-body"; import { JoinWaitlistAnchor } from "./join-waitlist-anchor"; import { WaitlistMessage } from "./waitlist-message"; +import { ModalBody } from "#/components/modals/modal-body"; +import { ModalBackdrop } from "#/components/modals/modal-backdrop"; +import { ModalButton } from "#/components/ui/buttons/modal-button"; interface WaitlistModalProps { ghToken: string | null; diff --git a/frontend/src/routes/_oh/route.tsx b/frontend/src/routes/_oh/route.tsx index 9918c3f1d7c6..ecd6e84dd9f4 100644 --- a/frontend/src/routes/_oh/route.tsx +++ b/frontend/src/routes/_oh/route.tsx @@ -1,7 +1,6 @@ import React from "react"; import { useRouteError, isRouteErrorResponse, Outlet } from "@remix-run/react"; import i18n from "#/i18n"; -import { WaitlistModal } from "#/components/waitlist/waitlist-modal"; import { useGitHubAuthUrl } from "#/hooks/use-github-auth-url"; import { useIsAuthed } from "#/hooks/query/use-is-authed"; import { useAuth } from "#/context/auth-context"; @@ -9,6 +8,7 @@ import { useUserPrefs } from "#/context/user-prefs-context"; import { useConfig } from "#/hooks/query/use-config"; import { AnalyticsConsentFormModal } from "#/components/features/analytics/analytics-consent-form-modal"; import { Sidebar } from "#/components/features/sidebar/sidebar"; +import { WaitlistModal } from "#/components/features/waitlist/waitlist-modal"; export function ErrorBoundary() { const error = useRouteError(); From 2395417f47ab0d21db3c2677a4dea5ea068de755 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:07:15 +0400 Subject: [PATCH 11/13] Further refactors --- .../modals/base-modal/base-modal.test.tsx | 2 +- .../components/connect-to-github-modal.tsx | 74 ---------- .../features/chat/chat-interface.tsx | 8 +- .../features/project-menu/ProjectMenuCard.tsx | 2 +- .../components/features/sidebar/sidebar.tsx | 8 +- .../features/sidebar/user-avatar.tsx | 2 +- .../modals/account-settings-form.tsx | 138 ------------------ .../account-settings-form.tsx | 16 +- .../account-settings-modal.tsx | 2 +- .../modals/base-modal/base-modal.tsx | 4 +- .../modals/confirmation-modals/base-modal.tsx | 4 +- .../confirmation-modals/danger-modal.tsx | 2 +- .../exit-project-confirmation-modal.tsx | 0 .../src/components/modals/loading-project.tsx | 45 ------ .../components/modals/security/security.tsx | 2 +- .../{ => modals/settings}/settings-form.tsx | 18 +-- .../{ => modals/settings}/settings-modal.tsx | 4 +- .../src/components/ui/loading-spinner.tsx | 22 ++- 18 files changed, 56 insertions(+), 297 deletions(-) delete mode 100644 frontend/src/components/connect-to-github-modal.tsx delete mode 100644 frontend/src/components/modals/account-settings-form.tsx rename frontend/src/components/{ => modals/account-settings}/account-settings-form.tsx (94%) rename frontend/src/components/{ => modals/account-settings}/account-settings-modal.tsx (96%) rename frontend/src/components/{ => modals}/exit-project-confirmation-modal.tsx (100%) delete mode 100644 frontend/src/components/modals/loading-project.tsx rename frontend/src/components/{ => modals/settings}/settings-form.tsx (93%) rename frontend/src/components/{ => modals/settings}/settings-modal.tsx (92%) diff --git a/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx b/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx index 59abb7e44a91..6824fd927eed 100644 --- a/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx +++ b/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx @@ -1,7 +1,7 @@ import { render, screen, act } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, it, vi, expect } from "vitest"; -import BaseModal from "#/components/modals/base-modal/base-modal"; +import { BaseModal } from "#/components/modals/base-modal/base-modal"; describe("BaseModal", () => { it("should render if the modal is open", () => { diff --git a/frontend/src/components/connect-to-github-modal.tsx b/frontend/src/components/connect-to-github-modal.tsx deleted file mode 100644 index 74b2ff642823..000000000000 --- a/frontend/src/components/connect-to-github-modal.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { I18nKey } from "#/i18n/declaration"; -import { useAuth } from "#/context/auth-context"; -import { CustomInput } from "./ui/custom-input"; -import { ModalButton } from "./ui/buttons/modal-button"; -import { ModalBody } from "./modals/modal-body"; -import { - BaseModalTitle, - BaseModalDescription, -} from "./modals/confirmation-modals/base-modal"; - -interface ConnectToGitHubModalProps { - onClose: () => void; -} - -export function ConnectToGitHubModal({ onClose }: ConnectToGitHubModalProps) { - const { gitHubToken, setGitHubToken } = useAuth(); - const { t } = useTranslation(); - - const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - const formData = new FormData(event.currentTarget); - const ghToken = formData.get("ghToken")?.toString(); - - if (ghToken) setGitHubToken(ghToken); - onClose(); - }; - - return ( - <ModalBody> - <div className="flex flex-col gap-2 self-start"> - <BaseModalTitle title="Connect to GitHub" /> - <BaseModalDescription - description={ - <span> - {t(I18nKey.CONNECT_TO_GITHUB_MODAL$GET_YOUR_TOKEN)}{" "} - <a - href="https://github.com/settings/tokens/new?description=openhands-app&scopes=repo,user,workflow" - target="_blank" - rel="noreferrer noopener" - className="text-[#791B80] underline" - > - {t(I18nKey.CONNECT_TO_GITHUB_MODAL$HERE)} - </a> - </span> - } - /> - </div> - <form onSubmit={handleSubmit} className="w-full flex flex-col gap-6"> - <CustomInput - label="GitHub Token" - name="ghToken" - required - type="password" - defaultValue={gitHubToken ?? ""} - /> - - <div className="flex flex-col gap-2 w-full"> - <ModalButton - testId="connect-to-github" - type="submit" - text={t(I18nKey.CONNECT_TO_GITHUB_MODAL$CONNECT)} - className="bg-[#791B80] w-full" - /> - <ModalButton - onClick={onClose} - text={t(I18nKey.CONNECT_TO_GITHUB_MODAL$CLOSE)} - className="bg-[#737373] w-full" - /> - </div> - </form> - </ModalBody> - ); -} diff --git a/frontend/src/components/features/chat/chat-interface.tsx b/frontend/src/components/features/chat/chat-interface.tsx index 33eb3cb47551..bdc6126b2f56 100644 --- a/frontend/src/components/features/chat/chat-interface.tsx +++ b/frontend/src/components/features/chat/chat-interface.tsx @@ -16,9 +16,9 @@ import { ContinueButton } from "../../ui/buttons/continue-button"; import { ScrollToBottomButton } from "../../ui/buttons/scroll-to-bottom-button"; import { useWsClient } from "#/context/ws-client-provider"; import { Messages } from "./messages"; -import { LoadingSpinner } from "../../ui/loading-spinner"; import { ChatSuggestions } from "./chat-suggestions"; import { ActionSuggestions } from "./action-suggestions"; +import { LoadingSpinner } from "#/components/ui/loading-spinner"; export function ChatInterface() { const { send, isLoadingMessages } = useWsClient(); @@ -81,7 +81,11 @@ export function ChatInterface() { onScroll={(e) => onChatBodyScroll(e.currentTarget)} className="flex flex-col grow overflow-y-auto overflow-x-hidden px-4 pt-4 gap-2" > - {isLoadingMessages && <LoadingSpinner />} + {isLoadingMessages && ( + <div className="flex justify-center"> + <LoadingSpinner size="small" /> + </div> + )} {!isLoadingMessages && ( <Messages diff --git a/frontend/src/components/features/project-menu/ProjectMenuCard.tsx b/frontend/src/components/features/project-menu/ProjectMenuCard.tsx index 8d2fca9b60a5..a83388707a0c 100644 --- a/frontend/src/components/features/project-menu/ProjectMenuCard.tsx +++ b/frontend/src/components/features/project-menu/ProjectMenuCard.tsx @@ -11,7 +11,7 @@ import { ProjectMenuCardContextMenu } from "./project.menu-card-context-menu"; import { ProjectMenuDetailsPlaceholder } from "./project-menu-details-placeholder"; import { ProjectMenuDetails } from "./project-menu-details"; import { downloadWorkspace } from "#/utils/download-workspace"; -import { LoadingSpinner } from "../../modals/loading-project"; +import { LoadingSpinner } from "../../ui/loading-spinner"; import { useWsClient } from "#/context/ws-client-provider"; interface ProjectMenuCardProps { diff --git a/frontend/src/components/features/sidebar/sidebar.tsx b/frontend/src/components/features/sidebar/sidebar.tsx index b689e19ffd2c..959ce4bc7db4 100644 --- a/frontend/src/components/features/sidebar/sidebar.tsx +++ b/frontend/src/components/features/sidebar/sidebar.tsx @@ -1,6 +1,5 @@ import React from "react"; import { useLocation } from "react-router-dom"; -import { LoadingSpinner } from "#/components/modals/loading-project"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useGitHubUser } from "#/hooks/query/use-github-user"; @@ -8,11 +7,12 @@ import { useIsAuthed } from "#/hooks/query/use-is-authed"; import { AllHandsLogoButton } from "#/components/ui/buttons/all-hands-logo-button"; import { DocsButton } from "#/components/ui/buttons/docs-button"; import { SettingsButton } from "#/components/ui/buttons/settings-button"; -import { AccountSettingsModal } from "#/components/account-settings-modal"; -import { ExitProjectConfirmationModal } from "#/components/exit-project-confirmation-modal"; -import { SettingsModal } from "#/components/settings-modal"; +import { AccountSettingsModal } from "#/components/modals/account-settings/account-settings-modal"; +import { SettingsModal } from "#/components/modals/settings/settings-modal"; import { UserActions } from "./user-actions"; import { ExitProjectButton } from "../../ui/buttons/exit-project-button"; +import { ExitProjectConfirmationModal } from "#/components/modals/exit-project-confirmation-modal"; +import { LoadingSpinner } from "#/components/ui/loading-spinner"; export function Sidebar() { const location = useLocation(); diff --git a/frontend/src/components/features/sidebar/user-avatar.tsx b/frontend/src/components/features/sidebar/user-avatar.tsx index 9c2e2a6b7f17..5c589860158e 100644 --- a/frontend/src/components/features/sidebar/user-avatar.tsx +++ b/frontend/src/components/features/sidebar/user-avatar.tsx @@ -1,7 +1,7 @@ import DefaultUserAvatar from "#/icons/default-user.svg?react"; import { cn } from "#/utils/utils"; import { Avatar } from "./avatar"; -import { LoadingSpinner } from "../../modals/loading-project"; +import { LoadingSpinner } from "../../ui/loading-spinner"; interface UserAvatarProps { onClick: () => void; diff --git a/frontend/src/components/modals/account-settings-form.tsx b/frontend/src/components/modals/account-settings-form.tsx deleted file mode 100644 index 026f26495d2c..000000000000 --- a/frontend/src/components/modals/account-settings-form.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { - BaseModalDescription, - BaseModalTitle, -} from "./confirmation-modals/base-modal"; -import { ModalBody } from "./modal-body"; -import { ModalButton } from "../ui/buttons/modal-button"; -import { FormFieldset } from "../ui/form-fieldset"; -import { CustomInput } from "../ui/custom-input"; -import { AvailableLanguages } from "#/i18n"; -import { I18nKey } from "#/i18n/declaration"; -import { useAuth } from "#/context/auth-context"; -import { useUserPrefs } from "#/context/user-prefs-context"; -import { handleCaptureConsent } from "#/utils/handle-capture-consent"; - -interface AccountSettingsFormProps { - onClose: () => void; - selectedLanguage: string; - gitHubError: boolean; - analyticsConsent: string | null; -} - -export function AccountSettingsForm({ - onClose, - selectedLanguage, - gitHubError, - analyticsConsent, -}: AccountSettingsFormProps) { - const { gitHubToken, setGitHubToken, logout } = useAuth(); - const { saveSettings } = useUserPrefs(); - const { t } = useTranslation(); - - const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - const formData = new FormData(event.currentTarget); - - const ghToken = formData.get("ghToken")?.toString(); - const language = formData.get("language")?.toString(); - const analytics = formData.get("analytics")?.toString() === "on"; - - if (ghToken) setGitHubToken(ghToken); - - // The form returns the language label, so we need to find the corresponding - // language key to save it in the settings - if (language) { - const languageKey = AvailableLanguages.find( - ({ label }) => label === language, - )?.value; - - if (languageKey) saveSettings({ LANGUAGE: languageKey }); - } - - handleCaptureConsent(analytics); - const ANALYTICS = analytics.toString(); - localStorage.setItem("analytics-consent", ANALYTICS); - - onClose(); - }; - - return ( - <ModalBody> - <form className="flex flex-col w-full gap-6" onSubmit={handleSubmit}> - <div className="w-full flex flex-col gap-2"> - <BaseModalTitle title="Account Settings" /> - - <FormFieldset - id="language" - label="Language" - defaultSelectedKey={selectedLanguage} - isClearable={false} - items={AvailableLanguages.map(({ label, value: key }) => ({ - key, - value: label, - }))} - /> - - <CustomInput - name="ghToken" - label="GitHub Token" - type="password" - defaultValue={gitHubToken ?? ""} - /> - <BaseModalDescription> - {t(I18nKey.CONNECT_TO_GITHUB_MODAL$GET_YOUR_TOKEN)}{" "} - <a - href="https://github.com/settings/tokens/new?description=openhands-app&scopes=repo,user,workflow" - target="_blank" - rel="noreferrer noopener" - className="text-[#791B80] underline" - > - {t(I18nKey.CONNECT_TO_GITHUB_MODAL$HERE)} - </a> - </BaseModalDescription> - {gitHubError && ( - <p className="text-danger text-xs"> - {t(I18nKey.ACCOUNT_SETTINGS_MODAL$GITHUB_TOKEN_INVALID)} - </p> - )} - {gitHubToken && !gitHubError && ( - <ModalButton - variant="text-like" - text={t(I18nKey.ACCOUNT_SETTINGS_MODAL$DISCONNECT)} - onClick={() => { - logout(); - onClose(); - }} - className="text-danger self-start" - /> - )} - </div> - - <label className="flex gap-2 items-center self-start"> - <input - name="analytics" - type="checkbox" - defaultChecked={analyticsConsent === "true"} - /> - Enable analytics - </label> - - <div className="flex flex-col gap-2 w-full"> - <ModalButton - type="submit" - intent="account" - text={t(I18nKey.ACCOUNT_SETTINGS_MODAL$SAVE)} - className="bg-[#4465DB]" - /> - <ModalButton - text={t(I18nKey.ACCOUNT_SETTINGS_MODAL$CLOSE)} - onClick={onClose} - className="bg-[#737373]" - /> - </div> - </form> - </ModalBody> - ); -} diff --git a/frontend/src/components/account-settings-form.tsx b/frontend/src/components/modals/account-settings/account-settings-form.tsx similarity index 94% rename from frontend/src/components/account-settings-form.tsx rename to frontend/src/components/modals/account-settings/account-settings-form.tsx index aa11558fa50e..92286516df64 100644 --- a/frontend/src/components/account-settings-form.tsx +++ b/frontend/src/components/modals/account-settings/account-settings-form.tsx @@ -1,18 +1,18 @@ import React from "react"; import { useTranslation } from "react-i18next"; +import { + BaseModalDescription, + BaseModalTitle, +} from "../confirmation-modals/base-modal"; +import { ModalBody } from "../modal-body"; +import { ModalButton } from "../../ui/buttons/modal-button"; +import { FormFieldset } from "../../ui/form-fieldset"; +import { CustomInput } from "../../ui/custom-input"; import { AvailableLanguages } from "#/i18n"; import { I18nKey } from "#/i18n/declaration"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { handleCaptureConsent } from "#/utils/handle-capture-consent"; -import { CustomInput } from "./ui/custom-input"; -import { FormFieldset } from "./ui/form-fieldset"; -import { ModalButton } from "./ui/buttons/modal-button"; -import { ModalBody } from "./modals/modal-body"; -import { - BaseModalTitle, - BaseModalDescription, -} from "./modals/confirmation-modals/base-modal"; interface AccountSettingsFormProps { onClose: () => void; diff --git a/frontend/src/components/account-settings-modal.tsx b/frontend/src/components/modals/account-settings/account-settings-modal.tsx similarity index 96% rename from frontend/src/components/account-settings-modal.tsx rename to frontend/src/components/modals/account-settings/account-settings-modal.tsx index d1568940486c..b9ab8c313217 100644 --- a/frontend/src/components/account-settings-modal.tsx +++ b/frontend/src/components/modals/account-settings/account-settings-modal.tsx @@ -1,4 +1,4 @@ -import { AccountSettingsForm } from "#/components/modals/account-settings-form"; +import { AccountSettingsForm } from "#/components/modals/account-settings/account-settings-form"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useGitHubUser } from "#/hooks/query/use-github-user"; diff --git a/frontend/src/components/modals/base-modal/base-modal.tsx b/frontend/src/components/modals/base-modal/base-modal.tsx index 128461fa0cc3..ccb6d17a180a 100644 --- a/frontend/src/components/modals/base-modal/base-modal.tsx +++ b/frontend/src/components/modals/base-modal/base-modal.tsx @@ -22,7 +22,7 @@ interface BaseModalProps { testID?: string; } -function BaseModal({ +export function BaseModal({ isOpen, onOpenChange, title, @@ -67,5 +67,3 @@ function BaseModal({ </Modal> ); } - -export default BaseModal; diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/modals/confirmation-modals/base-modal.tsx index 8dad0bda5305..cdd20965240e 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/base-modal.tsx @@ -40,7 +40,7 @@ interface BaseModalProps { buttons: ButtonConfig[]; } -function BaseModal({ title, description, buttons }: BaseModalProps) { +export function BaseModal({ title, description, buttons }: BaseModalProps) { return ( <ModalBody> <div className="flex flex-col gap-2 self-start"> @@ -61,5 +61,3 @@ function BaseModal({ title, description, buttons }: BaseModalProps) { </ModalBody> ); } - -export default BaseModal; diff --git a/frontend/src/components/modals/confirmation-modals/danger-modal.tsx b/frontend/src/components/modals/confirmation-modals/danger-modal.tsx index 0f14ff76f4ef..fa6d468d0072 100644 --- a/frontend/src/components/modals/confirmation-modals/danger-modal.tsx +++ b/frontend/src/components/modals/confirmation-modals/danger-modal.tsx @@ -1,4 +1,4 @@ -import BaseModal from "./base-modal"; +import { BaseModal } from "./base-modal"; interface DangerModalProps { title: string; diff --git a/frontend/src/components/exit-project-confirmation-modal.tsx b/frontend/src/components/modals/exit-project-confirmation-modal.tsx similarity index 100% rename from frontend/src/components/exit-project-confirmation-modal.tsx rename to frontend/src/components/modals/exit-project-confirmation-modal.tsx diff --git a/frontend/src/components/modals/loading-project.tsx b/frontend/src/components/modals/loading-project.tsx deleted file mode 100644 index e851656d245e..000000000000 --- a/frontend/src/components/modals/loading-project.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useTranslation } from "react-i18next"; -import LoadingSpinnerOuter from "#/icons/loading-outer.svg?react"; -import { cn } from "#/utils/utils"; -import { ModalBody } from "./modal-body"; -import { I18nKey } from "#/i18n/declaration"; - -interface LoadingSpinnerProps { - size: "small" | "large"; -} - -export function LoadingSpinner({ size }: LoadingSpinnerProps) { - const sizeStyle = - size === "small" ? "w-[25px] h-[25px]" : "w-[50px] h-[50px]"; - - return ( - <div data-testid="loading-spinner" className={cn("relative", sizeStyle)}> - <div - className={cn( - "rounded-full border-4 border-[#525252] absolute", - sizeStyle, - )} - /> - <LoadingSpinnerOuter className={cn("absolute animate-spin", sizeStyle)} /> - </div> - ); -} - -interface LoadingProjectModalProps { - message?: string; -} - -function LoadingProjectModal({ message }: LoadingProjectModalProps) { - const { t } = useTranslation(); - - return ( - <ModalBody> - <span className="text-xl leading-6 -tracking-[0.01em] font-semibold"> - {message || t(I18nKey.LOADING_PROJECT$LOADING)} - </span> - <LoadingSpinner size="large" /> - </ModalBody> - ); -} - -export default LoadingProjectModal; diff --git a/frontend/src/components/modals/security/security.tsx b/frontend/src/components/modals/security/security.tsx index f5001fa9a8f9..ba30bc08c851 100644 --- a/frontend/src/components/modals/security/security.tsx +++ b/frontend/src/components/modals/security/security.tsx @@ -1,8 +1,8 @@ import React from "react"; import { useTranslation } from "react-i18next"; import SecurityInvariant from "./invariant/invariant"; -import BaseModal from "../base-modal/base-modal"; import { I18nKey } from "#/i18n/declaration"; +import { BaseModal } from "../base-modal/base-modal"; interface SecurityProps { isOpen: boolean; diff --git a/frontend/src/components/settings-form.tsx b/frontend/src/components/modals/settings/settings-form.tsx similarity index 93% rename from frontend/src/components/settings-form.tsx rename to frontend/src/components/modals/settings/settings-form.tsx index 71db93b5bc80..d5c5d97efcb5 100644 --- a/frontend/src/components/settings-form.tsx +++ b/frontend/src/components/modals/settings/settings-form.tsx @@ -7,8 +7,8 @@ import { ModelSelector } from "#/components/modals/settings/model-selector"; import { getDefaultSettings, Settings } from "#/services/settings"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { extractModelAndProvider } from "#/utils/extract-model-and-provider"; -import { ModalButton } from "./ui/buttons/modal-button"; -import { DangerModal } from "./modals/confirmation-modals/danger-modal"; +import { ModalButton } from "../../ui/buttons/modal-button"; +import { DangerModal } from "../confirmation-modals/danger-modal"; import { I18nKey } from "#/i18n/declaration"; import { extractSettings, @@ -17,13 +17,13 @@ import { } from "#/utils/settings-utils"; import { useEndSession } from "#/hooks/use-end-session"; import { useUserPrefs } from "#/context/user-prefs-context"; -import { AdvancedOptionSwitch } from "./ui/inputs/advanced-option-switch"; -import { CustomModelInput } from "./ui/inputs/custom-model-input"; -import { BaseUrlInput } from "./ui/inputs/base-url-input"; -import { AgentInput } from "./ui/inputs/agent-input"; -import { APIKeyInput } from "./ui/inputs/api-key-input"; -import { SecurityAnalyzerInput } from "./ui/inputs/security-analyzers-input"; -import { ConfirmationModeSwitch } from "./ui/inputs/confirmation-mode-switch"; +import { AdvancedOptionSwitch } from "../../ui/inputs/advanced-option-switch"; +import { CustomModelInput } from "../../ui/inputs/custom-model-input"; +import { BaseUrlInput } from "../../ui/inputs/base-url-input"; +import { AgentInput } from "../../ui/inputs/agent-input"; +import { APIKeyInput } from "../../ui/inputs/api-key-input"; +import { SecurityAnalyzerInput } from "../../ui/inputs/security-analyzers-input"; +import { ConfirmationModeSwitch } from "../../ui/inputs/confirmation-mode-switch"; interface SettingsFormProps { disabled?: boolean; diff --git a/frontend/src/components/settings-modal.tsx b/frontend/src/components/modals/settings/settings-modal.tsx similarity index 92% rename from frontend/src/components/settings-modal.tsx rename to frontend/src/components/modals/settings/settings-modal.tsx index 7b3917c8324d..d3702d94c59c 100644 --- a/frontend/src/components/settings-modal.tsx +++ b/frontend/src/components/modals/settings/settings-modal.tsx @@ -1,8 +1,8 @@ -import { SettingsForm } from "#/components/settings-form"; -import { LoadingSpinner } from "#/components/modals/loading-project"; +import { SettingsForm } from "#/components/modals/settings/settings-form"; import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useAIConfigOptions } from "#/hooks/query/use-ai-config-options"; +import { LoadingSpinner } from "#/components/ui/loading-spinner"; interface SettingsModalProps { onClose: () => void; diff --git a/frontend/src/components/ui/loading-spinner.tsx b/frontend/src/components/ui/loading-spinner.tsx index ba119cb20c6b..5f19d0fe4de6 100644 --- a/frontend/src/components/ui/loading-spinner.tsx +++ b/frontend/src/components/ui/loading-spinner.tsx @@ -1,7 +1,23 @@ -export function LoadingSpinner() { +import LoadingSpinnerOuter from "#/icons/loading-outer.svg?react"; +import { cn } from "#/utils/utils"; + +interface LoadingSpinnerProps { + size: "small" | "large"; +} + +export function LoadingSpinner({ size }: LoadingSpinnerProps) { + const sizeStyle = + size === "small" ? "w-[25px] h-[25px]" : "w-[50px] h-[50px]"; + return ( - <div className="flex justify-center"> - <div className="w-6 h-6 border-2 border-t-[4px] border-primary-500 rounded-full animate-spin" /> + <div data-testid="loading-spinner" className={cn("relative", sizeStyle)}> + <div + className={cn( + "rounded-full border-4 border-[#525252] absolute", + sizeStyle, + )} + /> + <LoadingSpinnerOuter className={cn("absolute animate-spin", sizeStyle)} /> </div> ); } From cbbe55e09da0c67611a3f5a6ebd78c8825d7aa74 Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:21:02 +0400 Subject: [PATCH 12/13] Update README --- frontend/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/README.md b/frontend/README.md index 7d05e8a9ba3c..65493728aa39 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -9,6 +9,7 @@ This is the frontend of the OpenHands project. It is a React application that pr - Remix SPA Mode (React + Vite + React Router) - TypeScript - Redux +- TanStack Query - Tailwind CSS - i18next - React Testing Library @@ -85,7 +86,7 @@ frontend ├── src │ ├── api # API calls │ ├── assets -│ ├── components # Reusable components +│ ├── components │ ├── context # Local state management │ ├── hooks # Custom hooks │ ├── i18n # Internationalization @@ -99,6 +100,18 @@ frontend └── .env.sample # Sample environment variables ``` +#### Components + +Components are organized into folders based on their **domain**, **feature**, or **shared functionality**. + +```sh +components +├── features # Domain-specific components +├── layout +├── modals +└── ui # Shared UI components +``` + ### Features - Real-time updates with WebSockets From b89e1b070c0492a91edecdedadda53cedb0362eb Mon Sep 17 00:00:00 2001 From: amanape <83104063+amanape@users.noreply.github.com> Date: Thu, 28 Nov 2024 00:06:04 +0400 Subject: [PATCH 13/13] Rename ui to shared and move modals to shared --- .../modals/base-modal/base-modal.test.tsx | 2 +- .../modals/settings/model-selector.test.tsx | 2 +- .../analytics-consent-form-modal.tsx | 8 ++++---- .../components/features/chat/chat-input.tsx | 4 ++-- .../features/chat/chat-interface.tsx | 6 +++--- .../components/features/chat/chat-message.tsx | 2 +- .../src/components/features/chat/messages.tsx | 2 +- .../features/controls/agent-control-bar.tsx | 2 +- .../features/editor/editor-actions.tsx | 2 +- .../features/feedback/feedback-actions.tsx | 2 +- .../features/feedback/feedback-form.tsx | 2 +- .../features/feedback/feedback-modal.tsx | 8 ++++---- .../file-explorer/file-explorer-actions.tsx | 6 +++--- .../features/file-explorer/file-explorer.tsx | 2 +- .../github-repositories-suggestion-box.tsx | 6 +++--- .../features/images/image-preview.tsx | 2 +- .../components/features/jupyter/jupyter.tsx | 2 +- .../features/project-menu/ProjectMenuCard.tsx | 6 +++--- .../components/features/sidebar/sidebar.tsx | 16 +++++++-------- .../features/sidebar/user-avatar.tsx | 2 +- .../suggestions/suggestion-bubble.tsx | 2 +- .../features/waitlist/waitlist-modal.tsx | 6 +++--- .../{ui => shared}/action-tooltip.tsx | 0 .../{ui => shared}/buttons/action-button.tsx | 0 .../buttons/all-hands-logo-button.tsx | 0 .../buttons/confirmation-buttons.tsx | 0 .../buttons/continue-button.tsx | 0 .../buttons/copy-to-clipboard-button.tsx | 0 .../{ui => shared}/buttons/docs-button.tsx | 0 .../buttons/editor-action-button.tsx | 0 .../buttons/exit-project-button.tsx | 0 .../buttons/feedback-action-button.tsx | 0 .../{ui => shared}/buttons/icon-button.tsx | 0 .../{ui => shared}/buttons/modal-button.tsx | 0 .../buttons/open-vscode-button.tsx | 0 .../{ui => shared}/buttons/refresh-button.tsx | 0 .../buttons/refresh-icon-button.tsx | 2 +- .../{ui => shared}/buttons/remove-button.tsx | 0 .../buttons/scroll-to-bottom-button.tsx | 0 .../buttons/settings-button.tsx | 0 .../{ui => shared}/buttons/stop-button.tsx | 0 .../{ui => shared}/buttons/submit-button.tsx | 0 .../buttons/toggle-workspace-icon-button.tsx | 2 +- .../buttons/upload-icon-button.tsx | 2 +- .../{ui => shared}/custom-input.tsx | 0 .../components/{ui => shared}/error-toast.tsx | 0 .../{ui => shared}/form-fieldset.tsx | 0 .../{ui => shared}/hero-heading.tsx | 0 .../inputs/advanced-option-switch.tsx | 0 .../{ui => shared}/inputs/agent-input.tsx | 0 .../{ui => shared}/inputs/api-key-input.tsx | 0 .../{ui => shared}/inputs/base-url-input.tsx | 0 .../inputs/confirmation-mode-switch.tsx | 0 .../inputs/custom-model-input.tsx | 0 .../inputs/security-analyzers-input.tsx | 0 .../{ui => shared}/loading-spinner.tsx | 0 .../account-settings-form.tsx | 6 +++--- .../account-settings-modal.tsx | 4 ++-- .../modals/base-modal/base-modal.tsx | 0 .../modals/base-modal/footer-content.tsx | 0 .../modals/base-modal/header-content.tsx | 0 .../modals/confirmation-modals/base-modal.tsx | 2 +- .../confirmation-modals/danger-modal.tsx | 0 .../modals/connect-to-github-modal.tsx | 4 ++-- .../exit-project-confirmation-modal.tsx | 4 ++-- .../{ => shared}/modals/modal-backdrop.tsx | 0 .../{ => shared}/modals/modal-body.tsx | 0 .../modals/security/invariant/assets/logo.tsx | 0 .../modals/security/invariant/invariant.tsx | 0 .../{ => shared}/modals/security/security.tsx | 0 .../modals/settings/model-selector.tsx | 0 .../modals/settings/settings-form.tsx | 20 +++++++++---------- .../modals/settings/settings-modal.tsx | 6 +++--- .../components/{ui => shared}/task-form.tsx | 0 frontend/src/routes/_oh._index/route.tsx | 4 ++-- frontend/src/routes/_oh.app/route.tsx | 2 +- frontend/src/utils/display-error-toast.tsx | 2 +- 77 files changed, 76 insertions(+), 76 deletions(-) rename frontend/src/components/{ui => shared}/action-tooltip.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/action-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/all-hands-logo-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/confirmation-buttons.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/continue-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/copy-to-clipboard-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/docs-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/editor-action-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/exit-project-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/feedback-action-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/icon-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/modal-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/open-vscode-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/refresh-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/refresh-icon-button.tsx (87%) rename frontend/src/components/{ui => shared}/buttons/remove-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/scroll-to-bottom-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/settings-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/stop-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/submit-button.tsx (100%) rename frontend/src/components/{ui => shared}/buttons/toggle-workspace-icon-button.tsx (91%) rename frontend/src/components/{ui => shared}/buttons/upload-icon-button.tsx (87%) rename frontend/src/components/{ui => shared}/custom-input.tsx (100%) rename frontend/src/components/{ui => shared}/error-toast.tsx (100%) rename frontend/src/components/{ui => shared}/form-fieldset.tsx (100%) rename frontend/src/components/{ui => shared}/hero-heading.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/advanced-option-switch.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/agent-input.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/api-key-input.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/base-url-input.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/confirmation-mode-switch.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/custom-model-input.tsx (100%) rename frontend/src/components/{ui => shared}/inputs/security-analyzers-input.tsx (100%) rename frontend/src/components/{ui => shared}/loading-spinner.tsx (100%) rename frontend/src/components/{ => shared}/modals/account-settings/account-settings-form.tsx (96%) rename frontend/src/components/{ => shared}/modals/account-settings/account-settings-modal.tsx (81%) rename frontend/src/components/{ => shared}/modals/base-modal/base-modal.tsx (100%) rename frontend/src/components/{ => shared}/modals/base-modal/footer-content.tsx (100%) rename frontend/src/components/{ => shared}/modals/base-modal/header-content.tsx (100%) rename frontend/src/components/{ => shared}/modals/confirmation-modals/base-modal.tsx (95%) rename frontend/src/components/{ => shared}/modals/confirmation-modals/danger-modal.tsx (100%) rename frontend/src/components/{ => shared}/modals/connect-to-github-modal.tsx (95%) rename frontend/src/components/{ => shared}/modals/exit-project-confirmation-modal.tsx (87%) rename frontend/src/components/{ => shared}/modals/modal-backdrop.tsx (100%) rename frontend/src/components/{ => shared}/modals/modal-body.tsx (100%) rename frontend/src/components/{ => shared}/modals/security/invariant/assets/logo.tsx (100%) rename frontend/src/components/{ => shared}/modals/security/invariant/invariant.tsx (100%) rename frontend/src/components/{ => shared}/modals/security/security.tsx (100%) rename frontend/src/components/{ => shared}/modals/settings/model-selector.tsx (100%) rename frontend/src/components/{ => shared}/modals/settings/settings-form.tsx (92%) rename frontend/src/components/{ => shared}/modals/settings/settings-modal.tsx (88%) rename frontend/src/components/{ui => shared}/task-form.tsx (100%) diff --git a/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx b/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx index 6824fd927eed..563cbca6c45a 100644 --- a/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx +++ b/frontend/__tests__/components/modals/base-modal/base-modal.test.tsx @@ -1,7 +1,7 @@ import { render, screen, act } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, it, vi, expect } from "vitest"; -import { BaseModal } from "#/components/modals/base-modal/base-modal"; +import { BaseModal } from "#/components/shared/modals/base-modal/base-modal"; describe("BaseModal", () => { it("should render if the modal is open", () => { diff --git a/frontend/__tests__/components/modals/settings/model-selector.test.tsx b/frontend/__tests__/components/modals/settings/model-selector.test.tsx index 2823d988eca7..8da2fec14475 100644 --- a/frontend/__tests__/components/modals/settings/model-selector.test.tsx +++ b/frontend/__tests__/components/modals/settings/model-selector.test.tsx @@ -1,7 +1,7 @@ import { describe, it, expect } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { ModelSelector } from "#/components/modals/settings/model-selector"; +import { ModelSelector } from "#/components/shared/modals/settings/model-selector"; describe("ModelSelector", () => { const models = { diff --git a/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx b/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx index 0946a2880fc9..02fabd81aedc 100644 --- a/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx +++ b/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx @@ -1,10 +1,10 @@ -import { ModalBackdrop } from "../../modals/modal-backdrop"; -import { ModalBody } from "../../modals/modal-body"; -import { ModalButton } from "../../ui/buttons/modal-button"; +import { ModalButton } from "#/components/shared/buttons/modal-button"; import { BaseModalTitle, BaseModalDescription, -} from "../../modals/confirmation-modals/base-modal"; +} from "#/components/shared/modals/confirmation-modals/base-modal"; +import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop"; +import { ModalBody } from "#/components/shared/modals/modal-body"; import { handleCaptureConsent } from "#/utils/handle-capture-consent"; interface AnalyticsConsentFormModalProps { diff --git a/frontend/src/components/features/chat/chat-input.tsx b/frontend/src/components/features/chat/chat-input.tsx index af5be4d8336f..815eb1933720 100644 --- a/frontend/src/components/features/chat/chat-input.tsx +++ b/frontend/src/components/features/chat/chat-input.tsx @@ -1,8 +1,8 @@ import React from "react"; import TextareaAutosize from "react-textarea-autosize"; import { cn } from "#/utils/utils"; -import { SubmitButton } from "../../ui/buttons/submit-button"; -import { StopButton } from "../../ui/buttons/stop-button"; +import { SubmitButton } from "#/components/shared/buttons/submit-button"; +import { StopButton } from "#/components/shared/buttons/stop-button"; interface ChatInputProps { name?: string; diff --git a/frontend/src/components/features/chat/chat-interface.tsx b/frontend/src/components/features/chat/chat-interface.tsx index bdc6126b2f56..d87ded048906 100644 --- a/frontend/src/components/features/chat/chat-interface.tsx +++ b/frontend/src/components/features/chat/chat-interface.tsx @@ -12,13 +12,13 @@ import { generateAgentStateChangeEvent } from "#/services/agent-state-service"; import { FeedbackModal } from "../feedback/feedback-modal"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; import { TypingIndicator } from "./typing-indicator"; -import { ContinueButton } from "../../ui/buttons/continue-button"; -import { ScrollToBottomButton } from "../../ui/buttons/scroll-to-bottom-button"; import { useWsClient } from "#/context/ws-client-provider"; import { Messages } from "./messages"; import { ChatSuggestions } from "./chat-suggestions"; import { ActionSuggestions } from "./action-suggestions"; -import { LoadingSpinner } from "#/components/ui/loading-spinner"; +import { ContinueButton } from "#/components/shared/buttons/continue-button"; +import { ScrollToBottomButton } from "#/components/shared/buttons/scroll-to-bottom-button"; +import { LoadingSpinner } from "#/components/shared/loading-spinner"; export function ChatInterface() { const { send, isLoadingMessages } = useWsClient(); diff --git a/frontend/src/components/features/chat/chat-message.tsx b/frontend/src/components/features/chat/chat-message.tsx index 96e530e5e527..96d21dfcada9 100644 --- a/frontend/src/components/features/chat/chat-message.tsx +++ b/frontend/src/components/features/chat/chat-message.tsx @@ -4,7 +4,7 @@ import remarkGfm from "remark-gfm"; import { code } from "../markdown/code"; import { cn } from "#/utils/utils"; import { ul, ol } from "../markdown/list"; -import { CopyToClipboardButton } from "../../ui/buttons/copy-to-clipboard-button"; +import { CopyToClipboardButton } from "#/components/shared/buttons/copy-to-clipboard-button"; interface ChatMessageProps { type: "user" | "assistant"; diff --git a/frontend/src/components/features/chat/messages.tsx b/frontend/src/components/features/chat/messages.tsx index 8307238eac08..0b2f0789620a 100644 --- a/frontend/src/components/features/chat/messages.tsx +++ b/frontend/src/components/features/chat/messages.tsx @@ -1,5 +1,5 @@ import { ChatMessage } from "#/components/features/chat/chat-message"; -import { ConfirmationButtons } from "#/components/ui/buttons/confirmation-buttons"; +import { ConfirmationButtons } from "#/components/shared/buttons/confirmation-buttons"; import { ImageCarousel } from "../images/image-carousel"; import { ErrorMessage } from "./error-message"; diff --git a/frontend/src/components/features/controls/agent-control-bar.tsx b/frontend/src/components/features/controls/agent-control-bar.tsx index cb8e6009327f..dad718533f6e 100644 --- a/frontend/src/components/features/controls/agent-control-bar.tsx +++ b/frontend/src/components/features/controls/agent-control-bar.tsx @@ -6,7 +6,7 @@ import { RootState } from "#/store"; import AgentState from "#/types/agent-state"; import { useWsClient } from "#/context/ws-client-provider"; import { IGNORE_TASK_STATE_MAP } from "#/ignore-task-state-map.constant"; -import { ActionButton } from "../../ui/buttons/action-button"; +import { ActionButton } from "#/components/shared/buttons/action-button"; export function AgentControlBar() { const { send } = useWsClient(); diff --git a/frontend/src/components/features/editor/editor-actions.tsx b/frontend/src/components/features/editor/editor-actions.tsx index 28e375c58573..1f3accf6252a 100644 --- a/frontend/src/components/features/editor/editor-actions.tsx +++ b/frontend/src/components/features/editor/editor-actions.tsx @@ -1,4 +1,4 @@ -import { EditorActionButton } from "../../ui/buttons/editor-action-button"; +import { EditorActionButton } from "#/components/shared/buttons/editor-action-button"; interface EditorActionsProps { onSave: () => void; diff --git a/frontend/src/components/features/feedback/feedback-actions.tsx b/frontend/src/components/features/feedback/feedback-actions.tsx index 386c04c7d734..2293789c201f 100644 --- a/frontend/src/components/features/feedback/feedback-actions.tsx +++ b/frontend/src/components/features/feedback/feedback-actions.tsx @@ -1,6 +1,6 @@ import ThumbsUpIcon from "#/icons/thumbs-up.svg?react"; import ThumbDownIcon from "#/icons/thumbs-down.svg?react"; -import { FeedbackActionButton } from "../../ui/buttons/feedback-action-button"; +import { FeedbackActionButton } from "#/components/shared/buttons/feedback-action-button"; interface FeedbackActionsProps { onPositiveFeedback: () => void; diff --git a/frontend/src/components/features/feedback/feedback-form.tsx b/frontend/src/components/features/feedback/feedback-form.tsx index 6e2009c82623..31705a101493 100644 --- a/frontend/src/components/features/feedback/feedback-form.tsx +++ b/frontend/src/components/features/feedback/feedback-form.tsx @@ -1,8 +1,8 @@ import React from "react"; import hotToast from "react-hot-toast"; -import { ModalButton } from "../../ui/buttons/modal-button"; import { Feedback } from "#/api/open-hands.types"; import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback"; +import { ModalButton } from "#/components/shared/buttons/modal-button"; const FEEDBACK_VERSION = "1.0"; const VIEWER_PAGE = "https://www.all-hands.dev/share"; diff --git a/frontend/src/components/features/feedback/feedback-modal.tsx b/frontend/src/components/features/feedback/feedback-modal.tsx index 509343e4d544..a3e9d6264f56 100644 --- a/frontend/src/components/features/feedback/feedback-modal.tsx +++ b/frontend/src/components/features/feedback/feedback-modal.tsx @@ -1,10 +1,10 @@ -import { FeedbackForm } from "./feedback-form"; import { BaseModalTitle, BaseModalDescription, -} from "../../modals/confirmation-modals/base-modal"; -import { ModalBackdrop } from "../../modals/modal-backdrop"; -import { ModalBody } from "../../modals/modal-body"; +} from "#/components/shared/modals/confirmation-modals/base-modal"; +import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop"; +import { ModalBody } from "#/components/shared/modals/modal-body"; +import { FeedbackForm } from "./feedback-form"; interface FeedbackModalProps { onClose: () => void; diff --git a/frontend/src/components/features/file-explorer/file-explorer-actions.tsx b/frontend/src/components/features/file-explorer/file-explorer-actions.tsx index 847b8682f2dd..92698b87eabd 100644 --- a/frontend/src/components/features/file-explorer/file-explorer-actions.tsx +++ b/frontend/src/components/features/file-explorer/file-explorer-actions.tsx @@ -1,7 +1,7 @@ +import { RefreshIconButton } from "#/components/shared/buttons/refresh-icon-button"; +import { ToggleWorkspaceIconButton } from "#/components/shared/buttons/toggle-workspace-icon-button"; +import { UploadIconButton } from "#/components/shared/buttons/upload-icon-button"; import { cn } from "#/utils/utils"; -import { RefreshIconButton } from "../../ui/buttons/refresh-icon-button"; -import { ToggleWorkspaceIconButton } from "../../ui/buttons/toggle-workspace-icon-button"; -import { UploadIconButton } from "../../ui/buttons/upload-icon-button"; interface ExplorerActionsProps { onRefresh: () => void; diff --git a/frontend/src/components/features/file-explorer/file-explorer.tsx b/frontend/src/components/features/file-explorer/file-explorer.tsx index 47c04c99172d..b033cfb62126 100644 --- a/frontend/src/components/features/file-explorer/file-explorer.tsx +++ b/frontend/src/components/features/file-explorer/file-explorer.tsx @@ -13,7 +13,7 @@ import { cn } from "#/utils/utils"; import { Dropzone } from "./dropzone"; import { FileExplorerHeader } from "./file-explorer-header"; import { useVSCodeUrl } from "#/hooks/query/use-vscode-url"; -import { OpenVSCodeButton } from "../../ui/buttons/open-vscode-button"; +import { OpenVSCodeButton } from "#/components/shared/buttons/open-vscode-button"; interface FileExplorerProps { isOpen: boolean; diff --git a/frontend/src/components/features/github/github-repositories-suggestion-box.tsx b/frontend/src/components/features/github/github-repositories-suggestion-box.tsx index f45e408eb53d..f052e1f202f3 100644 --- a/frontend/src/components/features/github/github-repositories-suggestion-box.tsx +++ b/frontend/src/components/features/github/github-repositories-suggestion-box.tsx @@ -1,11 +1,11 @@ import React from "react"; import { isGitHubErrorReponse } from "#/api/github"; import { SuggestionBox } from "#/components/features/suggestions/suggestion-box"; -import { ConnectToGitHubModal } from "../../modals/connect-to-github-modal"; -import { ModalBackdrop } from "../../modals/modal-backdrop"; -import { ModalButton } from "../../ui/buttons/modal-button"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import { GitHubRepositorySelector } from "./github-repo-selector"; +import { ModalButton } from "#/components/shared/buttons/modal-button"; +import { ConnectToGitHubModal } from "#/components/shared/modals/connect-to-github-modal"; +import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop"; interface GitHubRepositoriesSuggestionBoxProps { handleSubmit: () => void; diff --git a/frontend/src/components/features/images/image-preview.tsx b/frontend/src/components/features/images/image-preview.tsx index f0fad3282af0..37dc314a4be8 100644 --- a/frontend/src/components/features/images/image-preview.tsx +++ b/frontend/src/components/features/images/image-preview.tsx @@ -1,4 +1,4 @@ -import { RemoveButton } from "../../ui/buttons/remove-button"; +import { RemoveButton } from "#/components/shared/buttons/remove-button"; import { Thumbnail } from "./thumbnail"; interface ImagePreviewProps { diff --git a/frontend/src/components/features/jupyter/jupyter.tsx b/frontend/src/components/features/jupyter/jupyter.tsx index fef5084d89ce..8ae871c520d0 100644 --- a/frontend/src/components/features/jupyter/jupyter.tsx +++ b/frontend/src/components/features/jupyter/jupyter.tsx @@ -3,7 +3,7 @@ import { useSelector } from "react-redux"; import { RootState } from "#/store"; import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom"; import { JupyterCell } from "./jupyter-cell"; -import { ScrollToBottomButton } from "../../ui/buttons/scroll-to-bottom-button"; +import { ScrollToBottomButton } from "#/components/shared/buttons/scroll-to-bottom-button"; interface JupyterEditorProps { maxWidth: number; diff --git a/frontend/src/components/features/project-menu/ProjectMenuCard.tsx b/frontend/src/components/features/project-menu/ProjectMenuCard.tsx index a83388707a0c..159edb9b5610 100644 --- a/frontend/src/components/features/project-menu/ProjectMenuCard.tsx +++ b/frontend/src/components/features/project-menu/ProjectMenuCard.tsx @@ -3,16 +3,16 @@ import { useDispatch } from "react-redux"; import toast from "react-hot-toast"; import posthog from "posthog-js"; import EllipsisH from "#/icons/ellipsis-h.svg?react"; -import { ModalBackdrop } from "../../modals/modal-backdrop"; -import { ConnectToGitHubModal } from "../../modals/connect-to-github-modal"; import { addUserMessage } from "#/state/chat-slice"; import { createChatMessage } from "#/services/chat-service"; import { ProjectMenuCardContextMenu } from "./project.menu-card-context-menu"; import { ProjectMenuDetailsPlaceholder } from "./project-menu-details-placeholder"; import { ProjectMenuDetails } from "./project-menu-details"; import { downloadWorkspace } from "#/utils/download-workspace"; -import { LoadingSpinner } from "../../ui/loading-spinner"; import { useWsClient } from "#/context/ws-client-provider"; +import { LoadingSpinner } from "#/components/shared/loading-spinner"; +import { ConnectToGitHubModal } from "#/components/shared/modals/connect-to-github-modal"; +import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop"; interface ProjectMenuCardProps { isConnectedToGitHub: boolean; diff --git a/frontend/src/components/features/sidebar/sidebar.tsx b/frontend/src/components/features/sidebar/sidebar.tsx index 959ce4bc7db4..f5345b2af2a9 100644 --- a/frontend/src/components/features/sidebar/sidebar.tsx +++ b/frontend/src/components/features/sidebar/sidebar.tsx @@ -4,15 +4,15 @@ import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useGitHubUser } from "#/hooks/query/use-github-user"; import { useIsAuthed } from "#/hooks/query/use-is-authed"; -import { AllHandsLogoButton } from "#/components/ui/buttons/all-hands-logo-button"; -import { DocsButton } from "#/components/ui/buttons/docs-button"; -import { SettingsButton } from "#/components/ui/buttons/settings-button"; -import { AccountSettingsModal } from "#/components/modals/account-settings/account-settings-modal"; -import { SettingsModal } from "#/components/modals/settings/settings-modal"; import { UserActions } from "./user-actions"; -import { ExitProjectButton } from "../../ui/buttons/exit-project-button"; -import { ExitProjectConfirmationModal } from "#/components/modals/exit-project-confirmation-modal"; -import { LoadingSpinner } from "#/components/ui/loading-spinner"; +import { AllHandsLogoButton } from "#/components/shared/buttons/all-hands-logo-button"; +import { DocsButton } from "#/components/shared/buttons/docs-button"; +import { ExitProjectButton } from "#/components/shared/buttons/exit-project-button"; +import { SettingsButton } from "#/components/shared/buttons/settings-button"; +import { LoadingSpinner } from "#/components/shared/loading-spinner"; +import { AccountSettingsModal } from "#/components/shared/modals/account-settings/account-settings-modal"; +import { ExitProjectConfirmationModal } from "#/components/shared/modals/exit-project-confirmation-modal"; +import { SettingsModal } from "#/components/shared/modals/settings/settings-modal"; export function Sidebar() { const location = useLocation(); diff --git a/frontend/src/components/features/sidebar/user-avatar.tsx b/frontend/src/components/features/sidebar/user-avatar.tsx index 5c589860158e..58a4af17386a 100644 --- a/frontend/src/components/features/sidebar/user-avatar.tsx +++ b/frontend/src/components/features/sidebar/user-avatar.tsx @@ -1,7 +1,7 @@ +import { LoadingSpinner } from "#/components/shared/loading-spinner"; import DefaultUserAvatar from "#/icons/default-user.svg?react"; import { cn } from "#/utils/utils"; import { Avatar } from "./avatar"; -import { LoadingSpinner } from "../../ui/loading-spinner"; interface UserAvatarProps { onClick: () => void; diff --git a/frontend/src/components/features/suggestions/suggestion-bubble.tsx b/frontend/src/components/features/suggestions/suggestion-bubble.tsx index 611a207ebd8c..5679799c6ed1 100644 --- a/frontend/src/components/features/suggestions/suggestion-bubble.tsx +++ b/frontend/src/components/features/suggestions/suggestion-bubble.tsx @@ -1,5 +1,5 @@ +import { RefreshButton } from "#/components/shared/buttons/refresh-button"; import Lightbulb from "#/icons/lightbulb.svg?react"; -import { RefreshButton } from "../../ui/buttons/refresh-button"; interface SuggestionBubbleProps { suggestion: string; diff --git a/frontend/src/components/features/waitlist/waitlist-modal.tsx b/frontend/src/components/features/waitlist/waitlist-modal.tsx index 546697ed6daf..c8ee583fbef0 100644 --- a/frontend/src/components/features/waitlist/waitlist-modal.tsx +++ b/frontend/src/components/features/waitlist/waitlist-modal.tsx @@ -1,10 +1,10 @@ +import { ModalBody } from "@nextui-org/react"; import GitHubLogo from "#/assets/branding/github-logo.svg?react"; import AllHandsLogo from "#/assets/branding/all-hands-logo.svg?react"; import { JoinWaitlistAnchor } from "./join-waitlist-anchor"; import { WaitlistMessage } from "./waitlist-message"; -import { ModalBody } from "#/components/modals/modal-body"; -import { ModalBackdrop } from "#/components/modals/modal-backdrop"; -import { ModalButton } from "#/components/ui/buttons/modal-button"; +import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop"; +import { ModalButton } from "#/components/shared/buttons/modal-button"; interface WaitlistModalProps { ghToken: string | null; diff --git a/frontend/src/components/ui/action-tooltip.tsx b/frontend/src/components/shared/action-tooltip.tsx similarity index 100% rename from frontend/src/components/ui/action-tooltip.tsx rename to frontend/src/components/shared/action-tooltip.tsx diff --git a/frontend/src/components/ui/buttons/action-button.tsx b/frontend/src/components/shared/buttons/action-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/action-button.tsx rename to frontend/src/components/shared/buttons/action-button.tsx diff --git a/frontend/src/components/ui/buttons/all-hands-logo-button.tsx b/frontend/src/components/shared/buttons/all-hands-logo-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/all-hands-logo-button.tsx rename to frontend/src/components/shared/buttons/all-hands-logo-button.tsx diff --git a/frontend/src/components/ui/buttons/confirmation-buttons.tsx b/frontend/src/components/shared/buttons/confirmation-buttons.tsx similarity index 100% rename from frontend/src/components/ui/buttons/confirmation-buttons.tsx rename to frontend/src/components/shared/buttons/confirmation-buttons.tsx diff --git a/frontend/src/components/ui/buttons/continue-button.tsx b/frontend/src/components/shared/buttons/continue-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/continue-button.tsx rename to frontend/src/components/shared/buttons/continue-button.tsx diff --git a/frontend/src/components/ui/buttons/copy-to-clipboard-button.tsx b/frontend/src/components/shared/buttons/copy-to-clipboard-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/copy-to-clipboard-button.tsx rename to frontend/src/components/shared/buttons/copy-to-clipboard-button.tsx diff --git a/frontend/src/components/ui/buttons/docs-button.tsx b/frontend/src/components/shared/buttons/docs-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/docs-button.tsx rename to frontend/src/components/shared/buttons/docs-button.tsx diff --git a/frontend/src/components/ui/buttons/editor-action-button.tsx b/frontend/src/components/shared/buttons/editor-action-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/editor-action-button.tsx rename to frontend/src/components/shared/buttons/editor-action-button.tsx diff --git a/frontend/src/components/ui/buttons/exit-project-button.tsx b/frontend/src/components/shared/buttons/exit-project-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/exit-project-button.tsx rename to frontend/src/components/shared/buttons/exit-project-button.tsx diff --git a/frontend/src/components/ui/buttons/feedback-action-button.tsx b/frontend/src/components/shared/buttons/feedback-action-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/feedback-action-button.tsx rename to frontend/src/components/shared/buttons/feedback-action-button.tsx diff --git a/frontend/src/components/ui/buttons/icon-button.tsx b/frontend/src/components/shared/buttons/icon-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/icon-button.tsx rename to frontend/src/components/shared/buttons/icon-button.tsx diff --git a/frontend/src/components/ui/buttons/modal-button.tsx b/frontend/src/components/shared/buttons/modal-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/modal-button.tsx rename to frontend/src/components/shared/buttons/modal-button.tsx diff --git a/frontend/src/components/ui/buttons/open-vscode-button.tsx b/frontend/src/components/shared/buttons/open-vscode-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/open-vscode-button.tsx rename to frontend/src/components/shared/buttons/open-vscode-button.tsx diff --git a/frontend/src/components/ui/buttons/refresh-button.tsx b/frontend/src/components/shared/buttons/refresh-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/refresh-button.tsx rename to frontend/src/components/shared/buttons/refresh-button.tsx diff --git a/frontend/src/components/ui/buttons/refresh-icon-button.tsx b/frontend/src/components/shared/buttons/refresh-icon-button.tsx similarity index 87% rename from frontend/src/components/ui/buttons/refresh-icon-button.tsx rename to frontend/src/components/shared/buttons/refresh-icon-button.tsx index c66d344e9fdc..3d0080ba0c60 100644 --- a/frontend/src/components/ui/buttons/refresh-icon-button.tsx +++ b/frontend/src/components/shared/buttons/refresh-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosRefresh } from "react-icons/io"; -import { IconButton } from "#/components/ui/buttons/icon-button"; +import { IconButton } from "./icon-button"; interface RefreshIconButtonProps { onClick: () => void; diff --git a/frontend/src/components/ui/buttons/remove-button.tsx b/frontend/src/components/shared/buttons/remove-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/remove-button.tsx rename to frontend/src/components/shared/buttons/remove-button.tsx diff --git a/frontend/src/components/ui/buttons/scroll-to-bottom-button.tsx b/frontend/src/components/shared/buttons/scroll-to-bottom-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/scroll-to-bottom-button.tsx rename to frontend/src/components/shared/buttons/scroll-to-bottom-button.tsx diff --git a/frontend/src/components/ui/buttons/settings-button.tsx b/frontend/src/components/shared/buttons/settings-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/settings-button.tsx rename to frontend/src/components/shared/buttons/settings-button.tsx diff --git a/frontend/src/components/ui/buttons/stop-button.tsx b/frontend/src/components/shared/buttons/stop-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/stop-button.tsx rename to frontend/src/components/shared/buttons/stop-button.tsx diff --git a/frontend/src/components/ui/buttons/submit-button.tsx b/frontend/src/components/shared/buttons/submit-button.tsx similarity index 100% rename from frontend/src/components/ui/buttons/submit-button.tsx rename to frontend/src/components/shared/buttons/submit-button.tsx diff --git a/frontend/src/components/ui/buttons/toggle-workspace-icon-button.tsx b/frontend/src/components/shared/buttons/toggle-workspace-icon-button.tsx similarity index 91% rename from frontend/src/components/ui/buttons/toggle-workspace-icon-button.tsx rename to frontend/src/components/shared/buttons/toggle-workspace-icon-button.tsx index 038ecb3d3675..5eedd1ae8f1b 100644 --- a/frontend/src/components/ui/buttons/toggle-workspace-icon-button.tsx +++ b/frontend/src/components/shared/buttons/toggle-workspace-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosArrowForward, IoIosArrowBack } from "react-icons/io"; -import { IconButton } from "#/components/ui/buttons/icon-button"; +import { IconButton } from "./icon-button"; interface ToggleWorkspaceIconButtonProps { onClick: () => void; diff --git a/frontend/src/components/ui/buttons/upload-icon-button.tsx b/frontend/src/components/shared/buttons/upload-icon-button.tsx similarity index 87% rename from frontend/src/components/ui/buttons/upload-icon-button.tsx rename to frontend/src/components/shared/buttons/upload-icon-button.tsx index 923e7be1b124..0e8bdeab29d1 100644 --- a/frontend/src/components/ui/buttons/upload-icon-button.tsx +++ b/frontend/src/components/shared/buttons/upload-icon-button.tsx @@ -1,5 +1,5 @@ import { IoIosCloudUpload } from "react-icons/io"; -import { IconButton } from "#/components/ui/buttons/icon-button"; +import { IconButton } from "./icon-button"; interface UploadIconButtonProps { onClick: () => void; diff --git a/frontend/src/components/ui/custom-input.tsx b/frontend/src/components/shared/custom-input.tsx similarity index 100% rename from frontend/src/components/ui/custom-input.tsx rename to frontend/src/components/shared/custom-input.tsx diff --git a/frontend/src/components/ui/error-toast.tsx b/frontend/src/components/shared/error-toast.tsx similarity index 100% rename from frontend/src/components/ui/error-toast.tsx rename to frontend/src/components/shared/error-toast.tsx diff --git a/frontend/src/components/ui/form-fieldset.tsx b/frontend/src/components/shared/form-fieldset.tsx similarity index 100% rename from frontend/src/components/ui/form-fieldset.tsx rename to frontend/src/components/shared/form-fieldset.tsx diff --git a/frontend/src/components/ui/hero-heading.tsx b/frontend/src/components/shared/hero-heading.tsx similarity index 100% rename from frontend/src/components/ui/hero-heading.tsx rename to frontend/src/components/shared/hero-heading.tsx diff --git a/frontend/src/components/ui/inputs/advanced-option-switch.tsx b/frontend/src/components/shared/inputs/advanced-option-switch.tsx similarity index 100% rename from frontend/src/components/ui/inputs/advanced-option-switch.tsx rename to frontend/src/components/shared/inputs/advanced-option-switch.tsx diff --git a/frontend/src/components/ui/inputs/agent-input.tsx b/frontend/src/components/shared/inputs/agent-input.tsx similarity index 100% rename from frontend/src/components/ui/inputs/agent-input.tsx rename to frontend/src/components/shared/inputs/agent-input.tsx diff --git a/frontend/src/components/ui/inputs/api-key-input.tsx b/frontend/src/components/shared/inputs/api-key-input.tsx similarity index 100% rename from frontend/src/components/ui/inputs/api-key-input.tsx rename to frontend/src/components/shared/inputs/api-key-input.tsx diff --git a/frontend/src/components/ui/inputs/base-url-input.tsx b/frontend/src/components/shared/inputs/base-url-input.tsx similarity index 100% rename from frontend/src/components/ui/inputs/base-url-input.tsx rename to frontend/src/components/shared/inputs/base-url-input.tsx diff --git a/frontend/src/components/ui/inputs/confirmation-mode-switch.tsx b/frontend/src/components/shared/inputs/confirmation-mode-switch.tsx similarity index 100% rename from frontend/src/components/ui/inputs/confirmation-mode-switch.tsx rename to frontend/src/components/shared/inputs/confirmation-mode-switch.tsx diff --git a/frontend/src/components/ui/inputs/custom-model-input.tsx b/frontend/src/components/shared/inputs/custom-model-input.tsx similarity index 100% rename from frontend/src/components/ui/inputs/custom-model-input.tsx rename to frontend/src/components/shared/inputs/custom-model-input.tsx diff --git a/frontend/src/components/ui/inputs/security-analyzers-input.tsx b/frontend/src/components/shared/inputs/security-analyzers-input.tsx similarity index 100% rename from frontend/src/components/ui/inputs/security-analyzers-input.tsx rename to frontend/src/components/shared/inputs/security-analyzers-input.tsx diff --git a/frontend/src/components/ui/loading-spinner.tsx b/frontend/src/components/shared/loading-spinner.tsx similarity index 100% rename from frontend/src/components/ui/loading-spinner.tsx rename to frontend/src/components/shared/loading-spinner.tsx diff --git a/frontend/src/components/modals/account-settings/account-settings-form.tsx b/frontend/src/components/shared/modals/account-settings/account-settings-form.tsx similarity index 96% rename from frontend/src/components/modals/account-settings/account-settings-form.tsx rename to frontend/src/components/shared/modals/account-settings/account-settings-form.tsx index 92286516df64..3da9b97e2c8d 100644 --- a/frontend/src/components/modals/account-settings/account-settings-form.tsx +++ b/frontend/src/components/shared/modals/account-settings/account-settings-form.tsx @@ -5,14 +5,14 @@ import { BaseModalTitle, } from "../confirmation-modals/base-modal"; import { ModalBody } from "../modal-body"; -import { ModalButton } from "../../ui/buttons/modal-button"; -import { FormFieldset } from "../../ui/form-fieldset"; -import { CustomInput } from "../../ui/custom-input"; import { AvailableLanguages } from "#/i18n"; import { I18nKey } from "#/i18n/declaration"; import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { handleCaptureConsent } from "#/utils/handle-capture-consent"; +import { ModalButton } from "../../buttons/modal-button"; +import { CustomInput } from "../../custom-input"; +import { FormFieldset } from "../../form-fieldset"; interface AccountSettingsFormProps { onClose: () => void; diff --git a/frontend/src/components/modals/account-settings/account-settings-modal.tsx b/frontend/src/components/shared/modals/account-settings/account-settings-modal.tsx similarity index 81% rename from frontend/src/components/modals/account-settings/account-settings-modal.tsx rename to frontend/src/components/shared/modals/account-settings/account-settings-modal.tsx index b9ab8c313217..f6bcdb48abfe 100644 --- a/frontend/src/components/modals/account-settings/account-settings-modal.tsx +++ b/frontend/src/components/shared/modals/account-settings/account-settings-modal.tsx @@ -1,7 +1,7 @@ -import { AccountSettingsForm } from "#/components/modals/account-settings/account-settings-form"; -import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useGitHubUser } from "#/hooks/query/use-github-user"; +import { ModalBackdrop } from "../modal-backdrop"; +import { AccountSettingsForm } from "./account-settings-form"; interface AccountSettingsModalProps { onClose: () => void; diff --git a/frontend/src/components/modals/base-modal/base-modal.tsx b/frontend/src/components/shared/modals/base-modal/base-modal.tsx similarity index 100% rename from frontend/src/components/modals/base-modal/base-modal.tsx rename to frontend/src/components/shared/modals/base-modal/base-modal.tsx diff --git a/frontend/src/components/modals/base-modal/footer-content.tsx b/frontend/src/components/shared/modals/base-modal/footer-content.tsx similarity index 100% rename from frontend/src/components/modals/base-modal/footer-content.tsx rename to frontend/src/components/shared/modals/base-modal/footer-content.tsx diff --git a/frontend/src/components/modals/base-modal/header-content.tsx b/frontend/src/components/shared/modals/base-modal/header-content.tsx similarity index 100% rename from frontend/src/components/modals/base-modal/header-content.tsx rename to frontend/src/components/shared/modals/base-modal/header-content.tsx diff --git a/frontend/src/components/modals/confirmation-modals/base-modal.tsx b/frontend/src/components/shared/modals/confirmation-modals/base-modal.tsx similarity index 95% rename from frontend/src/components/modals/confirmation-modals/base-modal.tsx rename to frontend/src/components/shared/modals/confirmation-modals/base-modal.tsx index cdd20965240e..2cb79b45c8c0 100644 --- a/frontend/src/components/modals/confirmation-modals/base-modal.tsx +++ b/frontend/src/components/shared/modals/confirmation-modals/base-modal.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { ModalButton } from "#/components/ui/buttons/modal-button"; import { ModalBody } from "../modal-body"; +import { ModalButton } from "../../buttons/modal-button"; interface ButtonConfig { text: string; diff --git a/frontend/src/components/modals/confirmation-modals/danger-modal.tsx b/frontend/src/components/shared/modals/confirmation-modals/danger-modal.tsx similarity index 100% rename from frontend/src/components/modals/confirmation-modals/danger-modal.tsx rename to frontend/src/components/shared/modals/confirmation-modals/danger-modal.tsx diff --git a/frontend/src/components/modals/connect-to-github-modal.tsx b/frontend/src/components/shared/modals/connect-to-github-modal.tsx similarity index 95% rename from frontend/src/components/modals/connect-to-github-modal.tsx rename to frontend/src/components/shared/modals/connect-to-github-modal.tsx index d5fb63817b69..130ca4e19929 100644 --- a/frontend/src/components/modals/connect-to-github-modal.tsx +++ b/frontend/src/components/shared/modals/connect-to-github-modal.tsx @@ -1,13 +1,13 @@ import { useTranslation } from "react-i18next"; import { ModalBody } from "./modal-body"; -import { CustomInput } from "../ui/custom-input"; -import { ModalButton } from "../ui/buttons/modal-button"; import { BaseModalDescription, BaseModalTitle, } from "./confirmation-modals/base-modal"; import { I18nKey } from "#/i18n/declaration"; import { useAuth } from "#/context/auth-context"; +import { ModalButton } from "../buttons/modal-button"; +import { CustomInput } from "../custom-input"; interface ConnectToGitHubModalProps { onClose: () => void; diff --git a/frontend/src/components/modals/exit-project-confirmation-modal.tsx b/frontend/src/components/shared/modals/exit-project-confirmation-modal.tsx similarity index 87% rename from frontend/src/components/modals/exit-project-confirmation-modal.tsx rename to frontend/src/components/shared/modals/exit-project-confirmation-modal.tsx index 5d425fd4a6a1..c29477f3e098 100644 --- a/frontend/src/components/modals/exit-project-confirmation-modal.tsx +++ b/frontend/src/components/shared/modals/exit-project-confirmation-modal.tsx @@ -1,9 +1,9 @@ import { useDispatch } from "react-redux"; -import { DangerModal } from "#/components/modals/confirmation-modals/danger-modal"; -import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { useEndSession } from "#/hooks/use-end-session"; import { setCurrentAgentState } from "#/state/agent-slice"; import AgentState from "#/types/agent-state"; +import { DangerModal } from "./confirmation-modals/danger-modal"; +import { ModalBackdrop } from "./modal-backdrop"; interface ExitProjectConfirmationModalProps { onClose: () => void; diff --git a/frontend/src/components/modals/modal-backdrop.tsx b/frontend/src/components/shared/modals/modal-backdrop.tsx similarity index 100% rename from frontend/src/components/modals/modal-backdrop.tsx rename to frontend/src/components/shared/modals/modal-backdrop.tsx diff --git a/frontend/src/components/modals/modal-body.tsx b/frontend/src/components/shared/modals/modal-body.tsx similarity index 100% rename from frontend/src/components/modals/modal-body.tsx rename to frontend/src/components/shared/modals/modal-body.tsx diff --git a/frontend/src/components/modals/security/invariant/assets/logo.tsx b/frontend/src/components/shared/modals/security/invariant/assets/logo.tsx similarity index 100% rename from frontend/src/components/modals/security/invariant/assets/logo.tsx rename to frontend/src/components/shared/modals/security/invariant/assets/logo.tsx diff --git a/frontend/src/components/modals/security/invariant/invariant.tsx b/frontend/src/components/shared/modals/security/invariant/invariant.tsx similarity index 100% rename from frontend/src/components/modals/security/invariant/invariant.tsx rename to frontend/src/components/shared/modals/security/invariant/invariant.tsx diff --git a/frontend/src/components/modals/security/security.tsx b/frontend/src/components/shared/modals/security/security.tsx similarity index 100% rename from frontend/src/components/modals/security/security.tsx rename to frontend/src/components/shared/modals/security/security.tsx diff --git a/frontend/src/components/modals/settings/model-selector.tsx b/frontend/src/components/shared/modals/settings/model-selector.tsx similarity index 100% rename from frontend/src/components/modals/settings/model-selector.tsx rename to frontend/src/components/shared/modals/settings/model-selector.tsx diff --git a/frontend/src/components/modals/settings/settings-form.tsx b/frontend/src/components/shared/modals/settings/settings-form.tsx similarity index 92% rename from frontend/src/components/modals/settings/settings-form.tsx rename to frontend/src/components/shared/modals/settings/settings-form.tsx index d5c5d97efcb5..4b50a85e783b 100644 --- a/frontend/src/components/modals/settings/settings-form.tsx +++ b/frontend/src/components/shared/modals/settings/settings-form.tsx @@ -3,11 +3,8 @@ import { useTranslation } from "react-i18next"; import React from "react"; import posthog from "posthog-js"; import { organizeModelsAndProviders } from "#/utils/organize-models-and-providers"; -import { ModelSelector } from "#/components/modals/settings/model-selector"; import { getDefaultSettings, Settings } from "#/services/settings"; -import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { extractModelAndProvider } from "#/utils/extract-model-and-provider"; -import { ModalButton } from "../../ui/buttons/modal-button"; import { DangerModal } from "../confirmation-modals/danger-modal"; import { I18nKey } from "#/i18n/declaration"; import { @@ -17,13 +14,16 @@ import { } from "#/utils/settings-utils"; import { useEndSession } from "#/hooks/use-end-session"; import { useUserPrefs } from "#/context/user-prefs-context"; -import { AdvancedOptionSwitch } from "../../ui/inputs/advanced-option-switch"; -import { CustomModelInput } from "../../ui/inputs/custom-model-input"; -import { BaseUrlInput } from "../../ui/inputs/base-url-input"; -import { AgentInput } from "../../ui/inputs/agent-input"; -import { APIKeyInput } from "../../ui/inputs/api-key-input"; -import { SecurityAnalyzerInput } from "../../ui/inputs/security-analyzers-input"; -import { ConfirmationModeSwitch } from "../../ui/inputs/confirmation-mode-switch"; +import { ModalButton } from "../../buttons/modal-button"; +import { AdvancedOptionSwitch } from "../../inputs/advanced-option-switch"; +import { AgentInput } from "../../inputs/agent-input"; +import { APIKeyInput } from "../../inputs/api-key-input"; +import { BaseUrlInput } from "../../inputs/base-url-input"; +import { ConfirmationModeSwitch } from "../../inputs/confirmation-mode-switch"; +import { CustomModelInput } from "../../inputs/custom-model-input"; +import { SecurityAnalyzerInput } from "../../inputs/security-analyzers-input"; +import { ModalBackdrop } from "../modal-backdrop"; +import { ModelSelector } from "./model-selector"; interface SettingsFormProps { disabled?: boolean; diff --git a/frontend/src/components/modals/settings/settings-modal.tsx b/frontend/src/components/shared/modals/settings/settings-modal.tsx similarity index 88% rename from frontend/src/components/modals/settings/settings-modal.tsx rename to frontend/src/components/shared/modals/settings/settings-modal.tsx index d3702d94c59c..4cd0dd45a719 100644 --- a/frontend/src/components/modals/settings/settings-modal.tsx +++ b/frontend/src/components/shared/modals/settings/settings-modal.tsx @@ -1,8 +1,8 @@ -import { SettingsForm } from "#/components/modals/settings/settings-form"; -import { ModalBackdrop } from "#/components/modals/modal-backdrop"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useAIConfigOptions } from "#/hooks/query/use-ai-config-options"; -import { LoadingSpinner } from "#/components/ui/loading-spinner"; +import { LoadingSpinner } from "../../loading-spinner"; +import { ModalBackdrop } from "../modal-backdrop"; +import { SettingsForm } from "./settings-form"; interface SettingsModalProps { onClose: () => void; diff --git a/frontend/src/components/ui/task-form.tsx b/frontend/src/components/shared/task-form.tsx similarity index 100% rename from frontend/src/components/ui/task-form.tsx rename to frontend/src/components/shared/task-form.tsx diff --git a/frontend/src/routes/_oh._index/route.tsx b/frontend/src/routes/_oh._index/route.tsx index 1687ab7f092b..1c4cb3efba0f 100644 --- a/frontend/src/routes/_oh._index/route.tsx +++ b/frontend/src/routes/_oh._index/route.tsx @@ -1,8 +1,6 @@ import { useLocation, useNavigate } from "@remix-run/react"; import React from "react"; import { useDispatch } from "react-redux"; -import { TaskForm } from "../../components/ui/task-form"; -import { HeroHeading } from "../../components/ui/hero-heading"; import { setImportedProjectZip } from "#/state/initial-query-slice"; import { convertZipToBase64 } from "#/utils/convert-zip-to-base64"; import { useUserRepositories } from "#/hooks/query/use-user-repositories"; @@ -12,6 +10,8 @@ import { useConfig } from "#/hooks/query/use-config"; import { useAuth } from "#/context/auth-context"; import { ImportProjectSuggestionBox } from "../../components/features/suggestions/import-project-suggestion-box"; import { GitHubRepositoriesSuggestionBox } from "#/components/features/github/github-repositories-suggestion-box"; +import { HeroHeading } from "#/components/shared/hero-heading"; +import { TaskForm } from "#/components/shared/task-form"; function Home() { const { token, gitHubToken } = useAuth(); diff --git a/frontend/src/routes/_oh.app/route.tsx b/frontend/src/routes/_oh.app/route.tsx index 6f307a563011..5d257b169495 100644 --- a/frontend/src/routes/_oh.app/route.tsx +++ b/frontend/src/routes/_oh.app/route.tsx @@ -2,7 +2,6 @@ import { useDisclosure } from "@nextui-org/react"; import React from "react"; import { Outlet } from "@remix-run/react"; import { useDispatch, useSelector } from "react-redux"; -import Security from "#/components/modals/security/security"; import { Controls } from "#/components/features/controls/controls"; import { RootState } from "#/store"; import { clearMessages } from "#/state/chat-slice"; @@ -21,6 +20,7 @@ import { useAuth } from "#/context/auth-context"; import { useUserPrefs } from "#/context/user-prefs-context"; import { useConversationConfig } from "#/hooks/query/use-conversation-config"; import { Container } from "#/components/layout/container"; +import Security from "#/components/shared/modals/security/security"; function App() { const { token, gitHubToken } = useAuth(); diff --git a/frontend/src/utils/display-error-toast.tsx b/frontend/src/utils/display-error-toast.tsx index 67485eb982c9..d481ccd932fd 100644 --- a/frontend/src/utils/display-error-toast.tsx +++ b/frontend/src/utils/display-error-toast.tsx @@ -1,5 +1,5 @@ import toast from "react-hot-toast"; -import { ErrorToast } from "#/components/ui/error-toast"; +import { ErrorToast } from "#/components/shared/error-toast"; export const displayErrorToast = (error: string) => toast((t) => <ErrorToast id={t.id} error={error} />, {