Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
110 changes: 13 additions & 97 deletions webview-ui/src/components/cloud/__tests__/CloudView.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,7 @@ Object.defineProperty(window, "IMAGES_BASE_URI", {

describe("CloudView", () => {
it("should display benefits when user is not authenticated", () => {
render(
<CloudView
userInfo={null}
isAuthenticated={false}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={null} isAuthenticated={false} cloudApiUrl="https://app.roocode.com" />)

// Check that the benefits section is displayed
expect(screen.getByRole("heading", { name: "Connect to Roo Code Cloud" })).toBeInTheDocument()
Expand All @@ -94,14 +87,7 @@ describe("CloudView", () => {
email: "[email protected]",
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the benefits section is NOT displayed
expect(
Expand All @@ -123,14 +109,7 @@ describe("CloudView", () => {
extensionBridgeEnabled: true,
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the remote control toggle is displayed
expect(screen.getByTestId("remote-control-toggle")).toBeInTheDocument()
Expand All @@ -147,14 +126,7 @@ describe("CloudView", () => {
extensionBridgeEnabled: false,
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the remote control toggle is NOT displayed
expect(screen.queryByTestId("remote-control-toggle")).not.toBeInTheDocument()
Expand All @@ -172,14 +144,7 @@ describe("CloudView", () => {
extensionBridgeEnabled: true, // Bridge enabled but roomote control disabled
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the remote control toggle is NOT displayed
expect(screen.queryByTestId("remote-control-toggle")).not.toBeInTheDocument()
Expand All @@ -202,14 +167,7 @@ describe("CloudView", () => {
extensionBridgeEnabled: true,
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the remote control toggle IS displayed for organization users
// (The ClineProvider would set featureRoomoteControlEnabled to true for org users)
Expand All @@ -226,14 +184,7 @@ describe("CloudView", () => {
email: "[email protected]",
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the cloud URL pill is NOT displayed for production URL
expect(screen.queryByText(/Roo Code Cloud URL:/)).not.toBeInTheDocument()
Expand All @@ -245,29 +196,15 @@ describe("CloudView", () => {
email: "[email protected]",
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://staging.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://staging.roocode.com" />)

// Check that the cloud URL pill is displayed with the staging URL
expect(screen.getByText(/Roo Code Cloud URL:/)).toBeInTheDocument()
expect(screen.getByText("https://staging.roocode.com")).toBeInTheDocument()
})

it("should display cloud URL pill for non-authenticated users when not pointing to production", () => {
render(
<CloudView
userInfo={null}
isAuthenticated={false}
cloudApiUrl="https://dev.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={null} isAuthenticated={false} cloudApiUrl="https://dev.roocode.com" />)

// Check that the cloud URL pill is displayed even when not authenticated
expect(screen.getByText(/Roo Code Cloud URL:/)).toBeInTheDocument()
Expand All @@ -280,7 +217,7 @@ describe("CloudView", () => {
email: "[email protected]",
}

render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} onDone={() => {}} />)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} />)

// Check that the cloud URL pill is NOT displayed when cloudApiUrl is undefined
expect(screen.queryByText(/Roo Code Cloud URL:/)).not.toBeInTheDocument()
Expand All @@ -294,14 +231,7 @@ describe("CloudView", () => {
organizationName: "Test Organization",
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the task sync toggle is disabled for organization users
const taskSyncToggle = screen.getByTestId("task-sync-toggle")
Expand All @@ -326,14 +256,7 @@ describe("CloudView", () => {
// No organizationId - regular user
}

render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the task sync toggle is enabled for non-organization users
const taskSyncToggle = screen.getByTestId("task-sync-toggle")
Expand All @@ -353,14 +276,7 @@ describe("CloudView", () => {
}

// Test with task sync enabled
render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
render(<CloudView userInfo={mockUserInfo} isAuthenticated={true} cloudApiUrl="https://app.roocode.com" />)

// Check that the toggle shows the current state (enabled in this case)
const taskSyncToggle = screen.getByTestId("task-sync-toggle")
Expand Down
2 changes: 1 addition & 1 deletion webview-ui/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer active:opacity-80",
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer active:opacity-80",
{
variants: {
variant: {
Expand Down
12 changes: 7 additions & 5 deletions webview-ui/src/i18n/locales/ca/cloud.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions webview-ui/src/i18n/locales/de/cloud.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions webview-ui/src/i18n/locales/en/cloud.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
"signIn": "Connect to Roo Code Cloud",
"connect": "Get started",
"cloudBenefitsTitle": "Try Roo Code Cloud",
"cloudBenefitProvider": "Access free and paid models that work great with Roo",
"cloudBenefitCloudAgents": "Give tasks to autonomous Cloud agents",
"cloudBenefitTriggers": "Get code reviews on Github, start tasks from Slack and more",
"cloudBenefitWalkaway": "Follow and control tasks from anywhere (including your phone)",
"cloudBenefitSharing": "Share tasks with others",
"cloudBenefitHistory": "Access your task history from anywhere",
"cloudBenefitHistory": "Access your task history from anywhere and share them with others",
"cloudBenefitMetrics": "Get a holistic view of your token consumption",
"visitCloudWebsite": "Visit Roo Code Cloud",
"taskSync": "Task sync",
Expand Down
Loading
Loading