diff --git a/frontend/components/discord-link.tsx b/frontend/components/discord-link.tsx deleted file mode 100644 index 584daa26..00000000 --- a/frontend/components/discord-link.tsx +++ /dev/null @@ -1,47 +0,0 @@ -"use client"; - -import * as React from "react"; -import { cn } from "@/lib/utils"; -import { useDiscordMembers } from "@/hooks/use-discord-members"; -import { formatCount } from "@/lib/format-count"; - -interface DiscordLinkProps { - inviteCode?: string; - className?: string; -} - -const DiscordLink = React.forwardRef( - ({ inviteCode = "EqksyE2EX9", className }, ref) => { - const { data, isLoading, error } = useDiscordMembers(inviteCode); - - return ( - - - - - - {isLoading - ? "..." - : error - ? "--" - : data - ? formatCount(data.approximate_member_count) - : "--"} - - - ); - }, -); - -DiscordLink.displayName = "DiscordLink"; - -export { DiscordLink }; diff --git a/frontend/components/file-upload-area.tsx b/frontend/components/file-upload-area.tsx deleted file mode 100644 index 84f0806a..00000000 --- a/frontend/components/file-upload-area.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"; - -import * as React from "react"; -import { cn } from "@/lib/utils"; -import { Button } from "@/components/ui/button"; -import { Loader2 } from "lucide-react"; - -interface FileUploadAreaProps { - onFileSelected?: (file: File) => void; - isLoading?: boolean; - className?: string; -} - -const FileUploadArea = React.forwardRef( - ({ onFileSelected, isLoading = false, className }, ref) => { - const [isDragging, setIsDragging] = React.useState(false); - const fileInputRef = React.useRef(null); - - const handleDragOver = (e: React.DragEvent) => { - e.preventDefault(); - setIsDragging(true); - }; - - const handleDragLeave = (e: React.DragEvent) => { - e.preventDefault(); - setIsDragging(false); - }; - - const handleDrop = (e: React.DragEvent) => { - e.preventDefault(); - setIsDragging(false); - - const files = Array.from(e.dataTransfer.files); - if (files.length > 0 && onFileSelected) { - onFileSelected(files[0]); - } - }; - - const handleFileSelect = (e: React.ChangeEvent) => { - const files = Array.from(e.target.files || []); - if (files.length > 0 && onFileSelected) { - onFileSelected(files[0]); - } - }; - - const handleClick = () => { - if (!isLoading) { - fileInputRef.current?.click(); - } - }; - - return ( -
- - -
- {isLoading && ( -
- -
- )} - -
-

- {isLoading - ? "Processing file..." - : "Drop files here or click to upload"} -

-

- {isLoading - ? "Please wait while your file is being processed" - : ""} -

