import React, { useMemo } from "react"; import { json, type LoaderFunctionArgs, type ActionFunctionArgs, } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { requireUserId, requireWorkpace } from "~/services/session.server"; import { getIntegrationDefinitions } from "~/services/integrationDefinition.server"; import { getIntegrationAccounts } from "~/services/integrationAccount.server"; import { getIcon, type IconType } from "~/components/icon-utils"; import { Checkbox } from "~/components/ui/checkbox"; import { MCPAuthSection } from "~/components/integrations/mcp-auth-section"; import { ConnectedAccountSection } from "~/components/integrations/connected-account-section"; import { IngestionRuleSection } from "~/components/integrations/ingestion-rule-section"; import { ApiKeyAuthSection } from "~/components/integrations/api-key-auth-section"; import { OAuthAuthSection } from "~/components/integrations/oauth-auth-section"; import { getIngestionRuleBySource, upsertIngestionRule, } from "~/services/ingestionRule.server"; import { Section } from "~/components/integrations/section"; import { PageHeader } from "~/components/common/page-header"; import { Plus } from "lucide-react"; export async function loader({ request, params }: LoaderFunctionArgs) { const userId = await requireUserId(request); const workspace = await requireWorkpace(request); const { slug } = params; const [integrationDefinitions, integrationAccounts] = await Promise.all([ getIntegrationDefinitions(workspace.id), getIntegrationAccounts(userId), ]); const integration = integrationDefinitions.find( (def) => def.slug === slug || def.id === slug, ); if (!integration) { throw new Response("Integration not found", { status: 404 }); } const activeAccount = integrationAccounts.find( (acc) => acc.integrationDefinitionId === integration.id && acc.isActive, ); let ingestionRule = null; if (activeAccount) { ingestionRule = await getIngestionRuleBySource( activeAccount.id, workspace.id, ); } return json({ integration, integrationAccounts, userId, ingestionRule, }); } export async function action({ request, params }: ActionFunctionArgs) { const userId = await requireUserId(request); const workspace = await requireWorkpace(request); const { slug } = params; const formData = await request.formData(); const ingestionRuleText = formData.get("ingestionRule") as string; if (!ingestionRuleText) { return json({ error: "Ingestion rule is required" }, { status: 400 }); } const [integrationDefinitions, integrationAccounts] = await Promise.all([ getIntegrationDefinitions(workspace.id), getIntegrationAccounts(userId), ]); const integration = integrationDefinitions.find( (def) => def.slug === slug || def.id === slug, ); if (!integration) { throw new Response("Integration not found", { status: 404 }); } const activeAccount = integrationAccounts.find( (acc) => acc.integrationDefinitionId === integration.id && acc.isActive, ); if (!activeAccount) { return json( { error: "No active integration account found" }, { status: 400 }, ); } await upsertIngestionRule({ text: ingestionRuleText, source: activeAccount.id, workspaceId: workspace.id, userId, }); return json({ success: true }); } function parseSpec(spec: any) { if (!spec) return {}; if (typeof spec === "string") { try { return JSON.parse(spec); } catch { return {}; } } return spec; } export default function IntegrationDetail() { const { integration, integrationAccounts, ingestionRule } = useLoaderData(); const activeAccount = useMemo( () => integrationAccounts.find( (acc) => acc.integrationDefinitionId === integration.id && acc.isActive, ), [integrationAccounts, integration.id], ); const specData = useMemo( () => parseSpec(integration.spec), [integration.spec], ); const hasApiKey = !!specData?.auth?.api_key; const hasOAuth2 = !!specData?.auth?.OAuth2; const hasMCPAuth = !!specData?.mcpAuth; const Component = getIcon(integration.icon as IconType); return (
, onClick: () => window.open( "https://github.com/redplanethq/core/issues/new", "_blank", ), variant: "secondary", }, ]} />
} >
{/* Authentication Methods */}

Authentication Methods

{hasApiKey && (
API Key authentication
)} {hasOAuth2 && (
OAuth 2.0 authentication
)} {!hasApiKey && !hasOAuth2 && !hasMCPAuth && (
No authentication method specified
)}
{/* Connect Section */} {!activeAccount && (hasApiKey || hasOAuth2) && (

Connect to {integration.name}

{/* API Key Authentication */} {/* OAuth Authentication */}
)} {/* Connected Account Info */} {/* MCP Authentication Section */} {/* Ingestion Rule Section */}
); }