- Connect Your Tools
-
+
+ Connect Your Tools
+
+
Integrate with your favorite services to enhance your research capabilities.
-
- {connectorCategories.map((category, categoryIndex) => (
-
+ {connectorCategories.map((category) => (
+ toggleCategory(category.id)}
- className="border rounded-lg overflow-hidden bg-card"
+ variants={fadeIn}
+ className="rounded-lg border bg-card text-card-foreground shadow-sm"
>
-
-
-
-
- {category.icon}
-
-
-
{category.title}
-
{category.description}
-
-
-
-
-
-
-
-
-
- {category.connectors.map((connector, index) => (
+ toggleCategory(category.id)}
+ className="w-full"
+ >
+
+
{category.title}
+
+
+
-
-
+
+
+
+
+ {category.connectors.map((connector) => (
+
+
+
+
+
+ {connector.icon}
+
+
+
+
+
{connector.title}
+ {connector.status === "coming-soon" && (
+
+ Coming soon
+
+ )}
+ {connector.status === "connected" && (
+
+ Connected
+
+ )}
+
+
+
+
+
+
+ {connector.description}
+
+
+
+
+ {connector.status === 'available' && (
+
+
+ Connect
+
+
+
+
+
+ )}
+ {connector.status === 'coming-soon' && (
+
+ Coming Soon
+
+ )}
+ {connector.status === 'connected' && (
+
+ Manage
+
+ )}
+
+
+
+ ))}
+
+
+
+
+
))}
-
+
);
}
diff --git a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx
index 66f8b0810..b7b4bf3ff 100644
--- a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx
+++ b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx
@@ -1,6 +1,7 @@
"use client";
-import { cn } from "@/lib/utils";
+import { DocumentViewer } from "@/components/document-viewer";
+import { JsonMetadataViewer } from "@/components/json-metadata-viewer";
import {
AlertDialog,
AlertDialogAction,
@@ -12,7 +13,6 @@ import {
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
-import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
@@ -43,6 +43,9 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
+import { useDocuments } from "@/hooks/use-documents";
+import { cn } from "@/lib/utils";
+import { IconBrandGithub, IconBrandNotion, IconBrandSlack, IconBrandYoutube, IconLayoutKanban } from "@tabler/icons-react";
import {
ColumnDef,
ColumnFiltersState,
@@ -59,6 +62,7 @@ import {
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
+import { AnimatePresence, motion } from "framer-motion";
import {
AlertCircle,
ChevronDown,
@@ -70,31 +74,22 @@ import {
CircleAlert,
CircleX,
Columns3,
- Filter,
- ListFilter,
- Plus,
- FileText,
- Globe,
- MessageSquare,
- FileX,
File,
- Trash,
+ FileX,
+ Filter,
+ Globe,
+ ListFilter,
MoreHorizontal,
- Webhook,
+ Trash,
+ Webhook
} from "lucide-react";
-import { useEffect, useId, useMemo, useRef, useState, useContext } from "react";
-import { motion, AnimatePresence } from "framer-motion";
import { useParams } from "next/navigation";
-import { useDocuments } from "@/hooks/use-documents";
-import React from "react";
-import { toast } from "sonner";
+import React, { useContext, useEffect, useId, useMemo, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
import remarkGfm from "remark-gfm";
-import { DocumentViewer } from "@/components/document-viewer";
-import { JsonMetadataViewer } from "@/components/json-metadata-viewer";
-import { IconBrandNotion, IconBrandSlack, IconBrandYoutube } from "@tabler/icons-react";
+import { toast } from "sonner";
// Define animation variants for reuse
const fadeInScale = {
@@ -114,7 +109,7 @@ const fadeInScale = {
type Document = {
id: number;
title: string;
- document_type: "EXTENSION" | "CRAWLED_URL" | "SLACK_CONNECTOR" | "NOTION_CONNECTOR" | "FILE" | "YOUTUBE_VIDEO";
+ document_type: "EXTENSION" | "CRAWLED_URL" | "SLACK_CONNECTOR" | "NOTION_CONNECTOR" | "FILE" | "YOUTUBE_VIDEO" | "LINEAR_CONNECTOR";
document_metadata: any;
content: string;
created_at: string;
@@ -142,6 +137,8 @@ const documentTypeIcons = {
NOTION_CONNECTOR: IconBrandNotion,
FILE: File,
YOUTUBE_VIDEO: IconBrandYoutube,
+ GITHUB_CONNECTOR: IconBrandGithub,
+ LINEAR_CONNECTOR: IconLayoutKanban,
} as const;
const columns: ColumnDef
[] = [
@@ -1028,4 +1025,5 @@ function RowActions({ row }: { row: Row }) {
);
}
-export { DocumentsTable }
\ No newline at end of file
+export { DocumentsTable };
+
diff --git a/surfsense_web/app/docs/[[...slug]]/page.tsx b/surfsense_web/app/docs/[[...slug]]/page.tsx
new file mode 100644
index 000000000..6c8574d87
--- /dev/null
+++ b/surfsense_web/app/docs/[[...slug]]/page.tsx
@@ -0,0 +1,46 @@
+import { source } from '@/lib/source';
+import {
+ DocsBody,
+ DocsDescription,
+ DocsPage,
+ DocsTitle,
+} from 'fumadocs-ui/page';
+import { notFound } from 'next/navigation';
+import { getMDXComponents } from '@/mdx-components';
+
+export default async function Page(props: {
+ params: Promise<{ slug?: string[] }>;
+}) {
+ const params = await props.params;
+ const page = source.getPage(params.slug);
+ if (!page) notFound();
+
+ const MDX = page.data.body;
+
+ return (
+
+ {page.data.title}
+ {page.data.description}
+
+
+
+
+ );
+}
+
+export async function generateStaticParams() {
+ return source.generateParams();
+}
+
+export async function generateMetadata(props: {
+ params: Promise<{ slug?: string[] }>;
+}) {
+ const params = await props.params;
+ const page = source.getPage(params.slug);
+ if (!page) notFound();
+
+ return {
+ title: page.data.title,
+ description: page.data.description,
+ };
+}
\ No newline at end of file
diff --git a/surfsense_web/app/docs/layout.tsx b/surfsense_web/app/docs/layout.tsx
new file mode 100644
index 000000000..e818c1f68
--- /dev/null
+++ b/surfsense_web/app/docs/layout.tsx
@@ -0,0 +1,12 @@
+import { source } from '@/lib/source';
+import { DocsLayout } from 'fumadocs-ui/layouts/docs';
+import type { ReactNode } from 'react';
+import { baseOptions } from '@/app/layout.config';
+
+export default function Layout({ children }: { children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
\ No newline at end of file
diff --git a/surfsense_web/app/globals.css b/surfsense_web/app/globals.css
index 8fdefeca5..98e4411fb 100644
--- a/surfsense_web/app/globals.css
+++ b/surfsense_web/app/globals.css
@@ -1,4 +1,6 @@
-@import "tailwindcss";
+@import 'tailwindcss';
+@import 'fumadocs-ui/css/neutral.css';
+@import 'fumadocs-ui/css/preset.css';
@plugin "tailwindcss-animate";
diff --git a/surfsense_web/app/layout.config.tsx b/surfsense_web/app/layout.config.tsx
new file mode 100644
index 000000000..ef0500157
--- /dev/null
+++ b/surfsense_web/app/layout.config.tsx
@@ -0,0 +1,7 @@
+import { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
+
+export const baseOptions: BaseLayoutProps = {
+ nav: {
+ title: 'SurfSense Documentation',
+ },
+};
\ No newline at end of file
diff --git a/surfsense_web/app/layout.tsx b/surfsense_web/app/layout.tsx
index be0b18079..6b60891a4 100644
--- a/surfsense_web/app/layout.tsx
+++ b/surfsense_web/app/layout.tsx
@@ -5,6 +5,7 @@ import { Roboto } from "next/font/google";
import { Toaster } from "@/components/ui/sonner";
import { ThemeProvider } from "@/components/theme/theme-provider";
+import { RootProvider } from 'fumadocs-ui/provider';
const roboto = Roboto({
subsets: ["latin"],
@@ -64,8 +65,10 @@ export default async function RootLayout({
disableTransitionOnChange
defaultTheme="light"
>
- {children}
-
+
+ {children}
+
+