The dropdown is connecting APIs
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import githubLogo from "~/assets/images/integrations/logo-github.png";
|
||||
import { useEffect } from "react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import Pizzly from "@nangohq/pizzly-frontend";
|
||||
import { useFetcher } from "@remix-run/react";
|
||||
import type {
|
||||
CreateResponse,
|
||||
Update,
|
||||
UpdateResponse,
|
||||
} from "~/routes/api/v1/internal/connection";
|
||||
|
||||
@@ -26,15 +27,17 @@ const actionPath = "/api/v1/internal/connection";
|
||||
export function ConnectButton({
|
||||
integration,
|
||||
organizationId,
|
||||
sourceId,
|
||||
className,
|
||||
children,
|
||||
}: {
|
||||
integration: Integration;
|
||||
organizationId: string;
|
||||
sourceId?: string;
|
||||
className?: string;
|
||||
children: (status: Status) => React.ReactNode;
|
||||
}) {
|
||||
const { createFetcher, status } = useCreateConnection();
|
||||
const { createFetcher, status } = useCreateConnection(sourceId);
|
||||
|
||||
return (
|
||||
<createFetcher.Form method="post" action={actionPath}>
|
||||
@@ -54,43 +57,87 @@ export function ConnectButton({
|
||||
|
||||
type Status = "loading" | "idle";
|
||||
|
||||
export function useCreateConnection() {
|
||||
export function useCreateConnection(sourceId?: string) {
|
||||
const createConnectionFetcher = useFetcher<CreateResponse>();
|
||||
const completeConnectionFetcher = useFetcher<UpdateResponse>();
|
||||
const status: Status =
|
||||
createConnectionFetcher.state === "loading" ||
|
||||
completeConnectionFetcher.state === "loading"
|
||||
? "loading"
|
||||
: "idle";
|
||||
createConnectionFetcher.state === "idle" &&
|
||||
completeConnectionFetcher.state === "idle"
|
||||
? "idle"
|
||||
: "loading";
|
||||
|
||||
useEffect(() => {
|
||||
async function authenticationFlow() {
|
||||
if (createConnectionFetcher.data === undefined) return;
|
||||
const completeFlow = useCallback(
|
||||
async ({
|
||||
pizzlyHost,
|
||||
connectionId,
|
||||
service,
|
||||
sourceId,
|
||||
}: {
|
||||
pizzlyHost: string;
|
||||
connectionId: string;
|
||||
service: string;
|
||||
sourceId?: string;
|
||||
}) => {
|
||||
console.log(`completeFlow`, {
|
||||
pizzlyHost,
|
||||
connectionId,
|
||||
service,
|
||||
sourceId,
|
||||
});
|
||||
|
||||
try {
|
||||
const pizzly = new Pizzly(createConnectionFetcher.data.host);
|
||||
const pizzly = new Pizzly(pizzlyHost);
|
||||
await pizzly.auth(service, connectionId);
|
||||
|
||||
await pizzly.auth(
|
||||
createConnectionFetcher.data.integrationKey,
|
||||
createConnectionFetcher.data.connectionId
|
||||
);
|
||||
let completeData: Update = {
|
||||
type: "update",
|
||||
connectionId: connectionId,
|
||||
};
|
||||
|
||||
completeConnectionFetcher.submit(
|
||||
{
|
||||
type: "update",
|
||||
connectionId: createConnectionFetcher.data.connectionId,
|
||||
},
|
||||
{ method: "post", action: actionPath }
|
||||
);
|
||||
if (sourceId) {
|
||||
completeData = {
|
||||
...completeData,
|
||||
sourceId,
|
||||
};
|
||||
}
|
||||
|
||||
completeConnectionFetcher.submit(completeData, {
|
||||
method: "post",
|
||||
action: actionPath,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error(
|
||||
`There was an error in the OAuth flow for integration "${error.providerConfigKey}" and connection-id "${error.connectionId}": ${error.error.type} - ${error.error.message}`
|
||||
`There was an error in the OAuth flow for integration "${error.providerConfigKey}" and connection-id "${error.connectionId}": ${error.error.type} - ${error.error.message}`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
[completeConnectionFetcher]
|
||||
);
|
||||
|
||||
authenticationFlow();
|
||||
}, [completeConnectionFetcher, createConnectionFetcher.data]);
|
||||
useEffect(() => {
|
||||
if (
|
||||
createConnectionFetcher.state !== "idle" ||
|
||||
createConnectionFetcher.type !== "done"
|
||||
)
|
||||
return;
|
||||
if (completeConnectionFetcher.state !== "idle") return;
|
||||
if (createConnectionFetcher.data === undefined) return;
|
||||
|
||||
completeFlow({
|
||||
pizzlyHost: createConnectionFetcher.data.host,
|
||||
connectionId: createConnectionFetcher.data.connectionId,
|
||||
service: createConnectionFetcher.data.integrationKey,
|
||||
sourceId,
|
||||
});
|
||||
}, [
|
||||
completeConnectionFetcher,
|
||||
completeConnectionFetcher.data,
|
||||
completeConnectionFetcher.submit,
|
||||
completeFlow,
|
||||
createConnectionFetcher,
|
||||
sourceId,
|
||||
]);
|
||||
|
||||
return {
|
||||
createFetcher: createConnectionFetcher,
|
||||
|
||||
@@ -35,6 +35,7 @@ export function ConnectionSelector({
|
||||
key={integration.key}
|
||||
integration={integration}
|
||||
organizationId={organizationId}
|
||||
sourceId={sourceId}
|
||||
className="flex rounded-md bg-slate-800 border border-rose-400 gap-3 text-sm text-slate-200 items-center hover:bg-slate-800/30 transition shadow-md disabled:opacity-50 py-1 pl-1 pr-3"
|
||||
>
|
||||
{(status) => (
|
||||
@@ -136,6 +137,7 @@ export function ConnectionSelector({
|
||||
key={integration.key}
|
||||
integration={integration}
|
||||
organizationId={organizationId}
|
||||
sourceId={sourceId}
|
||||
>
|
||||
{(status) => (
|
||||
<div className="flex items-center gap-2 mx-1 pl-2.5 py-2 rounded hover:bg-slate-800 transition">
|
||||
|
||||
@@ -10,6 +10,16 @@ import { integrations } from "~/components/integrations/ConnectButton";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { APIConnectionType } from ".prisma/client";
|
||||
import { env } from "~/env.server";
|
||||
import { connectExternalSource } from "~/models/externalSource.server";
|
||||
import { internalPubSub } from "~/services/messageBroker.server";
|
||||
|
||||
const updateSchema = z.object({
|
||||
type: z.literal("update"),
|
||||
connectionId: z.string(),
|
||||
sourceId: z.string().optional(),
|
||||
});
|
||||
|
||||
export type Update = z.infer<typeof updateSchema>;
|
||||
|
||||
const requestSchema = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
@@ -17,10 +27,7 @@ const requestSchema = z.discriminatedUnion("type", [
|
||||
organizationId: z.string(),
|
||||
key: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("update"),
|
||||
connectionId: z.string(),
|
||||
}),
|
||||
updateSchema,
|
||||
]);
|
||||
|
||||
export type CreateResponse = {
|
||||
@@ -85,17 +92,27 @@ export const action = async ({ request, params }: ActionArgs) => {
|
||||
return json(response);
|
||||
}
|
||||
case "update": {
|
||||
const { connectionId } = parsed;
|
||||
const { connectionId, sourceId } = parsed;
|
||||
await setConnectedAPIConnection({
|
||||
id: connectionId,
|
||||
});
|
||||
|
||||
console.log("sourceId", sourceId);
|
||||
|
||||
if (sourceId !== undefined) {
|
||||
await connectExternalSource({ sourceId, connectionId });
|
||||
await internalPubSub.publish("EXTERNAL_SOURCE_UPSERTED", {
|
||||
id: sourceId,
|
||||
});
|
||||
}
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log("error", error);
|
||||
return json({ message: error.message }, { status: 400 });
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user