mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-23 19:05:16 +02:00
refactor: connector icon handling by centralizing icon retrieval in contracts.
This commit is contained in:
parent
8f1fba52b4
commit
b33c2904a6
25 changed files with 318 additions and 310 deletions
|
|
@ -15,6 +15,7 @@ import {
|
|||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from "@/components/ui/sheet";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
import { useDocumentByChunk } from "@/hooks/use-document-by-chunk";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ export const CitationDisplay: React.FC<{ index: number; node: any }> = ({ index,
|
|||
<SheetContent side="right" className="w-full sm:max-w-5xl lg:max-w-7xl">
|
||||
<SheetHeader className="px-6 py-4 border-b">
|
||||
<SheetTitle className="flex items-center gap-3 text-lg">
|
||||
<FileText className="h-6 w-6" />
|
||||
{getConnectorIcon(sourceType)}
|
||||
{document?.title || node?.metadata?.title || node?.metadata?.group_name || "Source"}
|
||||
</SheetTitle>
|
||||
<SheetDescription className="text-base mt-2">
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ import { Brain, Check, FolderOpen, Zap } from "lucide-react";
|
|||
import { useParams } from "next/navigation";
|
||||
import React, { Suspense, useCallback, useState } from "react";
|
||||
import type { ResearchMode } from "@/components/chat";
|
||||
import {
|
||||
ConnectorButton as ConnectorButtonComponent,
|
||||
getConnectorIcon,
|
||||
} from "@/components/chat/ConnectorComponents";
|
||||
import { ConnectorButton as ConnectorButtonComponent } from "@/components/chat/ConnectorComponents";
|
||||
import { DocumentsDataTable } from "@/components/chat/DocumentsDataTable";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -27,6 +24,7 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
import { type Document, useDocuments } from "@/hooks/use-documents";
|
||||
import { useLLMConfigs, useLLMPreferences } from "@/hooks/use-llm-configs";
|
||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||
|
|
|
|||
|
|
@ -1,31 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import { getAnnotationData, type Message } from "@llamaindex/chat-ui";
|
||||
import {
|
||||
IconBrandDiscord,
|
||||
IconBrandGithub,
|
||||
IconBrandNotion,
|
||||
IconBrandSlack,
|
||||
IconBrandYoutube,
|
||||
} from "@tabler/icons-react";
|
||||
import {
|
||||
BookOpen,
|
||||
Calendar,
|
||||
CheckSquare,
|
||||
Database,
|
||||
ExternalLink,
|
||||
FileText,
|
||||
Globe,
|
||||
Link2,
|
||||
Mail,
|
||||
Puzzle,
|
||||
} from "lucide-react";
|
||||
import { ExternalLink, FileText } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
|
||||
interface Source {
|
||||
id: string;
|
||||
|
|
@ -56,86 +39,11 @@ interface SourceNode {
|
|||
}
|
||||
|
||||
function getSourceIcon(type: string) {
|
||||
switch (type) {
|
||||
// GitHub
|
||||
case "USER_SELECTED_GITHUB_CONNECTOR":
|
||||
case "GITHUB_CONNECTOR":
|
||||
return <IconBrandGithub className="h-4 w-4" />;
|
||||
|
||||
// Notion
|
||||
case "USER_SELECTED_NOTION_CONNECTOR":
|
||||
case "NOTION_CONNECTOR":
|
||||
return <IconBrandNotion className="h-4 w-4" />;
|
||||
|
||||
// Slack
|
||||
case "USER_SELECTED_SLACK_CONNECTOR":
|
||||
case "SLACK_CONNECTOR":
|
||||
return <IconBrandSlack className="h-4 w-4" />;
|
||||
|
||||
// Discord
|
||||
case "USER_SELECTED_DISCORD_CONNECTOR":
|
||||
case "DISCORD_CONNECTOR":
|
||||
return <IconBrandDiscord className="h-4 w-4" />;
|
||||
|
||||
// Google Calendar
|
||||
case "USER_SELECTED_GOOGLE_CALENDAR_CONNECTOR":
|
||||
case "GOOGLE_CALENDAR_CONNECTOR":
|
||||
return <Calendar className="h-4 w-4" />;
|
||||
|
||||
// Google Gmail
|
||||
case "USER_SELECTED_GOOGLE_GMAIL_CONNECTOR":
|
||||
case "GOOGLE_GMAIL_CONNECTOR":
|
||||
return <Mail className="h-4 w-4" />;
|
||||
|
||||
// Airtable
|
||||
case "USER_SELECTED_AIRTABLE_CONNECTOR":
|
||||
case "AIRTABLE_CONNECTOR":
|
||||
return <Database className="h-4 w-4" />;
|
||||
|
||||
// YouTube
|
||||
case "USER_SELECTED_YOUTUBE_VIDEO":
|
||||
case "YOUTUBE_VIDEO":
|
||||
return <IconBrandYoutube className="h-4 w-4" />;
|
||||
|
||||
// Linear
|
||||
case "USER_SELECTED_LINEAR_CONNECTOR":
|
||||
case "LINEAR_CONNECTOR":
|
||||
return <CheckSquare className="h-4 w-4" />;
|
||||
|
||||
// Jira
|
||||
case "USER_SELECTED_JIRA_CONNECTOR":
|
||||
case "JIRA_CONNECTOR":
|
||||
return <CheckSquare className="h-4 w-4" />;
|
||||
|
||||
// Confluence
|
||||
case "USER_SELECTED_CONFLUENCE_CONNECTOR":
|
||||
case "CONFLUENCE_CONNECTOR":
|
||||
return <BookOpen className="h-4 w-4" />;
|
||||
|
||||
// ClickUp
|
||||
case "USER_SELECTED_CLICKUP_CONNECTOR":
|
||||
case "CLICKUP_CONNECTOR":
|
||||
return <CheckSquare className="h-4 w-4" />;
|
||||
|
||||
// Files
|
||||
case "USER_SELECTED_FILE":
|
||||
case "FILE":
|
||||
return <FileText className="h-4 w-4" />;
|
||||
|
||||
// Extension
|
||||
case "USER_SELECTED_EXTENSION":
|
||||
case "EXTENSION":
|
||||
return <Puzzle className="h-4 w-4" />;
|
||||
|
||||
// Crawled URL
|
||||
case "USER_SELECTED_CRAWLED_URL":
|
||||
case "CRAWLED_URL":
|
||||
return <Link2 className="h-4 w-4" />;
|
||||
|
||||
// Default for any other source type
|
||||
default:
|
||||
return <Globe className="h-4 w-4" />;
|
||||
}
|
||||
// Handle USER_SELECTED_ prefix
|
||||
const normalizedType = type.startsWith("USER_SELECTED_")
|
||||
? type.replace("USER_SELECTED_", "")
|
||||
: type;
|
||||
return getConnectorIcon(normalizedType, "h-4 w-4");
|
||||
}
|
||||
|
||||
function SourceCard({ source }: { source: Source }) {
|
||||
|
|
|
|||
|
|
@ -1,81 +1,9 @@
|
|||
import {
|
||||
IconBrandDiscord,
|
||||
IconBrandGithub,
|
||||
IconBrandNotion,
|
||||
IconBrandSlack,
|
||||
IconBrandYoutube,
|
||||
IconCalendar,
|
||||
IconLayoutKanban,
|
||||
IconLinkPlus,
|
||||
IconMail,
|
||||
IconTable,
|
||||
IconTicket,
|
||||
} from "@tabler/icons-react";
|
||||
import {
|
||||
ChevronDown,
|
||||
File,
|
||||
FileText,
|
||||
Globe,
|
||||
Link,
|
||||
MessageCircle,
|
||||
Microscope,
|
||||
Plus,
|
||||
Search,
|
||||
Sparkles,
|
||||
Telescope,
|
||||
Webhook,
|
||||
} from "lucide-react";
|
||||
import { ChevronDown, FileText, MessageCircle, Plus } from "lucide-react";
|
||||
import type React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
import type { Connector, ResearchMode } from "./types";
|
||||
|
||||
// Helper function to get connector icon
|
||||
export const getConnectorIcon = (connectorType: string) => {
|
||||
const iconProps = { className: "h-4 w-4" };
|
||||
|
||||
switch (connectorType) {
|
||||
case "LINKUP_API":
|
||||
return <IconLinkPlus {...iconProps} />;
|
||||
case "LINEAR_CONNECTOR":
|
||||
return <IconLayoutKanban {...iconProps} />;
|
||||
case "GITHUB_CONNECTOR":
|
||||
return <IconBrandGithub {...iconProps} />;
|
||||
case "YOUTUBE_VIDEO":
|
||||
return <IconBrandYoutube {...iconProps} />;
|
||||
case "CRAWLED_URL":
|
||||
return <Globe {...iconProps} />;
|
||||
case "FILE":
|
||||
return <File {...iconProps} />;
|
||||
case "EXTENSION":
|
||||
return <Webhook {...iconProps} />;
|
||||
case "SERPER_API":
|
||||
case "TAVILY_API":
|
||||
return <Link {...iconProps} />;
|
||||
case "SLACK_CONNECTOR":
|
||||
return <IconBrandSlack {...iconProps} />;
|
||||
case "NOTION_CONNECTOR":
|
||||
return <IconBrandNotion {...iconProps} />;
|
||||
case "DISCORD_CONNECTOR":
|
||||
return <IconBrandDiscord {...iconProps} />;
|
||||
case "JIRA_CONNECTOR":
|
||||
return <IconTicket {...iconProps} />;
|
||||
case "GOOGLE_CALENDAR_CONNECTOR":
|
||||
return <IconCalendar {...iconProps} />;
|
||||
case "GOOGLE_GMAIL_CONNECTOR":
|
||||
return <IconMail {...iconProps} />;
|
||||
case "AIRTABLE_CONNECTOR":
|
||||
return <IconTable {...iconProps} />;
|
||||
case "DEEP":
|
||||
return <Sparkles {...iconProps} />;
|
||||
case "DEEPER":
|
||||
return <Microscope {...iconProps} />;
|
||||
case "DEEPEST":
|
||||
return <Telescope {...iconProps} />;
|
||||
default:
|
||||
return <Search {...iconProps} />;
|
||||
}
|
||||
};
|
||||
|
||||
export const researcherOptions: {
|
||||
value: ResearchMode;
|
||||
label: string;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import {
|
|||
} from "@tanstack/react-table";
|
||||
import { ArrowUpDown, Calendar, FileText, Search } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
|
@ -33,6 +32,8 @@ import {
|
|||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
import type { Document, DocumentType } from "@/hooks/use-documents";
|
||||
|
||||
interface DocumentsDataTableProps {
|
||||
|
|
@ -42,42 +43,16 @@ interface DocumentsDataTableProps {
|
|||
initialSelectedDocuments?: Document[];
|
||||
}
|
||||
|
||||
const DOCUMENT_TYPES: (DocumentType | "ALL")[] = [
|
||||
// Combine EnumConnectorName with additional document types
|
||||
const DOCUMENT_TYPES: (string | "ALL")[] = [
|
||||
"ALL",
|
||||
"FILE",
|
||||
"EXTENSION",
|
||||
"CRAWLED_URL",
|
||||
"YOUTUBE_VIDEO",
|
||||
"SLACK_CONNECTOR",
|
||||
"NOTION_CONNECTOR",
|
||||
"GITHUB_CONNECTOR",
|
||||
"LINEAR_CONNECTOR",
|
||||
"DISCORD_CONNECTOR",
|
||||
"JIRA_CONNECTOR",
|
||||
"CONFLUENCE_CONNECTOR",
|
||||
"CLICKUP_CONNECTOR",
|
||||
"GOOGLE_CALENDAR_CONNECTOR",
|
||||
"GOOGLE_GMAIL_CONNECTOR",
|
||||
"AIRTABLE_CONNECTOR",
|
||||
...Object.values(EnumConnectorName),
|
||||
];
|
||||
|
||||
const getDocumentTypeColor = (type: DocumentType) => {
|
||||
const colors = {
|
||||
FILE: "bg-blue-50 text-blue-700 border-blue-200",
|
||||
EXTENSION: "bg-green-50 text-green-700 border-green-200",
|
||||
CRAWLED_URL: "bg-purple-50 text-purple-700 border-purple-200",
|
||||
YOUTUBE_VIDEO: "bg-red-50 text-red-700 border-red-200",
|
||||
SLACK_CONNECTOR: "bg-yellow-50 text-yellow-700 border-yellow-200",
|
||||
NOTION_CONNECTOR: "bg-indigo-50 text-indigo-700 border-indigo-200",
|
||||
GITHUB_CONNECTOR: "bg-gray-50 text-gray-700 border-gray-200",
|
||||
LINEAR_CONNECTOR: "bg-pink-50 text-pink-700 border-pink-200",
|
||||
DISCORD_CONNECTOR: "bg-violet-50 text-violet-700 border-violet-200",
|
||||
JIRA_CONNECTOR: "bg-orange-50 text-orange-700 border-orange-200",
|
||||
CONFLUENCE_CONNECTOR: "bg-teal-50 text-teal-700 border-teal-200",
|
||||
};
|
||||
return colors[type] || "bg-gray-50 text-gray-700 border-gray-200";
|
||||
};
|
||||
|
||||
const columns: ColumnDef<Document>[] = [
|
||||
{
|
||||
id: "select",
|
||||
|
|
@ -133,13 +108,9 @@ const columns: ColumnDef<Document>[] = [
|
|||
cell: ({ row }) => {
|
||||
const type = row.getValue("document_type") as DocumentType;
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`${getDocumentTypeColor(type)} text-[10px] sm:text-xs px-1 sm:px-2`}
|
||||
>
|
||||
<span className="hidden sm:inline">{type.replace(/_/g, " ")}</span>
|
||||
<span className="sm:hidden">{type.split("_")[0]}</span>
|
||||
</Badge>
|
||||
<div className="flex items-center gap-2" title={type}>
|
||||
<span className="text-primary">{getConnectorIcon(type)}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
size: 80,
|
||||
|
|
@ -214,7 +185,7 @@ export function DocumentsDataTable({
|
|||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||
const [documentTypeFilter, setDocumentTypeFilter] = useState<DocumentType | "ALL">("ALL");
|
||||
const [documentTypeFilter, setDocumentTypeFilter] = useState<string | "ALL">("ALL");
|
||||
|
||||
// Memoize initial row selection to prevent infinite loops
|
||||
const initialRowSelection = useMemo(() => {
|
||||
|
|
@ -311,7 +282,7 @@ export function DocumentsDataTable({
|
|||
</div>
|
||||
<Select
|
||||
value={documentTypeFilter}
|
||||
onValueChange={(value) => setDocumentTypeFilter(value as DocumentType | "ALL")}
|
||||
onValueChange={(value) => setDocumentTypeFilter(value as string | "ALL")}
|
||||
>
|
||||
<SelectTrigger className="w-full sm:w-[180px]">
|
||||
<SelectValue />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue