From 306188817f10c4e63f25c60d4cfaa92e18354aa6 Mon Sep 17 00:00:00 2001 From: Robert Brennan Date: Sat, 22 Mar 2025 19:03:05 -0700 Subject: [PATCH] Remove upload functionality and add tooltip for Code not in GitHub link (#7431) Co-authored-by: openhands --- .../features/chat/chat-interface.tsx | 14 ++------ .../github/code-not-in-github-link.tsx | 30 ++++++++++++++++ .../import-project-suggestion-box.tsx | 33 ----------------- frontend/src/components/shared/task-form.tsx | 2 +- .../hooks/mutation/use-create-conversation.ts | 11 +----- frontend/src/routes/_oh._index/route.tsx | 26 ++++---------- .../hooks/use-handle-runtime-active.ts | 36 ++----------------- frontend/src/state/initial-query-slice.ts | 6 ---- frontend/src/utils/convert-zip-to-base64.ts | 10 ------ 9 files changed, 43 insertions(+), 125 deletions(-) create mode 100644 frontend/src/components/features/github/code-not-in-github-link.tsx delete mode 100644 frontend/src/components/features/suggestions/import-project-suggestion-box.tsx delete mode 100644 frontend/src/utils/convert-zip-to-base64.ts diff --git a/frontend/src/components/features/chat/chat-interface.tsx b/frontend/src/components/features/chat/chat-interface.tsx index 4f7cd0eab2..37a1603120 100644 --- a/frontend/src/components/features/chat/chat-interface.tsx +++ b/frontend/src/components/features/chat/chat-interface.tsx @@ -24,12 +24,8 @@ import { useGetTrajectory } from "#/hooks/mutation/use-get-trajectory"; import { downloadTrajectory } from "#/utils/download-trajectory"; import { displayErrorToast } from "#/utils/custom-toast-handlers"; -function getEntryPoint( - hasRepository: boolean | null, - hasImportedProjectZip: boolean | null, -): string { +function getEntryPoint(hasRepository: boolean | null): string { if (hasRepository) return "github"; - if (hasImportedProjectZip) return "zip"; return "direct"; } @@ -48,7 +44,7 @@ export function ChatInterface() { >("positive"); const [feedbackModalIsOpen, setFeedbackModalIsOpen] = React.useState(false); const [messageToSend, setMessageToSend] = React.useState(null); - const { selectedRepository, importedProjectZip } = useSelector( + const { selectedRepository } = useSelector( (state: RootState) => state.initialQuery, ); const params = useParams(); @@ -57,12 +53,8 @@ export function ChatInterface() { const handleSendMessage = async (content: string, files: File[]) => { if (messages.length === 0) { posthog.capture("initial_query_submitted", { - entry_point: getEntryPoint( - selectedRepository !== null, - importedProjectZip !== null, - ), + entry_point: getEntryPoint(selectedRepository !== null), query_character_length: content.length, - uploaded_zip_size: importedProjectZip?.length, }); } else { posthog.capture("user_message_sent", { diff --git a/frontend/src/components/features/github/code-not-in-github-link.tsx b/frontend/src/components/features/github/code-not-in-github-link.tsx new file mode 100644 index 0000000000..463ecf5c84 --- /dev/null +++ b/frontend/src/components/features/github/code-not-in-github-link.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { useDispatch } from "react-redux"; +import { useCreateConversation } from "#/hooks/mutation/use-create-conversation"; +import { setInitialPrompt } from "#/state/initial-query-slice"; + +const INITIAL_PROMPT = ""; + +export function CodeNotInGitHubLink() { + const dispatch = useDispatch(); + const { mutate: createConversation } = useCreateConversation(); + + const handleStartFromScratch = () => { + // Set the initial prompt and create a new conversation + dispatch(setInitialPrompt(INITIAL_PROMPT)); + createConversation({ q: INITIAL_PROMPT }); + }; + + return ( +
+ Code not in GitHub?{" "} + + Start from scratch + {" "} + and use the VS Code link to upload and download your code. +
+ ); +} diff --git a/frontend/src/components/features/suggestions/import-project-suggestion-box.tsx b/frontend/src/components/features/suggestions/import-project-suggestion-box.tsx deleted file mode 100644 index 5953e0fc62..0000000000 --- a/frontend/src/components/features/suggestions/import-project-suggestion-box.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { I18nKey } from "#/i18n/declaration"; -import { SuggestionBox } from "./suggestion-box"; - -interface ImportProjectSuggestionBoxProps { - onChange: (event: React.ChangeEvent) => void; -} - -export function ImportProjectSuggestionBox({ - onChange, -}: ImportProjectSuggestionBoxProps) { - const { t } = useTranslation(); - return ( - - - {t(I18nKey.LANDING$UPLOAD_ZIP)} - - - - } - /> - ); -} diff --git a/frontend/src/components/shared/task-form.tsx b/frontend/src/components/shared/task-form.tsx index 269f08e558..f6d35c8423 100644 --- a/frontend/src/components/shared/task-form.tsx +++ b/frontend/src/components/shared/task-form.tsx @@ -56,7 +56,7 @@ export function TaskForm({ ref }: TaskFormProps) { }; return ( -
+
{ const dispatch = useDispatch(); const queryClient = useQueryClient(); - const { selectedRepository, files, importedProjectZip } = useSelector( + const { selectedRepository, files } = useSelector( (state: RootState) => state.initialQuery, ); return useMutation({ mutationFn: async (variables: { q?: string }) => { - if ( - !variables.q?.trim() && - !selectedRepository && - files.length === 0 && - !importedProjectZip - ) { - throw new Error("No query provided"); - } - if (variables.q) dispatch(setInitialPrompt(variables.q)); return OpenHands.createConversation( diff --git a/frontend/src/routes/_oh._index/route.tsx b/frontend/src/routes/_oh._index/route.tsx index d3d6b58c91..ac0736bc71 100644 --- a/frontend/src/routes/_oh._index/route.tsx +++ b/frontend/src/routes/_oh._index/route.tsx @@ -1,18 +1,13 @@ import React from "react"; -import { useDispatch } from "react-redux"; -import posthog from "posthog-js"; -import { setImportedProjectZip } from "#/state/initial-query-slice"; -import { convertZipToBase64 } from "#/utils/convert-zip-to-base64"; import { useGitHubUser } from "#/hooks/query/use-github-user"; import { useGitHubAuthUrl } from "#/hooks/use-github-auth-url"; import { useConfig } from "#/hooks/query/use-config"; -import { ImportProjectSuggestionBox } from "../../components/features/suggestions/import-project-suggestion-box"; import { GitHubRepositoriesSuggestionBox } from "#/components/features/github/github-repositories-suggestion-box"; +import { CodeNotInGitHubLink } from "#/components/features/github/code-not-in-github-link"; import { HeroHeading } from "#/components/shared/hero-heading"; import { TaskForm } from "#/components/shared/task-form"; function Home() { - const dispatch = useDispatch(); const formRef = React.useRef(null); const { data: config } = useConfig(); @@ -29,29 +24,20 @@ function Home() { className="bg-base-secondary h-full rounded-xl flex flex-col items-center justify-center relative overflow-y-auto px-2" > -
+
-
+
formRef.current?.requestSubmit()} gitHubAuthUrl={gitHubAuthUrl} user={user || null} /> - { - if (event.target.files) { - const zip = event.target.files[0]; - dispatch(setImportedProjectZip(await convertZipToBase64(zip))); - posthog.capture("zip_file_uploaded"); - formRef.current?.requestSubmit(); - } else { - // TODO: handle error - } - }} - /> +
+
+
diff --git a/frontend/src/routes/_oh.app/hooks/use-handle-runtime-active.ts b/frontend/src/routes/_oh.app/hooks/use-handle-runtime-active.ts index 3793dc66ff..428f2fac00 100644 --- a/frontend/src/routes/_oh.app/hooks/use-handle-runtime-active.ts +++ b/frontend/src/routes/_oh.app/hooks/use-handle-runtime-active.ts @@ -1,44 +1,12 @@ -import React from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { setImportedProjectZip } from "#/state/initial-query-slice"; +import { useSelector } from "react-redux"; import { RootState } from "#/store"; -import { base64ToBlob } from "#/utils/base64-to-blob"; -import { useUploadFiles } from "../../../hooks/mutation/use-upload-files"; import { RUNTIME_INACTIVE_STATES } from "#/types/agent-state"; -import { displayErrorToast } from "#/utils/custom-toast-handlers"; export const useHandleRuntimeActive = () => { - const dispatch = useDispatch(); - - const { mutate: uploadFiles } = useUploadFiles(); const { curAgentState } = useSelector((state: RootState) => state.agent); const runtimeActive = !RUNTIME_INACTIVE_STATES.includes(curAgentState); - const { importedProjectZip } = useSelector( - (state: RootState) => state.initialQuery, - ); - - const handleUploadFiles = (zip: string) => { - const blob = base64ToBlob(zip); - const file = new File([blob], "imported-project.zip", { - type: blob.type, - }); - uploadFiles( - { files: [file] }, - { - onError: () => { - displayErrorToast("Failed to upload project files."); - }, - }, - ); - dispatch(setImportedProjectZip(null)); - }; - - React.useEffect(() => { - if (runtimeActive && importedProjectZip) { - handleUploadFiles(importedProjectZip); - } - }, [runtimeActive, importedProjectZip]); + return { runtimeActive }; }; diff --git a/frontend/src/state/initial-query-slice.ts b/frontend/src/state/initial-query-slice.ts index 1dcbe273ba..5cbacb6304 100644 --- a/frontend/src/state/initial-query-slice.ts +++ b/frontend/src/state/initial-query-slice.ts @@ -4,14 +4,12 @@ type SliceState = { files: string[]; // base64 encoded images initialPrompt: string | null; selectedRepository: string | null; - importedProjectZip: string | null; // base64 encoded zip }; const initialState: SliceState = { files: [], initialPrompt: null, selectedRepository: null, - importedProjectZip: null, }; export const selectedFilesSlice = createSlice({ @@ -39,9 +37,6 @@ export const selectedFilesSlice = createSlice({ clearSelectedRepository(state) { state.selectedRepository = null; }, - setImportedProjectZip(state, action: PayloadAction) { - state.importedProjectZip = action.payload; - }, }, }); @@ -53,6 +48,5 @@ export const { clearInitialPrompt, setSelectedRepository, clearSelectedRepository, - setImportedProjectZip, } = selectedFilesSlice.actions; export default selectedFilesSlice.reducer; diff --git a/frontend/src/utils/convert-zip-to-base64.ts b/frontend/src/utils/convert-zip-to-base64.ts deleted file mode 100644 index 34b57acdf1..0000000000 --- a/frontend/src/utils/convert-zip-to-base64.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const convertZipToBase64 = async (file: File) => { - const reader = new FileReader(); - - return new Promise((resolve) => { - reader.onload = () => { - resolve(reader.result as string); - }; - reader.readAsDataURL(file); - }); -};