mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-04-29 03:00:45 -04:00
Compare commits
2 Commits
eval/visua
...
add-app-ta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10a5c7e463 | ||
|
|
729caafa6e |
11
frontend/src/components/features/app/app-view.tsx
Normal file
11
frontend/src/components/features/app/app-view.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
export function AppView() {
|
||||
return (
|
||||
<div className="h-full w-full">
|
||||
<iframe
|
||||
src="http://localhost:4000"
|
||||
className="h-full w-full border-0"
|
||||
title="App"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,10 +5,12 @@ import { NavTab } from "./nav-tab";
|
||||
interface ContainerProps {
|
||||
label?: string;
|
||||
labels?: {
|
||||
id: string;
|
||||
label: string;
|
||||
to: string;
|
||||
icon?: React.ReactNode;
|
||||
isBeta?: boolean;
|
||||
isActive: boolean;
|
||||
onClick: (id: string) => void;
|
||||
}[];
|
||||
children: React.ReactNode;
|
||||
className?: React.HTMLAttributes<HTMLDivElement>["className"];
|
||||
@@ -29,8 +31,8 @@ export function Container({
|
||||
>
|
||||
{labels && (
|
||||
<div className="flex text-xs h-[36px]">
|
||||
{labels.map(({ label: l, to, icon, isBeta }) => (
|
||||
<NavTab key={to} to={to} label={l} icon={icon} isBeta={isBeta} />
|
||||
{labels.map(({ id, label: l, icon, isBeta, isActive, onClick }) => (
|
||||
<NavTab key={id} id={id} label={l} icon={icon} isBeta={isBeta} isActive={isActive} onClick={onClick} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
import { NavLink } from "react-router";
|
||||
import { cn } from "#/utils/utils";
|
||||
import { BetaBadge } from "./beta-badge";
|
||||
|
||||
interface NavTabProps {
|
||||
to: string;
|
||||
id: string;
|
||||
label: string;
|
||||
icon: React.ReactNode;
|
||||
isBeta?: boolean;
|
||||
isActive: boolean;
|
||||
onClick: (id: string) => void;
|
||||
}
|
||||
|
||||
export function NavTab({ to, label, icon, isBeta }: NavTabProps) {
|
||||
export function NavTab({ id, label, icon, isBeta, isActive, onClick }: NavTabProps) {
|
||||
return (
|
||||
<NavLink
|
||||
end
|
||||
key={to}
|
||||
to={to}
|
||||
className={({ isActive }) =>
|
||||
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",
|
||||
)
|
||||
}
|
||||
<button
|
||||
onClick={() => onClick(id)}
|
||||
className={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 && <BetaBadge />}
|
||||
</NavLink>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
7
frontend/src/routes/_oh.app.app/route.tsx
Normal file
7
frontend/src/routes/_oh.app.app/route.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import { AppView } from "#/components/features/app/app-view";
|
||||
|
||||
function App() {
|
||||
return <AppView />;
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useDisclosure } from "@nextui-org/react";
|
||||
import React from "react";
|
||||
import { Outlet } from "react-router";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Controls } from "#/components/features/controls/controls";
|
||||
import { RootState } from "#/store";
|
||||
@@ -21,10 +20,16 @@ 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";
|
||||
import { useState } from "react";
|
||||
import { AppView } from "#/components/features/app/app-view";
|
||||
import { Workspace } from "#/components/features/workspace/workspace";
|
||||
import { JupyterView } from "#/components/features/jupyter/jupyter-view";
|
||||
import { BrowserView } from "#/components/features/browser/browser-view";
|
||||
|
||||
function App() {
|
||||
const { token, gitHubToken } = useAuth();
|
||||
const { settings } = useUserPrefs();
|
||||
const [activeTab, setActiveTab] = useState("workspace");
|
||||
|
||||
const dispatch = useDispatch();
|
||||
useConversationConfig();
|
||||
@@ -59,6 +64,25 @@ function App() {
|
||||
onOpenChange: onSecurityModalOpenChange,
|
||||
} = useDisclosure();
|
||||
|
||||
const renderActiveTab = () => {
|
||||
switch (activeTab) {
|
||||
case "workspace":
|
||||
return (
|
||||
<FilesProvider>
|
||||
<Workspace />
|
||||
</FilesProvider>
|
||||
);
|
||||
case "jupyter":
|
||||
return <JupyterView />;
|
||||
case "browser":
|
||||
return <BrowserView />;
|
||||
case "app":
|
||||
return <AppView />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<WsClientProvider
|
||||
enabled
|
||||
@@ -78,19 +102,38 @@ function App() {
|
||||
<Container
|
||||
className="h-2/3"
|
||||
labels={[
|
||||
{ label: "Workspace", to: "", icon: <CodeIcon /> },
|
||||
{ label: "Jupyter", to: "jupyter", icon: <ListIcon /> },
|
||||
{
|
||||
id: "workspace",
|
||||
label: "Workspace",
|
||||
icon: <CodeIcon />,
|
||||
isActive: activeTab === "workspace",
|
||||
onClick: setActiveTab
|
||||
},
|
||||
{
|
||||
id: "jupyter",
|
||||
label: "Jupyter",
|
||||
icon: <ListIcon />,
|
||||
isActive: activeTab === "jupyter",
|
||||
onClick: setActiveTab
|
||||
},
|
||||
{
|
||||
id: "browser",
|
||||
label: "Browser",
|
||||
to: "browser",
|
||||
icon: <GlobeIcon />,
|
||||
isBeta: true,
|
||||
isActive: activeTab === "browser",
|
||||
onClick: setActiveTab
|
||||
},
|
||||
{
|
||||
id: "app",
|
||||
label: "App",
|
||||
icon: <GlobeIcon />,
|
||||
isActive: activeTab === "app",
|
||||
onClick: setActiveTab
|
||||
},
|
||||
]}
|
||||
>
|
||||
<FilesProvider>
|
||||
<Outlet />
|
||||
</FilesProvider>
|
||||
{renderActiveTab()}
|
||||
</Container>
|
||||
{/* Terminal uses some API that is not compatible in a server-environment. For this reason, we lazy load it to ensure
|
||||
* that it loads only in the client-side. */}
|
||||
|
||||
@@ -3,19 +3,22 @@ enum TabOption {
|
||||
CODE = "code",
|
||||
BROWSER = "browser",
|
||||
JUPYTER = "jupyter",
|
||||
APP = "app",
|
||||
}
|
||||
|
||||
type TabType =
|
||||
| TabOption.PLANNER
|
||||
| TabOption.CODE
|
||||
| TabOption.BROWSER
|
||||
| TabOption.JUPYTER;
|
||||
| TabOption.JUPYTER
|
||||
| TabOption.APP;
|
||||
|
||||
const AllTabs = [
|
||||
TabOption.CODE,
|
||||
TabOption.BROWSER,
|
||||
TabOption.PLANNER,
|
||||
TabOption.JUPYTER,
|
||||
TabOption.APP,
|
||||
];
|
||||
|
||||
export { AllTabs, TabOption, type TabType };
|
||||
|
||||
Reference in New Issue
Block a user