-
- - {!isLoading && } -
-
- ); - }, -); - -FileUploadArea.displayName = "FileUploadArea"; - -export { FileUploadArea }; diff --git a/frontend/components/github-star-button.tsx b/frontend/components/github-star-button.tsx deleted file mode 100644 index 81e4ca98..00000000 --- a/frontend/components/github-star-button.tsx +++ /dev/null @@ -1,47 +0,0 @@ -"use client"; - -import * as React from "react"; -import { cn } from "@/lib/utils"; -import { Github } from "lucide-react"; -import { useGitHubStars } from "@/hooks/use-github-stars"; -import { formatCount } from "@/lib/format-count"; - -interface GitHubStarButtonProps { - repo?: string; - className?: string; -} - -const GitHubStarButton = React.forwardRef< - HTMLAnchorElement, - GitHubStarButtonProps ->(({ repo = "phact/openrag", className }, ref) => { - const { data, isLoading, error } = useGitHubStars(repo); - - return ( - - - - {isLoading - ? "..." - : error - ? "--" - : data - ? formatCount(data.stargazers_count) - : "--"} - - - ); -}); - -GitHubStarButton.displayName = "GitHubStarButton"; - -export { GitHubStarButton }; diff --git a/frontend/components/knowledge-filter-dropdown.tsx b/frontend/components/knowledge-filter-dropdown.tsx deleted file mode 100644 index cb2106d9..00000000 --- a/frontend/components/knowledge-filter-dropdown.tsx +++ /dev/null @@ -1,458 +0,0 @@ -"use client"; - -import { useState, useEffect, useRef } from "react"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Card, CardContent } from "@/components/ui/card"; - -import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; -import { - ChevronDown, - Filter, - Search, - X, - Loader2, - Plus, - Save, -} from "lucide-react"; -import { cn } from "@/lib/utils"; - -interface KnowledgeFilter { - id: string; - name: string; - description: string; - query_data: string; - owner: string; - created_at: string; - updated_at: string; -} - -interface ParsedQueryData { - query: string; - filters: { - data_sources: string[]; - document_types: string[]; - owners: string[]; - }; - limit: number; - scoreThreshold: number; -} - -interface KnowledgeFilterDropdownProps { - selectedFilter: KnowledgeFilter | null; - onFilterSelect: (filter: KnowledgeFilter | null) => void; -} - -export function KnowledgeFilterDropdown({ - selectedFilter, - onFilterSelect, -}: KnowledgeFilterDropdownProps) { - const [isOpen, setIsOpen] = useState(false); - const [filters, setFilters] = useState([]); - const [loading, setLoading] = useState(false); - const [searchQuery, setSearchQuery] = useState(""); - const [showCreateModal, setShowCreateModal] = useState(false); - const [createName, setCreateName] = useState(""); - const [createDescription, setCreateDescription] = useState(""); - const [creating, setCreating] = useState(false); - const dropdownRef = useRef(null); - - const loadFilters = async (query = "") => { - setLoading(true); - try { - const response = await fetch("/api/knowledge-filter/search", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - query, - limit: 20, // Limit for dropdown - }), - }); - - const result = await response.json(); - if (response.ok && result.success) { - setFilters(result.filters); - } else { - console.error("Failed to load knowledge filters:", result.error); - setFilters([]); - } - } catch (error) { - console.error("Error loading knowledge filters:", error); - setFilters([]); - } finally { - setLoading(false); - } - }; - - const deleteFilter = async (filterId: string, e: React.MouseEvent) => { - e.stopPropagation(); - - try { - const response = await fetch(`/api/knowledge-filter/${filterId}`, { - method: "DELETE", - }); - - if (response.ok) { - // Remove from local state - setFilters((prev) => prev.filter((f) => f.id !== filterId)); - - // If this was the selected filter, clear selection - if (selectedFilter?.id === filterId) { - onFilterSelect(null); - } - } else { - console.error("Failed to delete knowledge filter"); - } - } catch (error) { - console.error("Error deleting knowledge filter:", error); - } - }; - - const handleFilterSelect = (filter: KnowledgeFilter) => { - onFilterSelect(filter); - setIsOpen(false); - }; - - const handleClearFilter = () => { - onFilterSelect(null); - setIsOpen(false); - }; - - const handleCreateNew = () => { - setIsOpen(false); - setShowCreateModal(true); - }; - - const handleCreateFilter = async () => { - if (!createName.trim()) return; - - setCreating(true); - try { - // Create a basic filter with wildcards (match everything by default) - const defaultFilterData = { - query: "", - filters: { - data_sources: ["*"], - document_types: ["*"], - owners: ["*"], - }, - limit: 10, - scoreThreshold: 0, - }; - - const response = await fetch("/api/knowledge-filter", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - name: createName.trim(), - description: createDescription.trim(), - queryData: JSON.stringify(defaultFilterData), - }), - }); - - const result = await response.json(); - if (response.ok && result.success) { - // Create the new filter object - const newFilter: KnowledgeFilter = { - id: result.filter.id, - name: createName.trim(), - description: createDescription.trim(), - query_data: JSON.stringify(defaultFilterData), - owner: result.filter.owner, - created_at: result.filter.created_at, - updated_at: result.filter.updated_at, - }; - - // Add to local filters list - setFilters((prev) => [newFilter, ...prev]); - - // Select the new filter - onFilterSelect(newFilter); - - // Close modal and reset form - setShowCreateModal(false); - setCreateName(""); - setCreateDescription(""); - } else { - console.error("Failed to create knowledge filter:", result.error); - } - } catch (error) { - console.error("Error creating knowledge filter:", error); - } finally { - setCreating(false); - } - }; - - const handleCancelCreate = () => { - setShowCreateModal(false); - setCreateName(""); - setCreateDescription(""); - }; - - const getFilterSummary = (filter: KnowledgeFilter): string => { - try { - const parsed = JSON.parse(filter.query_data) as ParsedQueryData; - const parts = []; - - if (parsed.query) parts.push(`"${parsed.query}"`); - if (parsed.filters.data_sources.length > 0) - parts.push(`${parsed.filters.data_sources.length} sources`); - if (parsed.filters.document_types.length > 0) - parts.push(`${parsed.filters.document_types.length} types`); - if (parsed.filters.owners.length > 0) - parts.push(`${parsed.filters.owners.length} owners`); - - return parts.join(" • ") || "No filters"; - } catch { - return "Invalid filter"; - } - }; - - useEffect(() => { - if (isOpen) { - loadFilters(); - } - }, [isOpen]); - - useEffect(() => { - const timeoutId = setTimeout(() => { - if (isOpen) { - loadFilters(searchQuery); - } - }, 300); - - return () => clearTimeout(timeoutId); - }, [searchQuery, isOpen]); - - // Close dropdown when clicking outside - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - dropdownRef.current && - !dropdownRef.current.contains(event.target as Node) - ) { - setIsOpen(false); - } - }; - - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, []); - - return ( -
- - - {isOpen && ( - - - {/* Search Header */} -
-
- - setSearchQuery(e.target.value)} - className="pl-9 h-8 text-sm" - /> -
-
- - {/* Filter List */} -
- {/* Clear filter option */} -
-
- -
-
All Knowledge
-
- No filters applied -
-
-
-
- - {loading ? ( -
- - - Loading... - -
- ) : filters.length === 0 ? ( -
- {searchQuery ? "No filters found" : "No saved filters"} -
- ) : ( - filters.map((filter) => ( -
handleFilterSelect(filter)} - className={cn( - "flex items-center gap-3 p-3 hover:bg-accent hover:text-accent-foreground cursor-pointer group transition-colors", - selectedFilter?.id === filter.id && - "bg-accent text-accent-foreground", - )} - > -
- -
-
- {filter.name} -
-
- {getFilterSummary(filter)} -
-
-
- -
- )) - )} -
- - {/* Create New Filter Option */} -
-
- -
-
- Create New Filter -
-
- Save current search as filter -
-
-
-
- - {/* Selected Filter Details */} - {selectedFilter && ( -
-
- Selected: {selectedFilter.name} -
- {selectedFilter.description && ( -
- {selectedFilter.description} -
- )} -
- )} -
-
- )} - - {/* Create Filter Modal */} - {showCreateModal && ( -
-
-

- Create New Knowledge Filter -

- -
-
- - setCreateName(e.target.value)} - className="mt-1" - /> -
- -
- -