From 57daef335d5cc40725de088e94515f2efa76c7a0 Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Thu, 30 Apr 2026 02:24:46 +0000 Subject: [PATCH 1/2] feat: sync options for google drive in nova (#891) --- .../components/add-document/connections.tsx | 149 +++++++++++++++++- 1 file changed, 144 insertions(+), 5 deletions(-) diff --git a/apps/web/components/add-document/connections.tsx b/apps/web/components/add-document/connections.tsx index 84a18adbc..8a003dc36 100644 --- a/apps/web/components/add-document/connections.tsx +++ b/apps/web/components/add-document/connections.tsx @@ -6,15 +6,28 @@ import type { ConnectionResponseSchema } from "@repo/validation/api" import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { GoogleDrive, Notion, OneDrive } from "@ui/assets/icons" import { useCustomer } from "autumn-js/react" -import { Check, Loader, Trash2, Zap } from "lucide-react" +import { Check, ChevronDown, Loader, Trash2, Zap } from "lucide-react" import { useEffect, useState } from "react" import { toast } from "sonner" import type { z } from "zod" import { dmSansClassName } from "@/lib/fonts" import { cn } from "@lib/utils" import { Button } from "@ui/components/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@ui/components/dropdown-menu" import { RemoveConnectionDialog } from "@/components/remove-connection-dialog" +type GDriveSyncScope = "scoped" | "full" + +const GDRIVE_SCOPE_LABELS: Record = { + scoped: "Files & Folders", + full: "Whole Drive", +} + type Connection = z.infer type ConnectorProvider = "google-drive" | "notion" | "onedrive" @@ -54,6 +67,8 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) { const isProUser = hasActivePlan(autumn.customer?.products, "api_pro") const [connectingProvider, setConnectingProvider] = useState(null) + const [gdriveSyncScope, setGdriveSyncScope] = + useState("scoped") const [isUpgrading, setIsUpgrading] = useState(false) const [removeDialog, setRemoveDialog] = useState<{ open: boolean @@ -114,7 +129,13 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) { // Connect mutation const addConnectionMutation = useMutation({ - mutationFn: async (provider: ConnectorProvider) => { + mutationFn: async ({ + provider, + syncScope, + }: { + provider: ConnectorProvider + syncScope?: GDriveSyncScope + }) => { if (!canAddConnection && !isProUser) { throw new Error( "Free plan doesn't include connections. Upgrade to Pro for unlimited connections.", @@ -126,6 +147,10 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) { body: { redirectUrl: window.location.href, containerTags: [selectedProject], + metadata: + provider === "google-drive" && syncScope === "full" + ? { syncScope: "full" } + : undefined, }, }) @@ -180,7 +205,10 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) { const handleConnect = (provider: ConnectorProvider) => { setConnectingProvider(provider) - addConnectionMutation.mutate(provider) + addConnectionMutation.mutate({ + provider, + syncScope: provider === "google-drive" ? gdriveSyncScope : undefined, + }) } const handleDisconnect = (connection: Connection) => { @@ -215,7 +243,66 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) { const isConnecting = connectingProvider === provider || (addConnectionMutation.isPending && - addConnectionMutation.variables === provider) + addConnectionMutation.variables?.provider === provider) + + if (provider === "google-drive") { + return ( +
+ +
+ + + + + + {( + Object.entries(GDRIVE_SCOPE_LABELS) as [ + GDriveSyncScope, + string, + ][] + ).map(([scope, label]) => ( + { + e.stopPropagation() + setGdriveSyncScope(scope) + }} + className="flex items-center justify-between" + > + {label} + {gdriveSyncScope === scope && ( + + )} + + ))} + + +
+ ) + } return ( + ) : provider === "google-drive" ? ( +
+ +
+ + + + + + {( + Object.entries(GDRIVE_SCOPE_LABELS) as [ + GDriveSyncScope, + string, + ][] + ).map(([scope, label]) => ( + { + e.stopPropagation() + setGdriveSyncScope(scope) + }} + className="flex items-center justify-between" + > + {label} + {gdriveSyncScope === scope && ( + + )} + + ))} + + +
) : ( + + {expanded && (hasOutput || (isError && errorText)) && ( +
+ {output?.stdout && output.stdout.length > 0 && ( +
+							{output.stdout}
+						
+ )} + {output?.stderr && output.stderr.length > 0 && ( +
+							{output.stderr}
+						
+ )} + {isError && errorText && ( +
+							{errorText}
+						
+ )} +
+ )} +
+ ) +} + function ToolCallDisplay({ part }: { part: ToolCallDisplayPart }) { const [expanded, setExpanded] = useState(false) const toolName = part.type.replace("tool-", "") + if (toolName === "bash") { + return + } const meta = TOOL_META[toolName] ?? (isWebSearchToolName(toolName)