Skip to content
53 linesCodeBlameRaw
1import { redirect } from "react-router";
2
3import { type Provider, PROVIDERS } from "@g1t/contracts";
4import { connectorsFor } from "@g1t/contracts/connectors";
5
6import type { Route } from "./+types/integrations-directory";
7import { ConnectorDirectory, ScopeNote } from "../../components/connectors";
8import { connectedStates } from "../../lib/connected.server";
9import { integrationsSection } from "../../lib/integration-sections";
10import { page } from "../../lib/meta";
11import { requireUser, roleIn } from "../../lib/session.server";
12
13export 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 */
23export 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
39export 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}