| 1 | import { redirect } from "react-router"; |
| 2 | |
| 3 | import { type Provider, PROVIDERS } from "@g1t/contracts"; |
| 4 | import { connectorsFor } from "@g1t/contracts/connectors"; |
| 5 | |
| 6 | import type { Route } from "./+types/integrations-directory"; |
| 7 | import { ConnectorDirectory, ScopeNote } from "../../components/connectors"; |
| 8 | import { connectedStates } from "../../lib/connected.server"; |
| 9 | import { integrationsSection } from "../../lib/integration-sections"; |
| 10 | import { page } from "../../lib/meta"; |
| 11 | import { requireUser, roleIn } from "../../lib/session.server"; |
| 12 | |
| 13 | export function meta({ params, ...args }: Route.MetaArgs) { |
| 14 | return page(args, { title: `Integrations · ${params.owner} · g1t` }); |
| 15 | } |
| 16 | |
| 17 | /** |
| 18 | * The workspace's integrations: every connector g1t has or will have, by |
| 19 | * category, with what this workspace has connected first. Each one is set |
| 20 | * up on its own page (the model providers, alerts and trackers pages, the |
| 21 | * GitHub import, webhooks); this page only finds them. |
| 22 | */ |
| 23 | export async function loader({ params, context, request }: Route.LoaderArgs) { |
| 24 | // Signed out, sign in first (as Chat and Docs do), rather than a 404. |
| 25 | const viewer = requireUser(context, request); |
| 26 | const role = roleIn(viewer, params.owner); |
| 27 | if (!role || !viewer) throw new Response(null, { status: 404 }); |
| 28 | const slug = params.owner.toLowerCase(); |
| 29 | |
| 30 | // An older link to one provider's form (`?add=sentry`): its own page now. |
| 31 | const add = new URL(request.url).searchParams.get("add"); |
| 32 | if (add && add in PROVIDERS) { |
| 33 | throw redirect(`/${slug}/-/integrations/${integrationsSection(PROVIDERS[add as Provider].kind)}?add=${add}#add`); |
| 34 | } |
| 35 | |
| 36 | return { slug, owner: role === "owner", connected: await connectedStates(slug, viewer) }; |
| 37 | } |
| 38 | |
| 39 | export default function WorkspaceIntegrationsDirectory({ loaderData }: Route.ComponentProps) { |
| 40 | const { slug, owner, connected } = loaderData; |
| 41 | return ( |
| 42 | <div> |
| 43 | <ScopeNote scope="workspace" workspace={slug} /> |
| 44 | <ConnectorDirectory |
| 45 | scope="workspace" |
| 46 | views={connectorsFor("workspace")} |
| 47 | connected={connected} |
| 48 | workspace={slug} |
| 49 | canManage={owner} |
| 50 | /> |
| 51 | </div> |
| 52 | ); |
| 53 | } |