mirror of
https://github.com/MODSetter/SurfSense.git
synced 2025-09-02 18:49:09 +00:00
fix(ui) : Added back Tavily and Updated the researcher icon for GitHub
This commit is contained in:
parent
62d09d5faa
commit
37f11b1521
3 changed files with 175 additions and 77 deletions
|
@ -15,6 +15,7 @@ import {
|
||||||
IconBrandZoom,
|
IconBrandZoom,
|
||||||
IconChevronRight,
|
IconChevronRight,
|
||||||
IconWorldWww,
|
IconWorldWww,
|
||||||
|
IconChevronDown,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
@ -23,6 +24,8 @@ import Link from "next/link";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
// Define the Connector type
|
// Define the Connector type
|
||||||
|
@ -31,7 +34,7 @@ interface Connector {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
icon: React.ReactNode;
|
icon: React.ReactNode;
|
||||||
status: "available" | "coming-soon" | "connected"; // Added connected status example
|
status: "available" | "coming-soon" | "connected";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConnectorCategory {
|
interface ConnectorCategory {
|
||||||
|
@ -47,12 +50,11 @@ const connectorCategories: ConnectorCategory[] = [
|
||||||
title: "Search Engines",
|
title: "Search Engines",
|
||||||
connectors: [
|
connectors: [
|
||||||
{
|
{
|
||||||
id: "web-search",
|
id: "tavily-api",
|
||||||
title: "Web Search",
|
title: "Tavily API",
|
||||||
description: "Enable web search capabilities for broader context.",
|
description: "Search the web using the Tavily API",
|
||||||
icon: <IconWorldWww className="h-6 w-6" />,
|
icon: <IconWorldWww className="h-6 w-6" />,
|
||||||
status: "available", // Example status
|
status: "available",
|
||||||
// Potentially add config form here if needed (e.g., choosing provider)
|
|
||||||
},
|
},
|
||||||
// Add other search engine connectors like Tavily, Serper if they have UI config
|
// Add other search engine connectors like Tavily, Serper if they have UI config
|
||||||
],
|
],
|
||||||
|
@ -94,10 +96,9 @@ const connectorCategories: ConnectorCategory[] = [
|
||||||
description: "Connect to your Notion workspace to access pages and databases.",
|
description: "Connect to your Notion workspace to access pages and databases.",
|
||||||
icon: <IconBrandNotion className="h-6 w-6" />,
|
icon: <IconBrandNotion className="h-6 w-6" />,
|
||||||
status: "available",
|
status: "available",
|
||||||
// No form here, assumes it links to its own page
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "github-connector", // Keep the id simple
|
id: "github-connector",
|
||||||
title: "GitHub",
|
title: "GitHub",
|
||||||
description: "Connect a GitHub PAT to index code and docs from accessible repositories.",
|
description: "Connect a GitHub PAT to index code and docs from accessible repositories.",
|
||||||
icon: <IconBrandGithub className="h-6 w-6" />,
|
icon: <IconBrandGithub className="h-6 w-6" />,
|
||||||
|
@ -127,6 +128,44 @@ const connectorCategories: ConnectorCategory[] = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Animation variants
|
||||||
|
const fadeIn = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: { opacity: 1, transition: { duration: 0.4 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const staggerContainer = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardVariants = {
|
||||||
|
hidden: { opacity: 0, y: 20 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
type: "spring",
|
||||||
|
stiffness: 260,
|
||||||
|
damping: 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
scale: 1.02,
|
||||||
|
boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
|
||||||
|
transition: {
|
||||||
|
type: "spring",
|
||||||
|
stiffness: 400,
|
||||||
|
damping: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default function ConnectorsPage() {
|
export default function ConnectorsPage() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const searchSpaceId = params.search_space_id as string;
|
const searchSpaceId = params.search_space_id as string;
|
||||||
|
@ -141,85 +180,142 @@ export default function ConnectorsPage() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto py-8 max-w-6xl">
|
<div className="container mx-auto py-12 max-w-6xl">
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{
|
||||||
className="mb-8 text-center"
|
duration: 0.6,
|
||||||
|
ease: [0.22, 1, 0.36, 1]
|
||||||
|
}}
|
||||||
|
className="mb-12 text-center"
|
||||||
>
|
>
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Connect Your Tools</h1>
|
<h1 className="text-4xl font-bold tracking-tight bg-gradient-to-r from-indigo-500 to-purple-500 bg-clip-text text-transparent">
|
||||||
<p className="text-muted-foreground mt-2">
|
Connect Your Tools
|
||||||
|
</h1>
|
||||||
|
<p className="text-muted-foreground mt-3 text-lg max-w-2xl mx-auto">
|
||||||
Integrate with your favorite services to enhance your research capabilities.
|
Integrate with your favorite services to enhance your research capabilities.
|
||||||
</p>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
<div className="space-y-6">
|
<motion.div
|
||||||
|
className="space-y-8"
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
variants={staggerContainer}
|
||||||
|
>
|
||||||
{connectorCategories.map((category) => (
|
{connectorCategories.map((category) => (
|
||||||
<Collapsible
|
<motion.div
|
||||||
key={category.id}
|
key={category.id}
|
||||||
|
variants={fadeIn}
|
||||||
|
className="rounded-lg border bg-card text-card-foreground shadow-sm"
|
||||||
|
>
|
||||||
|
<Collapsible
|
||||||
open={expandedCategories.includes(category.id)}
|
open={expandedCategories.includes(category.id)}
|
||||||
onOpenChange={() => toggleCategory(category.id)}
|
onOpenChange={() => toggleCategory(category.id)}
|
||||||
className="space-y-2"
|
className="w-full"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between space-x-4 px-1">
|
<div className="flex items-center justify-between space-x-4 p-4">
|
||||||
<h3 className="text-lg font-semibold dark:text-gray-200">{category.title}</h3>
|
<h3 className="text-xl font-semibold">{category.title}</h3>
|
||||||
<CollapsibleTrigger asChild>
|
<CollapsibleTrigger asChild>
|
||||||
{/* Replace with your preferred expand/collapse icon/button */}
|
<Button variant="ghost" size="sm" className="w-9 p-0 hover:bg-muted">
|
||||||
<button className="text-sm text-indigo-600 hover:underline dark:text-indigo-400">
|
<motion.div
|
||||||
{expandedCategories.includes(category.id) ? "Collapse" : "Expand"}
|
animate={{ rotate: expandedCategories.includes(category.id) ? 180 : 0 }}
|
||||||
</button>
|
transition={{ duration: 0.3, ease: "easeInOut" }}
|
||||||
|
>
|
||||||
|
<IconChevronDown className="h-5 w-5" />
|
||||||
|
</motion.div>
|
||||||
|
<span className="sr-only">Toggle</span>
|
||||||
|
</Button>
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CollapsibleContent>
|
<CollapsibleContent>
|
||||||
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 p-1">
|
<AnimatePresence>
|
||||||
|
<motion.div
|
||||||
|
className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 p-4"
|
||||||
|
variants={staggerContainer}
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
exit="hidden"
|
||||||
|
>
|
||||||
{category.connectors.map((connector) => (
|
{category.connectors.map((connector) => (
|
||||||
<div key={connector.id} className="col-span-1 flex flex-col divide-y divide-gray-200 dark:divide-gray-700 rounded-lg bg-white dark:bg-gray-800 shadow">
|
<motion.div
|
||||||
<div className="flex w-full items-center justify-between space-x-6 p-6 flex-grow">
|
key={connector.id}
|
||||||
<div className="flex-1 truncate">
|
variants={cardVariants}
|
||||||
<div className="flex items-center space-x-3">
|
whileHover="hover"
|
||||||
<span className="text-gray-900 dark:text-gray-100">{connector.icon}</span>
|
className="col-span-1"
|
||||||
<h3 className="truncate text-sm font-medium text-gray-900 dark:text-gray-100">
|
>
|
||||||
{connector.title}
|
<Card className="h-full flex flex-col overflow-hidden border-transparent transition-all duration-200 hover:border-primary/50">
|
||||||
</h3>
|
<CardHeader className="flex-row items-center gap-4 pb-2">
|
||||||
{connector.status === "coming-soon" && (
|
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 dark:bg-primary/20">
|
||||||
<span className="inline-block flex-shrink-0 rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">
|
<motion.div
|
||||||
Coming soon
|
whileHover={{ rotate: 5, scale: 1.1 }}
|
||||||
</span>
|
className="text-primary"
|
||||||
)}
|
>
|
||||||
{/* TODO: Add 'Connected' badge based on actual state */}
|
{connector.icon}
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 truncate text-sm text-gray-500 dark:text-gray-400">
|
<div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h3 className="font-medium">{connector.title}</h3>
|
||||||
|
{connector.status === "coming-soon" && (
|
||||||
|
<Badge variant="outline" className="text-xs bg-amber-100 dark:bg-amber-950 text-amber-800 dark:text-amber-300 border-amber-200 dark:border-amber-800">
|
||||||
|
Coming soon
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{connector.status === "connected" && (
|
||||||
|
<Badge variant="outline" className="text-xs bg-green-100 dark:bg-green-950 text-green-800 dark:text-green-300 border-green-200 dark:border-green-800">
|
||||||
|
Connected
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent className="pb-4">
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
{connector.description}
|
{connector.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</CardContent>
|
||||||
</div>
|
|
||||||
{/* Always render Link button if available */}
|
<CardFooter className="mt-auto pt-2">
|
||||||
{connector.status === 'available' && (
|
{connector.status === 'available' && (
|
||||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700">
|
<Link href={`/dashboard/${searchSpaceId}/connectors/add/${connector.id}`} className="w-full">
|
||||||
<Link href={`/dashboard/${searchSpaceId}/connectors/add/${connector.id}`}>
|
<Button variant="default" className="w-full group">
|
||||||
<Button variant="default" className="w-full">
|
<span>Connect</span>
|
||||||
Connect
|
<motion.div
|
||||||
|
className="ml-1"
|
||||||
|
initial={{ x: 0 }}
|
||||||
|
whileHover={{ x: 3 }}
|
||||||
|
transition={{ type: "spring", stiffness: 400, damping: 10 }}
|
||||||
|
>
|
||||||
|
<IconChevronRight className="h-4 w-4" />
|
||||||
|
</motion.div>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{connector.status === 'coming-soon' && (
|
{connector.status === 'coming-soon' && (
|
||||||
<div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700">
|
<Button variant="outline" disabled className="w-full opacity-70">
|
||||||
<Button variant="outline" disabled className="w-full">
|
|
||||||
Coming Soon
|
Coming Soon
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{/* TODO: Add logic for 'connected' status */}
|
{connector.status === 'connected' && (
|
||||||
</div>
|
<Button variant="outline" className="w-full border-green-500 text-green-600 hover:bg-green-50 dark:hover:bg-green-950">
|
||||||
|
Manage
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</motion.div>
|
||||||
|
</AnimatePresence>
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
<Separator className="my-4" />
|
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ export function ModernHeroWithGradients() {
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="mx-auto max-w-3xl py-6 text-center text-base text-gray-600 dark:text-neutral-300 md:text-lg lg:text-xl">
|
<p className="mx-auto max-w-3xl py-6 text-center text-base text-gray-600 dark:text-neutral-300 md:text-lg lg:text-xl">
|
||||||
A Customizable AI Research Agent just like NotebookLM or Perplexity, but connected to external sources such as search engines (Tavily), Slack, Notion, and more.
|
A Customizable AI Research Agent just like NotebookLM or Perplexity, but connected to external sources such as search engines (Tavily), Slack, Notion, YouTube, GitHub and more.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col items-center gap-6 py-6 sm:flex-row">
|
<div className="flex flex-col items-center gap-6 py-6 sm:flex-row">
|
||||||
<Link
|
<Link
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
Link,
|
Link,
|
||||||
Webhook,
|
Webhook,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { IconBrandNotion, IconBrandSlack, IconBrandYoutube } from "@tabler/icons-react";
|
import { IconBrandNotion, IconBrandSlack, IconBrandYoutube, IconBrandGithub } from "@tabler/icons-react";
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Connector, ResearchMode } from './types';
|
import { Connector, ResearchMode } from './types';
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ export const getConnectorIcon = (connectorType: string) => {
|
||||||
const iconProps = { className: "h-4 w-4" };
|
const iconProps = { className: "h-4 w-4" };
|
||||||
|
|
||||||
switch(connectorType) {
|
switch(connectorType) {
|
||||||
|
case 'GITHUB_CONNECTOR':
|
||||||
|
return <IconBrandGithub {...iconProps} />;
|
||||||
case 'YOUTUBE_VIDEO':
|
case 'YOUTUBE_VIDEO':
|
||||||
return <IconBrandYoutube {...iconProps} />;
|
return <IconBrandYoutube {...iconProps} />;
|
||||||
case 'CRAWLED_URL':
|
case 'CRAWLED_URL':
|
||||||
|
|
Loading…
Add table
Reference in a new issue