Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion webview-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ const App = () => {
isAuthenticated={cloudIsAuthenticated}
cloudApiUrl={cloudApiUrl}
organizations={cloudOrganizations}
onDone={() => switchTab("chat")}
/>
)}
<ChatView
Expand Down
8 changes: 2 additions & 6 deletions webview-ui/src/__tests__/App.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,8 @@ vi.mock("@src/components/marketplace/MarketplaceView", () => ({
}))

vi.mock("@src/components/cloud/CloudView", () => ({
CloudView: function CloudView({ onDone }: { onDone: () => void }) {
return (
<div data-testid="cloud-view" onClick={onDone}>
Cloud View
</div>
)
CloudView: function CloudView() {
return <div data-testid="cloud-view">Cloud View</div>
},
}))

Expand Down
27 changes: 18 additions & 9 deletions webview-ui/src/components/cloud/CloudUpsellDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next"
import { Dialog, DialogContent, DialogHeader, Button } from "@/components/ui"
import RooHero from "../welcome/RooHero"
import { CircleDollarSign, FileStack, Router, Share } from "lucide-react"
import { ArrowRight, Brain, Cable, CircleDollarSign, FileStack, Router, Users2 } from "lucide-react"
import { DialogTitle } from "@radix-ui/react-dialog"

interface CloudUpsellDialogProps {
Expand All @@ -19,21 +19,29 @@ export const renderCloudBenefitsContent = (t: any) => {
</div>
<h1 className="text-xl font-bold text-vscode-foreground">{t("cloud:cloudBenefitsTitle")}</h1>
<div className="text-lg">
<ul className="text-vscode-descriptionForeground space-y-4 my-8">
<ul className="text-vscode-descriptionForeground space-y-2 my-8">
<li className="flex items-start gap-2">
<Router className="size-4 mt-0.5 shrink-0" />
{t("cloud:cloudBenefitWalkaway")}
<Brain className="size-4 mt-1 shrink-0" />
{t("cloud:cloudBenefitProvider")}
</li>
<li className="flex items-start gap-2">
<Users2 className="size-4 mt-1 shrink-0" />
{t("cloud:cloudBenefitCloudAgents")}
</li>
<li className="flex items-start gap-2">
<Share className="size-4 mt-0.5 shrink-0" />
{t("cloud:cloudBenefitSharing")}
<Cable className="size-4 mt-1 shrink-0" />
{t("cloud:cloudBenefitTriggers")}
</li>
<li className="flex items-start gap-2">
<Router className="size-4 mt-1 shrink-0" />
{t("cloud:cloudBenefitWalkaway")}
</li>
<li className="flex items-start gap-2">
<CircleDollarSign className="size-4 mt-0.5 shrink-0" />
<CircleDollarSign className="size-4 mt-1 shrink-0" />
{t("cloud:cloudBenefitMetrics")}
</li>
<li className="flex items-start gap-2">
<FileStack className="size-4 mt-0.5 shrink-0" />
<FileStack className="size-4 mt-1 shrink-0" />
{t("cloud:cloudBenefitHistory")}
</li>
</ul>
Expand All @@ -56,8 +64,9 @@ export const CloudUpsellDialog = ({ open, onOpenChange, onConnect }: CloudUpsell
{renderCloudBenefitsContent(t)}

<div className="flex flex-col gap-4">
<Button onClick={onConnect} className="w-full">
<Button variant="primary" onClick={onConnect} className="w-full">
{t("cloud:connect")}
<ArrowRight />
</Button>
</div>
</div>
Expand Down
17 changes: 6 additions & 11 deletions webview-ui/src/components/cloud/CloudView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { vscode } from "@src/utils/vscode"
import { telemetryClient } from "@src/utils/TelemetryClient"
import { ToggleSwitch } from "@/components/ui/toggle-switch"
import { renderCloudBenefitsContent } from "./CloudUpsellDialog"
import { CircleAlert, Info, Lock, TriangleAlert } from "lucide-react"
import { ArrowRight, CircleAlert, Info, Lock, TriangleAlert } from "lucide-react"
import { cn } from "@/lib/utils"
import { Tab, TabContent, TabHeader } from "../common/Tab"
import { Tab, TabContent } from "../common/Tab"
import { Button } from "@/components/ui/button"
import { OrganizationSwitcher } from "./OrganizationSwitcher"
import { StandardTooltip } from "../ui"
Expand All @@ -23,11 +23,10 @@ type CloudViewProps = {
userInfo: CloudUserInfo | null
isAuthenticated: boolean
cloudApiUrl?: string
onDone: () => void
organizations?: CloudOrganizationMembership[]
}

export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone, organizations = [] }: CloudViewProps) => {
export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, organizations = [] }: CloudViewProps) => {
const { t } = useAppTranslation()
const {
remoteControlEnabled,
Expand Down Expand Up @@ -159,11 +158,6 @@ export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone, orga

return (
<Tab>
<TabHeader className="flex justify-between items-center">
<h3 className="text-vscode-foreground m-0">{isAuthenticated && t("cloud:title")}</h3>
<Button onClick={onDone}>{t("settings:common.done")}</Button>
</TabHeader>

<TabContent className="pt-10">
{isAuthenticated ? (
<>
Expand Down Expand Up @@ -271,12 +265,13 @@ export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone, orga
</>
) : (
<>
<div className="flex flex-col items-start gap-4 px-8 max-w-100">
<div className="flex flex-col items-start gap-4 px-4 max-w-lg">
<div className={cn(authInProgress && "opacity-50")}>{renderCloudBenefitsContent(t)}</div>

{!authInProgress && (
<Button variant="primary" onClick={handleConnectClick} className="w-full">
<Button variant="primary" onClick={handleConnectClick}>
{t("cloud:connect")}
<ArrowRight />
</Button>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ vi.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string) => {
const translations: Record<string, string> = {
"cloud:cloudBenefitsTitle": "Connect to Roo Cloud",
"cloud:cloudBenefitSharing": "Share tasks with your team",
"cloud:cloudBenefitHistory": "Access conversation history",
"cloud:cloudBenefitMetrics": "View usage metrics",
"cloud:cloudBenefitWalkaway": "Walk away with your code",
"cloud:connect": "Connect to Cloud",
"cloud:cloudBenefitsTitle": "Try Roo Code Cloud",
"cloud:cloudBenefitProvider": "Access free and paid models that work great with Roo",
"cloud:cloudBenefitCloudAgents": "Give tasks to autonomous Cloud agents",
"cloud:cloudBenefitTriggers": "Get code reviews on Github, start tasks from Slack and more",
"cloud:cloudBenefitWalkaway": "Follow and control tasks from anywhere (including your phone)",
"cloud:cloudBenefitHistory": "Access your task history from anywhere and share them with others",
"cloud:cloudBenefitMetrics": "Get a holistic view of your token consumption",
"cloud:connect": "Get started",
}
return translations[key] || key
},
Expand All @@ -30,32 +32,37 @@ describe("CloudUpsellDialog", () => {
it("renders dialog when open", () => {
render(<CloudUpsellDialog open={true} onOpenChange={mockOnOpenChange} onConnect={mockOnConnect} />)

expect(screen.getByText("Connect to Roo Cloud")).toBeInTheDocument()
expect(screen.getByText("Share tasks with your team")).toBeInTheDocument()
expect(screen.getByText("Access conversation history")).toBeInTheDocument()
expect(screen.getByText("View usage metrics")).toBeInTheDocument()
expect(screen.getByRole("button", { name: "Connect to Cloud" })).toBeInTheDocument()
expect(screen.getByText("Try Roo Code Cloud")).toBeInTheDocument()
expect(screen.getByText("Access free and paid models that work great with Roo")).toBeInTheDocument()
expect(screen.getByText("Give tasks to autonomous Cloud agents")).toBeInTheDocument()
expect(screen.getByText("Get code reviews on Github, start tasks from Slack and more")).toBeInTheDocument()
expect(screen.getByText("Follow and control tasks from anywhere (including your phone)")).toBeInTheDocument()
expect(
screen.getByText("Access your task history from anywhere and share them with others"),
).toBeInTheDocument()
expect(screen.getByText("Get a holistic view of your token consumption")).toBeInTheDocument()
expect(screen.getByRole("button", { name: "Get started" })).toBeInTheDocument()
})

it("does not render dialog when closed", () => {
render(<CloudUpsellDialog open={false} onOpenChange={mockOnOpenChange} onConnect={mockOnConnect} />)

expect(screen.queryByText("Connect to Roo Cloud")).not.toBeInTheDocument()
expect(screen.queryByText("Try Roo Code Cloud")).not.toBeInTheDocument()
})

it("calls onConnect when connect button is clicked", () => {
render(<CloudUpsellDialog open={true} onOpenChange={mockOnOpenChange} onConnect={mockOnConnect} />)

const connectButton = screen.getByRole("button", { name: "Connect to Cloud" })
const connectButton = screen.getByRole("button", { name: "Get started" })
fireEvent.click(connectButton)

expect(mockOnConnect).toHaveBeenCalledTimes(1)
})

it("renders all three benefits as list items", () => {
it("renders all benefits as list items", () => {
render(<CloudUpsellDialog open={true} onOpenChange={mockOnOpenChange} onConnect={mockOnConnect} />)

const listItems = screen.getAllByRole("listitem")
expect(listItems).toHaveLength(4)
expect(listItems).toHaveLength(6)
})
})
Loading
Loading