"use client"; import { format } from "date-fns"; import { GithubIcon, PlusIcon, Trash2Icon } from "lucide-react"; import { useState } from "react"; import { deleteIntegration, testIntegrationConnection, updateIntegration, } from "@/actions/integrations"; import { IntegrationActionButtons, IntegrationCardHeader, IntegrationSkeleton, } from "@/components/integrations/shared"; import { Button } from "@/components/shadcn"; import { useToast } from "@/components/ui"; import { CustomAlertModal } from "@/components/ui/custom"; import { DataTablePagination } from "@/components/ui/table/data-table-pagination"; import { triggerTestConnectionWithDelay } from "@/lib/integrations/test-connection-helper"; import { MetaDataProps } from "@/types"; import { IntegrationProps } from "@/types/integrations"; import { Card, CardContent, CardHeader } from "../../shadcn"; import { GitHubIntegrationForm } from "./github-integration-form"; interface GitHubIntegrationsManagerProps { integrations: IntegrationProps[]; metadata?: MetaDataProps; } export const GitHubIntegrationsManager = ({ integrations, metadata, }: GitHubIntegrationsManagerProps) => { const [isModalOpen, setIsModalOpen] = useState(false); const [editingIntegration, setEditingIntegration] = useState(null); const [isDeleting, setIsDeleting] = useState(null); const [isTesting, setIsTesting] = useState(null); const [isOperationLoading, setIsOperationLoading] = useState(false); const [isDeleteOpen, setIsDeleteOpen] = useState(false); const [integrationToDelete, setIntegrationToDelete] = useState(null); const { toast } = useToast(); const handleAddIntegration = () => { setEditingIntegration(null); setIsModalOpen(true); }; const handleEditCredentials = (integration: IntegrationProps) => { setEditingIntegration(integration); setIsModalOpen(true); }; const handleOpenDeleteModal = (integration: IntegrationProps) => { setIntegrationToDelete(integration); setIsDeleteOpen(true); }; const handleDeleteIntegration = async (id: string) => { setIsDeleting(id); try { const result = await deleteIntegration(id, "github"); if (result.success) { toast({ title: "Success!", description: "GitHub integration deleted successfully.", }); } else if (result.error) { toast({ variant: "destructive", title: "Delete Failed", description: result.error, }); } } catch (error) { toast({ variant: "destructive", title: "Error", description: "Failed to delete GitHub integration. Please try again.", }); } finally { setIsDeleting(null); setIsDeleteOpen(false); setIntegrationToDelete(null); } }; const handleTestConnection = async (id: string) => { setIsTesting(id); try { const result = await testIntegrationConnection(id); if (result.success) { toast({ title: "Connection test successful!", description: result.message || "Connection test completed successfully.", }); } else if (result.error) { toast({ variant: "destructive", title: "Connection test failed", description: result.error, }); } } catch (error) { toast({ variant: "destructive", title: "Error", description: "Failed to test connection. Please try again.", }); } finally { setIsTesting(null); } }; const handleToggleEnabled = async (integration: IntegrationProps) => { try { const newEnabledState = !integration.attributes.enabled; const formData = new FormData(); formData.append( "integration_type", integration.attributes.integration_type, ); formData.append("enabled", JSON.stringify(newEnabledState)); const result = await updateIntegration(integration.id, formData); if (result && "success" in result) { toast({ title: "Success!", description: `Integration ${newEnabledState ? "enabled" : "disabled"} successfully.`, }); // If enabling, trigger test connection automatically if (newEnabledState) { setIsTesting(integration.id); triggerTestConnectionWithDelay( integration.id, true, "github", toast, 500, () => { setIsTesting(null); }, ); } } else if (result && "error" in result) { toast({ variant: "destructive", title: "Toggle Failed", description: result.error, }); } } catch (error) { toast({ variant: "destructive", title: "Error", description: "Failed to toggle integration. Please try again.", }); } }; const handleModalClose = () => { setIsModalOpen(false); setEditingIntegration(null); }; const handleFormSuccess = async ( integrationId?: string, shouldTestConnection?: boolean, ) => { // Close the modal immediately setIsModalOpen(false); setEditingIntegration(null); setIsOperationLoading(true); // Set testing state for server-triggered test connections if (integrationId && shouldTestConnection) { setIsTesting(integrationId); } // Trigger test connection if needed triggerTestConnectionWithDelay( integrationId, shouldTestConnection, "github", toast, 200, () => { // Clear testing state when server-triggered test completes setIsTesting(null); }, ); // Reset loading state after a short delay to show the skeleton briefly setTimeout(() => { setIsOperationLoading(false); }, 1500); }; return ( <>

GitHub Integrations

Manage your GitHub integrations to send findings as issues

{isOperationLoading && } {!isOperationLoading && integrations.length === 0 && (

No GitHub integrations configured

Get started by adding your first GitHub integration

)} {!isOperationLoading && integrations.map((integration) => ( } title="GitHub Integration" subtitle={ integration.attributes.configuration.owner ? `Owner: ${integration.attributes.configuration.owner}` : "All accessible repositories" } integrationId={integration.id} enabled={integration.attributes.enabled} connected={integration.attributes.connected} lastChecked={integration.attributes.connection_last_checked_at} isTesting={isTesting === integration.id} />
{integration.attributes.configuration.repositories && Object.keys( integration.attributes.configuration.repositories, ).length > 0 && (

Accessible Repositories:{" "} { Object.keys( integration.attributes.configuration.repositories, ).length }

Last synced:{" "} {integration.attributes.connection_last_checked_at ? format( new Date( integration.attributes.connection_last_checked_at, ), "PPpp", ) : "Never"}

)}
))}
{metadata && integrations.length > 0 && !isOperationLoading && ( )}
); };