From 2655692db361aba97a1b628e9311013c9e48c616 Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Mon, 4 Aug 2025 01:05:12 +0200 Subject: [PATCH] add UI implementations --- .../add/google-gmail-connector/page.tsx | 199 ++++++++++++++++++ .../[search_space_id]/connectors/add/page.tsx | 6 +- .../components/chat/ConnectorComponents.tsx | 3 + 3 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx new file mode 100644 index 0000000..6c130bf --- /dev/null +++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/google-gmail-connector/page.tsx @@ -0,0 +1,199 @@ +"use client"; + +import { zodResolver } from "@hookform/resolvers/zod"; +import { IconMail } from "@tabler/icons-react"; +import { motion } from "framer-motion"; +import { ArrowLeft, Check, ExternalLink, Loader2 } from "lucide-react"; +import Link from "next/link"; +import { useParams, useRouter, useSearchParams } from "next/navigation"; +import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + type SearchSourceConnector, + useSearchSourceConnectors, +} from "@/hooks/useSearchSourceConnectors"; + +export default function GoogleGmailConnectorPage() { + const router = useRouter(); + const params = useParams(); + const searchSpaceId = params.search_space_id as string; + const [isConnecting, setIsConnecting] = useState(false); + const [doesConnectorExist, setDoesConnectorExist] = useState(false); + + const { fetchConnectors } = useSearchSourceConnectors(); + + useEffect(() => { + fetchConnectors().then((data) => { + const connector = data.find( + (c: SearchSourceConnector) => c.connector_type === "GOOGLE_GMAIL_CONNECTOR" + ); + if (connector) { + setDoesConnectorExist(true); + } + }); + }, []); + + // Handle Google OAuth connection + const handleConnectGoogle = async () => { + try { + setIsConnecting(true); + // Call backend to initiate authorization flow + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/auth/google/gmail/connector/add/?space_id=${searchSpaceId}`, + { + method: "GET", + headers: { + Authorization: `Bearer ${localStorage.getItem("surfsense_bearer_token")}`, + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to initiate Google OAuth"); + } + + const data = await response.json(); + + // Redirect to Google for authentication + window.location.href = data.auth_url; + } catch (error) { + console.error("Error connecting to Google:", error); + toast.error("Failed to connect to Google Gmail"); + } finally { + setIsConnecting(false); + } + }; + + return ( +
+ + {/* Header */} +
+ + + Back to connectors + +
+
+ +
+
+

Connect Google Gmail

+

+ Connect your Gmail account to search through your emails +

+
+
+
+ + {/* Connection Card */} + {!doesConnectorExist ? ( + + + Connect Your Gmail Account + + Securely connect your Gmail account to enable email search within SurfSense. We'll + only access your emails with read-only permissions. + + + +
+ + Read-only access to your emails +
+
+ + Search through email content and metadata +
+
+ + Secure OAuth 2.0 authentication +
+
+ + You can disconnect anytime +
+
+ + + + +
+ ) : ( + /* Configuration Form Card */ + + + ✅ Your Gmail is successfully connected! + + + )} + + {/* Information Card */} + + + What data will be indexed? + + +
+

Email Content

+

+ We'll index the content of your emails including subject lines, sender information, + and message body text to make them searchable. +

+
+
+

Email Metadata

+

+ Information like sender, recipient, date, and labels will be indexed to provide + better search context and filtering options. +

+
+
+

Privacy & Security

+

+ Your emails are processed securely and stored with encryption. We only access emails + with read-only permissions and never modify or send emails on your behalf. +

+
+
+
+
+
+ ); +} diff --git a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx index c6ec629..2d4f2b9 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx @@ -157,11 +157,11 @@ const connectorCategories: ConnectorCategory[] = [ status: "available", }, { - id: "gmail", + id: "google-gmail-connector", title: "Gmail", - description: "Connect to your Gmail account to access emails.", + description: "Connect to your Gmail account to search through your emails.", icon: , - status: "coming-soon", + status: "available", }, { id: "zoom", diff --git a/surfsense_web/components/chat/ConnectorComponents.tsx b/surfsense_web/components/chat/ConnectorComponents.tsx index 2a3cdb4..d66227e 100644 --- a/surfsense_web/components/chat/ConnectorComponents.tsx +++ b/surfsense_web/components/chat/ConnectorComponents.tsx @@ -7,6 +7,7 @@ import { IconCalendar, IconLayoutKanban, IconLinkPlus, + IconMail, IconTicket, } from "@tabler/icons-react"; import { @@ -59,6 +60,8 @@ export const getConnectorIcon = (connectorType: string) => { return ; case "GOOGLE_CALENDAR_CONNECTOR": return ; + case "GOOGLE_GMAIL_CONNECTOR": + return ; case "DEEP": return ; case "DEEPER":