mirror of
https://github.com/MODSetter/SurfSense.git
synced 2025-09-02 18:49:09 +00:00
Biome: fixes for app/dashboard/search_pace_id pages
This commit is contained in:
parent
07063a1a18
commit
ecc4c11100
22 changed files with 472 additions and 480 deletions
|
@ -1,25 +1,23 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { format } from "date-fns";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { AnimatePresence, motion, type Variants } from "framer-motion";
|
||||||
import { useSearchParams } from "next/navigation";
|
|
||||||
import {
|
import {
|
||||||
MessageCircleMore,
|
|
||||||
Search,
|
|
||||||
Calendar,
|
Calendar,
|
||||||
Tag,
|
|
||||||
Trash2,
|
|
||||||
ExternalLink,
|
|
||||||
MoreHorizontal,
|
|
||||||
Radio,
|
|
||||||
CheckCircle,
|
CheckCircle,
|
||||||
Circle,
|
Circle,
|
||||||
|
ExternalLink,
|
||||||
|
MessageCircleMore,
|
||||||
|
MoreHorizontal,
|
||||||
Podcast,
|
Podcast,
|
||||||
|
Search,
|
||||||
|
Tag,
|
||||||
|
Trash2,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { format } from "date-fns";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
// UI Components
|
import { toast } from "sonner";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
@ -29,22 +27,6 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
} from "@/components/ui/dropdown-menu";
|
|
||||||
import {
|
|
||||||
Pagination,
|
|
||||||
PaginationContent,
|
|
||||||
PaginationItem,
|
|
||||||
PaginationLink,
|
|
||||||
PaginationNext,
|
|
||||||
PaginationPrevious,
|
|
||||||
} from "@/components/ui/pagination";
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
@ -53,6 +35,24 @@ import {
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
// UI Components
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Pagination,
|
||||||
|
PaginationContent,
|
||||||
|
PaginationItem,
|
||||||
|
PaginationLink,
|
||||||
|
PaginationNext,
|
||||||
|
PaginationPrevious,
|
||||||
|
} from "@/components/ui/pagination";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
@ -61,9 +61,6 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
interface Chat {
|
interface Chat {
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
@ -86,13 +83,13 @@ interface ChatsPageClientProps {
|
||||||
searchSpaceId: string;
|
searchSpaceId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageVariants = {
|
const pageVariants: Variants = {
|
||||||
initial: { opacity: 0 },
|
initial: { opacity: 0 },
|
||||||
enter: { opacity: 1, transition: { duration: 0.3, ease: "easeInOut" } },
|
enter: { opacity: 1, transition: { duration: 0.3, ease: "easeInOut" } },
|
||||||
exit: { opacity: 0, transition: { duration: 0.3, ease: "easeInOut" } },
|
exit: { opacity: 0, transition: { duration: 0.3, ease: "easeInOut" } },
|
||||||
};
|
};
|
||||||
|
|
||||||
const chatCardVariants = {
|
const chatCardVariants: Variants = {
|
||||||
initial: { y: 20, opacity: 0 },
|
initial: { y: 20, opacity: 0 },
|
||||||
animate: { y: 0, opacity: 1 },
|
animate: { y: 0, opacity: 1 },
|
||||||
exit: { y: -20, opacity: 0 },
|
exit: { y: -20, opacity: 0 },
|
||||||
|
@ -101,6 +98,7 @@ const chatCardVariants = {
|
||||||
const MotionCard = motion(Card);
|
const MotionCard = motion(Card);
|
||||||
|
|
||||||
export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps) {
|
export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps) {
|
||||||
|
const router = useRouter();
|
||||||
const [chats, setChats] = useState<Chat[]>([]);
|
const [chats, setChats] = useState<Chat[]>([]);
|
||||||
const [filteredChats, setFilteredChats] = useState<Chat[]>([]);
|
const [filteredChats, setFilteredChats] = useState<Chat[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
@ -134,7 +132,7 @@ export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps)
|
||||||
const pageParam = searchParams.get("page");
|
const pageParam = searchParams.get("page");
|
||||||
if (pageParam) {
|
if (pageParam) {
|
||||||
const pageNumber = parseInt(pageParam, 10);
|
const pageNumber = parseInt(pageParam, 10);
|
||||||
if (!isNaN(pageNumber) && pageNumber > 0) {
|
if (!Number.isNaN(pageNumber) && pageNumber > 0) {
|
||||||
setCurrentPage(pageNumber);
|
setCurrentPage(pageNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,7 +316,7 @@ export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps)
|
||||||
throw new Error(errorData.detail || "Failed to generate podcast");
|
throw new Error(errorData.detail || "Failed to generate podcast");
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const _data = await response.json();
|
||||||
toast.success(`Podcast "${currentTitle}" generation started!`);
|
toast.success(`Podcast "${currentTitle}" generation started!`);
|
||||||
|
|
||||||
// Move to the next chat or finish
|
// Move to the next chat or finish
|
||||||
|
@ -636,7 +634,9 @@ export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps)
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
(window.location.href = `/dashboard/${chat.search_space_id}/researcher/${chat.id}`)
|
router.push(
|
||||||
|
`/dashboard/${chat.search_space_id}/researcher/${chat.id}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ExternalLink className="mr-2 h-4 w-4" />
|
<ExternalLink className="mr-2 h-4 w-4" />
|
||||||
|
@ -841,10 +841,7 @@ export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps)
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
"Create a podcast from this chat. The podcast will be available in the podcasts section once generated."
|
||||||
Create a podcast from this chat. The podcast will be available in the podcasts
|
|
||||||
section once generated.
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
|
||||||
import { ThemeTogglerComponent } from "@/components/theme/theme-toggle";
|
|
||||||
import type React from "react";
|
import type React from "react";
|
||||||
import { Separator } from "@/components/ui/separator";
|
|
||||||
import { AppSidebarProvider } from "@/components/sidebar/AppSidebarProvider";
|
import { AppSidebarProvider } from "@/components/sidebar/AppSidebarProvider";
|
||||||
|
import { ThemeTogglerComponent } from "@/components/theme/theme-toggle";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
||||||
|
|
||||||
export function DashboardClientLayout({
|
export function DashboardClientLayout({
|
||||||
children,
|
children,
|
||||||
|
|
|
@ -1,22 +1,12 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { format } from "date-fns";
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
import { Calendar as CalendarIcon, Edit, Plus, RefreshCw, Trash2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { Edit, Plus, Trash2, RefreshCw, Calendar as CalendarIcon } from "lucide-react";
|
import { getConnectorIcon } from "@/components/chat";
|
||||||
|
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table";
|
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
|
@ -28,7 +18,9 @@ import {
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/ui/alert-dialog";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
@ -36,14 +28,20 @@ import {
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { getConnectorIcon } from "@/components/chat";
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { format } from "date-fns";
|
|
||||||
|
|
||||||
// Helper function to format date with time
|
// Helper function to format date with time
|
||||||
const formatDateTime = (dateString: string | null): string => {
|
const formatDateTime = (dateString: string | null): string => {
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
import { ArrowLeft, Check, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useEffect } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { ArrowLeft, Check, Loader2, Github } from "lucide-react";
|
import { getConnectorIcon } from "@/components/chat";
|
||||||
|
import { EditConnectorLoadingSkeleton } from "@/components/editConnector/EditConnectorLoadingSkeleton";
|
||||||
import { Form } from "@/components/ui/form";
|
import { EditConnectorNameForm } from "@/components/editConnector/EditConnectorNameForm";
|
||||||
|
import { EditGitHubConnectorConfig } from "@/components/editConnector/EditGitHubConnectorConfig";
|
||||||
|
import { EditSimpleTokenForm } from "@/components/editConnector/EditSimpleTokenForm";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
@ -16,15 +19,10 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
|
import { Form } from "@/components/ui/form";
|
||||||
|
import { useConnectorEditPage } from "@/hooks/useConnectorEditPage";
|
||||||
// Import Utils, Types, Hook, and Components
|
// Import Utils, Types, Hook, and Components
|
||||||
import { getConnectorTypeDisplay } from "@/lib/connectors/utils";
|
import { getConnectorTypeDisplay } from "@/lib/connectors/utils";
|
||||||
import { useConnectorEditPage } from "@/hooks/useConnectorEditPage";
|
|
||||||
import { EditConnectorLoadingSkeleton } from "@/components/editConnector/EditConnectorLoadingSkeleton";
|
|
||||||
import { EditConnectorNameForm } from "@/components/editConnector/EditConnectorNameForm";
|
|
||||||
import { EditGitHubConnectorConfig } from "@/components/editConnector/EditGitHubConnectorConfig";
|
|
||||||
import { EditSimpleTokenForm } from "@/components/editConnector/EditSimpleTokenForm";
|
|
||||||
import { getConnectorIcon } from "@/components/chat";
|
|
||||||
|
|
||||||
export default function EditConnectorPage() {
|
export default function EditConnectorPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -58,7 +56,7 @@ export default function EditConnectorPage() {
|
||||||
|
|
||||||
// Redirect if connectorId is not a valid number after parsing
|
// Redirect if connectorId is not a valid number after parsing
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isNaN(connectorId)) {
|
if (Number.isNaN(connectorId)) {
|
||||||
toast.error("Invalid Connector ID.");
|
toast.error("Invalid Connector ID.");
|
||||||
router.push(`/dashboard/${searchSpaceId}/connectors`);
|
router.push(`/dashboard/${searchSpaceId}/connectors`);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +65,7 @@ export default function EditConnectorPage() {
|
||||||
// Loading State
|
// Loading State
|
||||||
if (connectorsLoading || !connector) {
|
if (connectorsLoading || !connector) {
|
||||||
// Handle NaN case before showing skeleton
|
// Handle NaN case before showing skeleton
|
||||||
if (isNaN(connectorId)) return null;
|
if (Number.isNaN(connectorId)) return null;
|
||||||
return <EditConnectorLoadingSkeleton />;
|
return <EditConnectorLoadingSkeleton />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import {
|
import { useEffect, useState } from "react";
|
||||||
useSearchSourceConnectors,
|
import { useForm } from "react-hook-form";
|
||||||
type SearchSourceConnector,
|
import { toast } from "sonner";
|
||||||
} from "@/hooks/useSearchSourceConnectors";
|
import * as z from "zod";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -23,9 +21,10 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
import {
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
type SearchSourceConnector,
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
useSearchSourceConnectors,
|
||||||
|
} from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const apiConnectorFormSchema = z.object({
|
const apiConnectorFormSchema = z.object({
|
||||||
|
@ -57,6 +56,20 @@ const getConnectorTypeDisplay = (type: string): string => {
|
||||||
// Define the type for the form values
|
// Define the type for the form values
|
||||||
type ApiConnectorFormValues = z.infer<typeof apiConnectorFormSchema>;
|
type ApiConnectorFormValues = z.infer<typeof apiConnectorFormSchema>;
|
||||||
|
|
||||||
|
// Get API key field name based on connector type
|
||||||
|
const getApiKeyFieldName = (connectorType: string): string => {
|
||||||
|
const fieldMap: Record<string, string> = {
|
||||||
|
SERPER_API: "SERPER_API_KEY",
|
||||||
|
TAVILY_API: "TAVILY_API_KEY",
|
||||||
|
SLACK_CONNECTOR: "SLACK_BOT_TOKEN",
|
||||||
|
NOTION_CONNECTOR: "NOTION_INTEGRATION_TOKEN",
|
||||||
|
GITHUB_CONNECTOR: "GITHUB_PAT",
|
||||||
|
DISCORD_CONNECTOR: "DISCORD_BOT_TOKEN",
|
||||||
|
LINKUP_API: "LINKUP_API_KEY",
|
||||||
|
};
|
||||||
|
return fieldMap[connectorType] || "";
|
||||||
|
};
|
||||||
|
|
||||||
export default function EditConnectorPage() {
|
export default function EditConnectorPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
@ -77,20 +90,6 @@ export default function EditConnectorPage() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get API key field name based on connector type
|
|
||||||
const getApiKeyFieldName = (connectorType: string): string => {
|
|
||||||
const fieldMap: Record<string, string> = {
|
|
||||||
SERPER_API: "SERPER_API_KEY",
|
|
||||||
TAVILY_API: "TAVILY_API_KEY",
|
|
||||||
SLACK_CONNECTOR: "SLACK_BOT_TOKEN",
|
|
||||||
NOTION_CONNECTOR: "NOTION_INTEGRATION_TOKEN",
|
|
||||||
GITHUB_CONNECTOR: "GITHUB_PAT",
|
|
||||||
DISCORD_CONNECTOR: "DISCORD_BOT_TOKEN",
|
|
||||||
LINKUP_API: "LINKUP_API_KEY",
|
|
||||||
};
|
|
||||||
return fieldMap[connectorType] || "";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find connector in the list
|
// Find connector in the list
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentConnector = connectors.find((c) => c.id === connectorId);
|
const currentConnector = connectors.find((c) => c.id === connectorId);
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,23 +34,8 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const discordConnectorFormSchema = z.object({
|
const discordConnectorFormSchema = z.object({
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { ArrowLeft, Check, CircleAlert, Github, Info, ListChecks, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { ArrowLeft, Check, Info, Loader2, Github, CircleAlert, ListChecks } from "lucide-react";
|
import * as z from "zod";
|
||||||
|
import {
|
||||||
// Assuming useSearchSourceConnectors hook exists and works similarly
|
Accordion,
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -21,24 +35,9 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
// Assuming useSearchSourceConnectors hook exists and works similarly
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod for GitHub PAT entry step
|
// Define the form schema with Zod for GitHub PAT entry step
|
||||||
const githubPatFormSchema = z.object({
|
const githubPatFormSchema = z.object({
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,23 +34,8 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const jiraConnectorFormSchema = z.object({
|
const jiraConnectorFormSchema = z.object({
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,23 +34,8 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const linearConnectorFormSchema = z.object({
|
const linearConnectorFormSchema = z.object({
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,16 +28,7 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const linkupApiFormSchema = z.object({
|
const linkupApiFormSchema = z.object({
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,23 +34,8 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const notionConnectorFormSchema = z.object({
|
const notionConnectorFormSchema = z.object({
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card";
|
|
||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
|
||||||
import {
|
import {
|
||||||
IconBrandDiscord,
|
IconBrandDiscord,
|
||||||
IconBrandGithub,
|
IconBrandGithub,
|
||||||
|
@ -12,16 +8,20 @@ import {
|
||||||
IconBrandZoom,
|
IconBrandZoom,
|
||||||
IconChevronDown,
|
IconChevronDown,
|
||||||
IconChevronRight,
|
IconChevronRight,
|
||||||
IconMail,
|
|
||||||
IconWorldWww,
|
|
||||||
IconTicket,
|
|
||||||
IconLayoutKanban,
|
IconLayoutKanban,
|
||||||
IconLinkPlus,
|
IconLinkPlus,
|
||||||
|
IconMail,
|
||||||
|
IconTicket,
|
||||||
|
IconWorldWww,
|
||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card";
|
||||||
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||||
|
|
||||||
// Define the Connector type
|
// Define the Connector type
|
||||||
interface Connector {
|
interface Connector {
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,16 +28,7 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const serperApiFormSchema = z.object({
|
const serperApiFormSchema = z.object({
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,23 +34,8 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const slackConnectorFormSchema = z.object({
|
const slackConnectorFormSchema = z.object({
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { motion } from "framer-motion";
|
||||||
import * as z from "zod";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
import { ArrowLeft, Check, Info, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import * as z from "zod";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
@ -20,16 +28,7 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { useSearchSourceConnectors } from "@/hooks/useSearchSourceConnectors";
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
|
|
||||||
// Define the form schema with Zod
|
// Define the form schema with Zod
|
||||||
const tavilyApiFormSchema = z.object({
|
const tavilyApiFormSchema = z.object({
|
||||||
|
|
|
@ -1,5 +1,57 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
IconBrandDiscord,
|
||||||
|
IconBrandGithub,
|
||||||
|
IconBrandNotion,
|
||||||
|
IconBrandSlack,
|
||||||
|
IconBrandYoutube,
|
||||||
|
IconLayoutKanban,
|
||||||
|
IconTicket,
|
||||||
|
} from "@tabler/icons-react";
|
||||||
|
import {
|
||||||
|
type ColumnDef,
|
||||||
|
type ColumnFiltersState,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFacetedUniqueValues,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
type PaginationState,
|
||||||
|
type Row,
|
||||||
|
type SortingState,
|
||||||
|
useReactTable,
|
||||||
|
type VisibilityState,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import { AnimatePresence, motion, type Variants } from "framer-motion";
|
||||||
|
import {
|
||||||
|
AlertCircle,
|
||||||
|
ChevronDown,
|
||||||
|
ChevronFirst,
|
||||||
|
ChevronLast,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
ChevronUp,
|
||||||
|
CircleAlert,
|
||||||
|
CircleX,
|
||||||
|
Columns3,
|
||||||
|
File,
|
||||||
|
FileX,
|
||||||
|
Filter,
|
||||||
|
Globe,
|
||||||
|
ListFilter,
|
||||||
|
MoreHorizontal,
|
||||||
|
Trash,
|
||||||
|
Webhook,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
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 { toast } from "sonner";
|
||||||
import { DocumentViewer } from "@/components/document-viewer";
|
import { DocumentViewer } from "@/components/document-viewer";
|
||||||
import { JsonMetadataViewer } from "@/components/json-metadata-viewer";
|
import { JsonMetadataViewer } from "@/components/json-metadata-viewer";
|
||||||
import {
|
import {
|
||||||
|
@ -43,64 +95,12 @@ import {
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import { useDocuments } from "@/hooks/use-documents";
|
import { useDocuments } from "@/hooks/use-documents";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import {
|
|
||||||
IconBrandDiscord,
|
|
||||||
IconBrandGithub,
|
|
||||||
IconBrandNotion,
|
|
||||||
IconBrandSlack,
|
|
||||||
IconBrandYoutube,
|
|
||||||
IconLayoutKanban,
|
|
||||||
IconTicket,
|
|
||||||
} from "@tabler/icons-react";
|
|
||||||
import {
|
|
||||||
type ColumnDef,
|
|
||||||
type ColumnFiltersState,
|
|
||||||
type FilterFn,
|
|
||||||
type PaginationState,
|
|
||||||
type Row,
|
|
||||||
type SortingState,
|
|
||||||
type VisibilityState,
|
|
||||||
flexRender,
|
|
||||||
getCoreRowModel,
|
|
||||||
getFacetedUniqueValues,
|
|
||||||
getFilteredRowModel,
|
|
||||||
getPaginationRowModel,
|
|
||||||
getSortedRowModel,
|
|
||||||
useReactTable,
|
|
||||||
} from "@tanstack/react-table";
|
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
|
||||||
import {
|
|
||||||
AlertCircle,
|
|
||||||
ChevronDown,
|
|
||||||
ChevronFirst,
|
|
||||||
ChevronLast,
|
|
||||||
ChevronLeft,
|
|
||||||
ChevronRight,
|
|
||||||
ChevronUp,
|
|
||||||
CircleAlert,
|
|
||||||
CircleX,
|
|
||||||
Columns3,
|
|
||||||
File,
|
|
||||||
FileX,
|
|
||||||
Filter,
|
|
||||||
Globe,
|
|
||||||
ListFilter,
|
|
||||||
MoreHorizontal,
|
|
||||||
Trash,
|
|
||||||
Webhook,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useParams } from "next/navigation";
|
|
||||||
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 { toast } from "sonner";
|
|
||||||
|
|
||||||
// Define animation variants for reuse
|
// Define animation variants for reuse
|
||||||
const fadeInScale = {
|
const fadeInScale: Variants = {
|
||||||
hidden: { opacity: 0, scale: 0.95 },
|
hidden: { opacity: 0, scale: 0.95 },
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
@ -132,19 +132,6 @@ type Document = {
|
||||||
search_space_id: number;
|
search_space_id: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Custom filter function for multi-column searching
|
|
||||||
const multiColumnFilterFn: FilterFn<Document> = (row, columnId, filterValue) => {
|
|
||||||
const searchableRowContent = `${row.original.title}`.toLowerCase();
|
|
||||||
const searchTerm = (filterValue ?? "").toLowerCase();
|
|
||||||
return searchableRowContent.includes(searchTerm);
|
|
||||||
};
|
|
||||||
|
|
||||||
const statusFilterFn: FilterFn<Document> = (row, columnId, filterValue: string[]) => {
|
|
||||||
if (!filterValue?.length) return true;
|
|
||||||
const status = row.getValue(columnId) as string;
|
|
||||||
return filterValue.includes(status);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add document type icons mapping
|
// Add document type icons mapping
|
||||||
const documentTypeIcons = {
|
const documentTypeIcons = {
|
||||||
EXTENSION: Webhook,
|
EXTENSION: Webhook,
|
||||||
|
@ -187,6 +174,8 @@ const columns: ColumnDef<Document>[] = [
|
||||||
accessorKey: "title",
|
accessorKey: "title",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const Icon = documentTypeIcons[row.original.document_type];
|
const Icon = documentTypeIcons[row.original.document_type];
|
||||||
|
const title = row.getValue("title") as string;
|
||||||
|
const truncatedTitle = title.length > 30 ? `${title.slice(0, 30)}...` : title;
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="flex items-center gap-2 font-medium"
|
className="flex items-center gap-2 font-medium"
|
||||||
|
@ -194,8 +183,17 @@ const columns: ColumnDef<Document>[] = [
|
||||||
transition={{ type: "spring", stiffness: 300 }}
|
transition={{ type: "spring", stiffness: 300 }}
|
||||||
style={{ display: "flex" }}
|
style={{ display: "flex" }}
|
||||||
>
|
>
|
||||||
<Icon size={16} className="text-muted-foreground shrink-0" />
|
<Tooltip>
|
||||||
<span>{row.getValue("title")}</span>
|
<TooltipTrigger asChild>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<Icon size={16} className="text-muted-foreground shrink-0" />
|
||||||
|
<span>{truncatedTitle}</span>
|
||||||
|
</span>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>{title}</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -231,7 +229,7 @@ const columns: ColumnDef<Document>[] = [
|
||||||
const title = row.getValue("title") as string;
|
const title = row.getValue("title") as string;
|
||||||
|
|
||||||
// Create a truncated preview (first 150 characters)
|
// Create a truncated preview (first 150 characters)
|
||||||
const previewContent = content.length > 150 ? content.substring(0, 150) + "..." : content;
|
const previewContent = content.length > 150 ? `${content.substring(0, 150)}...` : content;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
|
@ -336,7 +334,7 @@ export default function DocumentsTable() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (documents) {
|
if (documents) {
|
||||||
setData(documents);
|
setData(documents as Document[]);
|
||||||
}
|
}
|
||||||
}, [documents]);
|
}, [documents]);
|
||||||
|
|
||||||
|
@ -408,19 +406,19 @@ export default function DocumentsTable() {
|
||||||
const values = Array.from(statusColumn.getFacetedUniqueValues().keys());
|
const values = Array.from(statusColumn.getFacetedUniqueValues().keys());
|
||||||
|
|
||||||
return values.sort();
|
return values.sort();
|
||||||
}, [table.getColumn("document_type")?.getFacetedUniqueValues()]);
|
}, [table.getColumn]);
|
||||||
|
|
||||||
// Get counts for each status
|
// Get counts for each status
|
||||||
const statusCounts = useMemo(() => {
|
const statusCounts = useMemo(() => {
|
||||||
const statusColumn = table.getColumn("document_type");
|
const statusColumn = table.getColumn("document_type");
|
||||||
if (!statusColumn) return new Map();
|
if (!statusColumn) return new Map();
|
||||||
return statusColumn.getFacetedUniqueValues();
|
return statusColumn.getFacetedUniqueValues();
|
||||||
}, [table.getColumn("document_type")?.getFacetedUniqueValues()]);
|
}, [table.getColumn]);
|
||||||
|
|
||||||
const selectedStatuses = useMemo(() => {
|
const selectedStatuses = useMemo(() => {
|
||||||
const filterValue = table.getColumn("document_type")?.getFilterValue() as string[];
|
const filterValue = table.getColumn("document_type")?.getFilterValue() as string[];
|
||||||
return filterValue ?? [];
|
return filterValue ?? [];
|
||||||
}, [table.getColumn("document_type")?.getFilterValue()]);
|
}, [table.getColumn]);
|
||||||
|
|
||||||
const handleStatusChange = (checked: boolean, value: string) => {
|
const handleStatusChange = (checked: boolean, value: string) => {
|
||||||
const filterValue = table.getColumn("document_type")?.getFilterValue() as string[];
|
const filterValue = table.getColumn("document_type")?.getFilterValue() as string[];
|
||||||
|
@ -722,7 +720,8 @@ export default function DocumentsTable() {
|
||||||
className="h-12 px-4 py-3"
|
className="h-12 px-4 py-3"
|
||||||
>
|
>
|
||||||
{header.isPlaceholder ? null : header.column.getCanSort() ? (
|
{header.isPlaceholder ? null : header.column.getCanSort() ? (
|
||||||
<div
|
<Button
|
||||||
|
variant="ghost"
|
||||||
className={cn(
|
className={cn(
|
||||||
header.column.getCanSort() &&
|
header.column.getCanSort() &&
|
||||||
"flex h-full cursor-pointer select-none items-center justify-between gap-2"
|
"flex h-full cursor-pointer select-none items-center justify-between gap-2"
|
||||||
|
@ -759,7 +758,7 @@ export default function DocumentsTable() {
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
}[header.column.getIsSorted() as string] ?? null}
|
}[header.column.getIsSorted() as string] ?? null}
|
||||||
</div>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
flexRender(header.column.columnDef.header, header.getContext())
|
flexRender(header.column.columnDef.header, header.getContext())
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback, useRef } from "react";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
|
import { Calendar, CheckCircle2, FileType, Tag, Upload, X } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useCallback, useRef, useState } from "react";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { X, Upload, Tag, CheckCircle2, Calendar, FileType } from "lucide-react";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useRouter, useParams } from "next/navigation";
|
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
|
||||||
|
|
||||||
// Grid pattern component inspired by Aceternity UI
|
// Grid pattern component inspired by Aceternity UI
|
||||||
function GridPattern() {
|
function GridPattern() {
|
||||||
|
@ -230,7 +230,7 @@ export default function FileUploader() {
|
||||||
const k = 1024;
|
const k = 1024;
|
||||||
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
return parseFloat((bytes / k ** i).toFixed(2)) + " " + sizes[i];
|
return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpload = async () => {
|
const handleUpload = async () => {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useParams, useRouter } from "next/navigation";
|
|
||||||
import { type Tag, TagInput } from "emblor";
|
import { type Tag, TagInput } from "emblor";
|
||||||
|
import { Globe, Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
|
@ -13,8 +14,7 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { toast } from "sonner";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Globe, Loader2 } from "lucide-react";
|
|
||||||
|
|
||||||
// URL validation regex
|
// URL validation regex
|
||||||
const urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
|
const urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { IconBrandYoutube } from "@tabler/icons-react";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
|
||||||
import { type Tag, TagInput } from "emblor";
|
import { type Tag, TagInput } from "emblor";
|
||||||
|
import { motion, type Variants } from "framer-motion";
|
||||||
|
import { Loader2 } from "lucide-react";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
|
@ -13,9 +16,7 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { toast } from "sonner";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Youtube, Loader2 } from "lucide-react";
|
|
||||||
import { motion } from "framer-motion";
|
|
||||||
|
|
||||||
// YouTube video ID validation regex
|
// YouTube video ID validation regex
|
||||||
const youtubeRegex =
|
const youtubeRegex =
|
||||||
|
@ -135,7 +136,7 @@ export default function YouTubeVideoAdder() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Animation variants
|
// Animation variants
|
||||||
const containerVariants = {
|
const containerVariants: Variants = {
|
||||||
hidden: { opacity: 0 },
|
hidden: { opacity: 0 },
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
@ -145,7 +146,7 @@ export default function YouTubeVideoAdder() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const itemVariants = {
|
const itemVariants: Variants = {
|
||||||
hidden: { y: 20, opacity: 0 },
|
hidden: { y: 20, opacity: 0 },
|
||||||
visible: {
|
visible: {
|
||||||
y: 0,
|
y: 0,
|
||||||
|
@ -165,7 +166,7 @@ export default function YouTubeVideoAdder() {
|
||||||
<motion.div variants={itemVariants}>
|
<motion.div variants={itemVariants}>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="flex items-center gap-2">
|
<CardTitle className="flex items-center gap-2">
|
||||||
<Youtube className="h-5 w-5" />
|
<IconBrandYoutube className="h-5 w-5" />
|
||||||
Add YouTube Videos
|
Add YouTube Videos
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
|
@ -282,7 +283,7 @@ export default function YouTubeVideoAdder() {
|
||||||
transition={{ delay: 0.2 }}
|
transition={{ delay: 0.2 }}
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
>
|
>
|
||||||
<Youtube className="h-4 w-4" />
|
<IconBrandYoutube className="h-4 w-4" />
|
||||||
</motion.span>
|
</motion.span>
|
||||||
Submit YouTube Videos
|
Submit YouTube Videos
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,5 +1,51 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
type ColumnDef,
|
||||||
|
type ColumnFiltersState,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFacetedUniqueValues,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
type PaginationState,
|
||||||
|
type Row,
|
||||||
|
type SortingState,
|
||||||
|
useReactTable,
|
||||||
|
type VisibilityState,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import { AnimatePresence, motion, type Variants } from "framer-motion";
|
||||||
|
import {
|
||||||
|
Activity,
|
||||||
|
AlertCircle,
|
||||||
|
AlertTriangle,
|
||||||
|
Bug,
|
||||||
|
CheckCircle2,
|
||||||
|
ChevronDown,
|
||||||
|
ChevronFirst,
|
||||||
|
ChevronLast,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
ChevronUp,
|
||||||
|
CircleAlert,
|
||||||
|
CircleX,
|
||||||
|
Clock,
|
||||||
|
Columns3,
|
||||||
|
Filter,
|
||||||
|
Info,
|
||||||
|
ListFilter,
|
||||||
|
MoreHorizontal,
|
||||||
|
RefreshCw,
|
||||||
|
Terminal,
|
||||||
|
Trash,
|
||||||
|
X,
|
||||||
|
Zap,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import React, { useContext, useId, useMemo, useRef, useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { JsonMetadataViewer } from "@/components/json-metadata-viewer";
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
|
@ -12,7 +58,7 @@ import {
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/ui/alert-dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
|
@ -42,57 +88,11 @@ import {
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { JsonMetadataViewer } from "@/components/json-metadata-viewer";
|
import { type Log, type LogLevel, type LogStatus, useLogs, useLogsSummary } from "@/hooks/use-logs";
|
||||||
import { useLogs, useLogsSummary, type Log, type LogLevel, type LogStatus } from "@/hooks/use-logs";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import {
|
|
||||||
type ColumnDef,
|
|
||||||
type ColumnFiltersState,
|
|
||||||
type PaginationState,
|
|
||||||
type Row,
|
|
||||||
type SortingState,
|
|
||||||
type VisibilityState,
|
|
||||||
flexRender,
|
|
||||||
getCoreRowModel,
|
|
||||||
getFacetedUniqueValues,
|
|
||||||
getFilteredRowModel,
|
|
||||||
getPaginationRowModel,
|
|
||||||
getSortedRowModel,
|
|
||||||
useReactTable,
|
|
||||||
} from "@tanstack/react-table";
|
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
|
||||||
import {
|
|
||||||
Activity,
|
|
||||||
AlertCircle,
|
|
||||||
AlertTriangle,
|
|
||||||
Bug,
|
|
||||||
CheckCircle2,
|
|
||||||
ChevronDown,
|
|
||||||
ChevronFirst,
|
|
||||||
ChevronLast,
|
|
||||||
ChevronLeft,
|
|
||||||
ChevronRight,
|
|
||||||
ChevronUp,
|
|
||||||
CircleAlert,
|
|
||||||
CircleX,
|
|
||||||
Clock,
|
|
||||||
Columns3,
|
|
||||||
Filter,
|
|
||||||
Info,
|
|
||||||
ListFilter,
|
|
||||||
MoreHorizontal,
|
|
||||||
RefreshCw,
|
|
||||||
Terminal,
|
|
||||||
Trash,
|
|
||||||
X,
|
|
||||||
Zap,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useParams } from "next/navigation";
|
|
||||||
import React, { useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
// Define animation variants for reuse
|
// Define animation variants for reuse
|
||||||
const fadeInScale = {
|
const fadeInScale: Variants = {
|
||||||
hidden: { opacity: 0, scale: 0.95 },
|
hidden: { opacity: 0, scale: 0.95 },
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
@ -324,13 +324,13 @@ export default function LogsManagePage() {
|
||||||
const levelColumn = table.getColumn("level");
|
const levelColumn = table.getColumn("level");
|
||||||
if (!levelColumn) return [];
|
if (!levelColumn) return [];
|
||||||
return Array.from(levelColumn.getFacetedUniqueValues().keys()).sort();
|
return Array.from(levelColumn.getFacetedUniqueValues().keys()).sort();
|
||||||
}, [table.getColumn("level")?.getFacetedUniqueValues()]);
|
}, [table.getColumn]);
|
||||||
|
|
||||||
const uniqueStatuses = useMemo(() => {
|
const uniqueStatuses = useMemo(() => {
|
||||||
const statusColumn = table.getColumn("status");
|
const statusColumn = table.getColumn("status");
|
||||||
if (!statusColumn) return [];
|
if (!statusColumn) return [];
|
||||||
return Array.from(statusColumn.getFacetedUniqueValues().keys()).sort();
|
return Array.from(statusColumn.getFacetedUniqueValues().keys()).sort();
|
||||||
}, [table.getColumn("status")?.getFacetedUniqueValues()]);
|
}, [table.getColumn]);
|
||||||
|
|
||||||
const handleDeleteRows = async () => {
|
const handleDeleteRows = async () => {
|
||||||
const selectedRows = table.getSelectedRowModel().rows;
|
const selectedRows = table.getSelectedRowModel().rows;
|
||||||
|
@ -631,15 +631,17 @@ function LogsFilters({
|
||||||
<ListFilter size={16} strokeWidth={2} />
|
<ListFilter size={16} strokeWidth={2} />
|
||||||
</div>
|
</div>
|
||||||
{Boolean(table.getColumn("message")?.getFilterValue()) && (
|
{Boolean(table.getColumn("message")?.getFilterValue()) && (
|
||||||
<button
|
<Button
|
||||||
className="absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-lg text-muted-foreground/80 hover:text-foreground"
|
className="absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-lg text-muted-foreground/80 hover:text-foreground"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
table.getColumn("message")?.setFilterValue("");
|
table.getColumn("message")?.setFilterValue("");
|
||||||
inputRef.current?.focus();
|
inputRef.current?.focus();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CircleX size={16} strokeWidth={2} />
|
<CircleX size={16} strokeWidth={2} />
|
||||||
</button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
@ -705,7 +707,7 @@ function FilterDropdown({
|
||||||
const selectedValues = useMemo(() => {
|
const selectedValues = useMemo(() => {
|
||||||
const filterValue = column?.getFilterValue() as string[];
|
const filterValue = column?.getFilterValue() as string[];
|
||||||
return filterValue ?? [];
|
return filterValue ?? [];
|
||||||
}, [column?.getFilterValue()]);
|
}, [column?.getFilterValue]);
|
||||||
|
|
||||||
const handleValueChange = (checked: boolean, value: string) => {
|
const handleValueChange = (checked: boolean, value: string) => {
|
||||||
const filterValue = column?.getFilterValue() as string[];
|
const filterValue = column?.getFilterValue() as string[];
|
||||||
|
@ -848,7 +850,9 @@ function LogsTable({
|
||||||
className="h-12 px-4 py-3"
|
className="h-12 px-4 py-3"
|
||||||
>
|
>
|
||||||
{header.isPlaceholder ? null : header.column.getCanSort() ? (
|
{header.isPlaceholder ? null : header.column.getCanSort() ? (
|
||||||
<div
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full cursor-pointer select-none items-center justify-between gap-2"
|
"flex h-full cursor-pointer select-none items-center justify-between gap-2"
|
||||||
)}
|
)}
|
||||||
|
@ -859,7 +863,7 @@ function LogsTable({
|
||||||
asc: <ChevronUp className="shrink-0 opacity-60" size={16} />,
|
asc: <ChevronUp className="shrink-0 opacity-60" size={16} />,
|
||||||
desc: <ChevronDown className="shrink-0 opacity-60" size={16} />,
|
desc: <ChevronDown className="shrink-0 opacity-60" size={16} />,
|
||||||
}[header.column.getIsSorted() as string] ?? null}
|
}[header.column.getIsSorted() as string] ?? null}
|
||||||
</div>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
flexRender(header.column.columnDef.header, header.getContext())
|
flexRender(header.column.columnDef.header, header.getContext())
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion, type Variants } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
Calendar,
|
Calendar,
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
|
@ -16,8 +16,9 @@ import {
|
||||||
VolumeX,
|
VolumeX,
|
||||||
X,
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import Image from "next/image";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
// UI Components
|
// UI Components
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
|
@ -45,7 +46,6 @@ import {
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Slider } from "@/components/ui/slider";
|
import { Slider } from "@/components/ui/slider";
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
interface PodcastItem {
|
interface PodcastItem {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -60,7 +60,7 @@ interface PodcastsPageClientProps {
|
||||||
searchSpaceId: string;
|
searchSpaceId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageVariants = {
|
const pageVariants: Variants = {
|
||||||
initial: { opacity: 0 },
|
initial: { opacity: 0 },
|
||||||
enter: {
|
enter: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
@ -69,7 +69,7 @@ const pageVariants = {
|
||||||
exit: { opacity: 0, transition: { duration: 0.3, ease: "easeInOut" } },
|
exit: { opacity: 0, transition: { duration: 0.3, ease: "easeInOut" } },
|
||||||
};
|
};
|
||||||
|
|
||||||
const podcastCardVariants = {
|
const podcastCardVariants: Variants = {
|
||||||
initial: { scale: 0.95, y: 20, opacity: 0 },
|
initial: { scale: 0.95, y: 20, opacity: 0 },
|
||||||
animate: {
|
animate: {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
|
@ -162,7 +162,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchPodcasts();
|
fetchPodcasts();
|
||||||
}, [searchSpaceId]);
|
}, []);
|
||||||
|
|
||||||
// Filter and sort podcasts based on search query and sort order
|
// Filter and sort podcasts based on search query and sort order
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -540,11 +540,13 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient
|
||||||
>
|
>
|
||||||
<div className="relative w-full aspect-[16/10] mb-4 rounded-lg overflow-hidden">
|
<div className="relative w-full aspect-[16/10] mb-4 rounded-lg overflow-hidden">
|
||||||
{/* Podcast image with gradient overlay */}
|
{/* Podcast image with gradient overlay */}
|
||||||
<img
|
<Image
|
||||||
src={PODCAST_IMAGE_URL}
|
src={PODCAST_IMAGE_URL}
|
||||||
alt="Podcast illustration"
|
alt="Podcast illustration"
|
||||||
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105 brightness-[0.85] contrast-[1.1]"
|
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105 brightness-[0.85] contrast-[1.1]"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Better overlay with gradient for improved text legibility */}
|
{/* Better overlay with gradient for improved text legibility */}
|
||||||
|
@ -675,7 +677,8 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ delay: 0.1 }}
|
transition={{ delay: 0.1 }}
|
||||||
>
|
>
|
||||||
<div
|
<Button
|
||||||
|
variant="ghost"
|
||||||
className="h-1.5 bg-muted rounded-full cursor-pointer group relative overflow-hidden"
|
className="h-1.5 bg-muted rounded-full cursor-pointer group relative overflow-hidden"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -702,7 +705,7 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient
|
||||||
whileHover={{ scale: 1.5 }}
|
whileHover={{ scale: 1.5 }}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</Button>
|
||||||
<div className="flex justify-between mt-1.5 text-xs text-muted-foreground">
|
<div className="flex justify-between mt-1.5 text-xs text-muted-foreground">
|
||||||
<span>{formatTime(currentTime)}</span>
|
<span>{formatTime(currentTime)}</span>
|
||||||
<span>{formatTime(duration)}</span>
|
<span>{formatTime(duration)}</span>
|
||||||
|
@ -1024,7 +1027,9 @@ export default function PodcastsPageClient({ searchSpaceId }: PodcastsPageClient
|
||||||
// Reset playing state on error
|
// Reset playing state on error
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
<track kind="captions" />
|
||||||
|
</audio>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,14 +229,14 @@ export function DocumentsDataTable({
|
||||||
if (hasChanges && Object.keys(initialRowSelection).length > 0) {
|
if (hasChanges && Object.keys(initialRowSelection).length > 0) {
|
||||||
setRowSelection(initialRowSelection);
|
setRowSelection(initialRowSelection);
|
||||||
}
|
}
|
||||||
}, [initialRowSelection, rowSelection]);
|
}, [initialRowSelection]);
|
||||||
|
|
||||||
// Initialize row selection on mount
|
// Initialize row selection on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Object.keys(rowSelection).length === 0 && Object.keys(initialRowSelection).length > 0) {
|
if (Object.keys(rowSelection).length === 0 && Object.keys(initialRowSelection).length > 0) {
|
||||||
setRowSelection(initialRowSelection);
|
setRowSelection(initialRowSelection);
|
||||||
}
|
}
|
||||||
}, [initialRowSelection, rowSelection]);
|
}, []);
|
||||||
|
|
||||||
const filteredDocuments = useMemo(() => {
|
const filteredDocuments = useMemo(() => {
|
||||||
if (documentTypeFilter === "ALL") return documents;
|
if (documentTypeFilter === "ALL") return documents;
|
||||||
|
@ -263,7 +263,7 @@ export function DocumentsDataTable({
|
||||||
const selectedRows = table.getFilteredSelectedRowModel().rows;
|
const selectedRows = table.getFilteredSelectedRowModel().rows;
|
||||||
const selectedDocuments = selectedRows.map((row) => row.original);
|
const selectedDocuments = selectedRows.map((row) => row.original);
|
||||||
onSelectionChange(selectedDocuments);
|
onSelectionChange(selectedDocuments);
|
||||||
}, [onSelectionChange, table]);
|
}, [rowSelection, onSelectionChange, table]);
|
||||||
|
|
||||||
const handleClearAll = () => setRowSelection({});
|
const handleClearAll = () => setRowSelection({});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue