mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Add code editor and separate tabs (#43)
This commit is contained in:
parent
cac687508f
commit
cdb83c72e2
36
frontend/package-lock.json
generated
36
frontend/package-lock.json
generated
@ -8,6 +8,7 @@
|
||||
"name": "opendevin-frontend",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -1663,6 +1664,30 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@monaco-editor/loader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz",
|
||||
"integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
|
||||
"dependencies": {
|
||||
"state-local": "^1.0.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"monaco-editor": ">= 0.21.0 < 1"
|
||||
}
|
||||
},
|
||||
"node_modules/@monaco-editor/react": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz",
|
||||
"integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==",
|
||||
"dependencies": {
|
||||
"@monaco-editor/loader": "^1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"monaco-editor": ">= 0.25.0 < 1",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@ -7281,6 +7306,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/monaco-editor": {
|
||||
"version": "0.47.0",
|
||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.47.0.tgz",
|
||||
"integrity": "sha512-VabVvHvQ9QmMwXu4du008ZDuyLnHs9j7ThVFsiJoXSOQk18+LF89N4ADzPbFenm0W4V2bGHnFBztIRQTgBfxzw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -8503,6 +8534,11 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/state-local": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
|
||||
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
|
||||
},
|
||||
"node_modules/stop-iteration-iterator": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
|
||||
@ -4,11 +4,41 @@ import "./App.css";
|
||||
import ChatInterface from "./components/ChatInterface";
|
||||
import Terminal from "./components/Terminal";
|
||||
import Planner from "./components/Planner";
|
||||
import CodeEditor from "./components/CodeEditor";
|
||||
|
||||
const TAB_OPTIONS = ["terminal", "planner", "code"] as const;
|
||||
type TabOption = (typeof TAB_OPTIONS)[number];
|
||||
|
||||
const tabData = {
|
||||
terminal: {
|
||||
name: "Terminal",
|
||||
component: <Terminal />,
|
||||
},
|
||||
planner: {
|
||||
name: "Planner",
|
||||
component: <Planner />,
|
||||
},
|
||||
code: {
|
||||
name: "Code Editor",
|
||||
component: <CodeEditor />,
|
||||
},
|
||||
};
|
||||
|
||||
type TabProps = {
|
||||
name: string;
|
||||
active: boolean;
|
||||
onClick: () => void;
|
||||
};
|
||||
function Tab({ name, active, onClick }: TabProps): JSX.Element {
|
||||
return (
|
||||
<div className={`tab ${active ? "active" : ""}`} onClick={() => onClick()}>
|
||||
{name}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function App(): JSX.Element {
|
||||
const [activeTab, setActiveTab] = useState<"terminal" | "planner">(
|
||||
"terminal",
|
||||
);
|
||||
const [activeTab, setActiveTab] = useState<TabOption>("terminal");
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
@ -17,22 +47,16 @@ function App(): JSX.Element {
|
||||
</div>
|
||||
<div className="right-pane">
|
||||
<div className="tab-container">
|
||||
<div
|
||||
className={`tab ${activeTab === "terminal" ? "active" : ""}`}
|
||||
onClick={() => setActiveTab("terminal")}
|
||||
>
|
||||
Shell
|
||||
</div>
|
||||
<div
|
||||
className={`tab ${activeTab === "planner" ? "active" : ""}`}
|
||||
onClick={() => setActiveTab("planner")}
|
||||
>
|
||||
Planner
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-content">
|
||||
{activeTab === "terminal" ? <Terminal /> : <Planner />}
|
||||
{TAB_OPTIONS.map((tab) => (
|
||||
<Tab
|
||||
key={tab}
|
||||
name={tabData[tab].name}
|
||||
active={activeTab === tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="tab-content">{tabData[activeTab].component}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
19
frontend/src/components/CodeEditor.tsx
Normal file
19
frontend/src/components/CodeEditor.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import Editor from "@monaco-editor/react";
|
||||
|
||||
function CodeEditor(): JSX.Element {
|
||||
const handleEditorChange = (value: string | undefined) => {
|
||||
console.log("Content changed:", value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Editor
|
||||
height="100%"
|
||||
defaultLanguage="javascript"
|
||||
defaultValue="// Welcome to OpenDevin!"
|
||||
onChange={handleEditorChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default CodeEditor;
|
||||
Loading…
x
Reference in New Issue
Block a user