Support dyad add integration flow
This commit is contained in:
73
src/components/chat/DyadAddIntegration.tsx
Normal file
73
src/components/chat/DyadAddIntegration.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { selectedAppIdAtom } from "@/atoms/appAtoms";
|
||||||
|
import { useAtomValue, atom, useAtom } from "jotai";
|
||||||
|
import { showError } from "@/lib/toast";
|
||||||
|
import { useStreamChat } from "@/hooks/useStreamChat";
|
||||||
|
import { selectedChatIdAtom } from "@/atoms/chatAtoms";
|
||||||
|
|
||||||
|
interface DyadAddIntegrationProps {
|
||||||
|
node: {
|
||||||
|
properties: {
|
||||||
|
provider: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSetupAtom = atom(false);
|
||||||
|
|
||||||
|
export const DyadAddIntegration: React.FC<DyadAddIntegrationProps> = ({
|
||||||
|
node,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const { streamMessage } = useStreamChat();
|
||||||
|
const [isSetup, setIsSetup] = useAtom(isSetupAtom);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { provider } = node.properties;
|
||||||
|
const appId = useAtomValue(selectedAppIdAtom);
|
||||||
|
const selectedChatId = useAtomValue(selectedChatIdAtom);
|
||||||
|
|
||||||
|
const handleSetupClick = () => {
|
||||||
|
if (!appId) {
|
||||||
|
showError("No app ID found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
navigate({ to: "/app-details", search: { appId } });
|
||||||
|
setIsSetup(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isSetup) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setIsSetup(false);
|
||||||
|
if (!selectedChatId) {
|
||||||
|
showError("No chat ID found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
streamMessage({
|
||||||
|
prompt: "OK, I've setup Supabase. Continue",
|
||||||
|
chatId: selectedChatId,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="my-1"
|
||||||
|
>
|
||||||
|
Continue | I've setup {provider}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2 my-2 p-3 border rounded-md bg-secondary/10">
|
||||||
|
<div className="text-sm">
|
||||||
|
<div className="font-medium">Integrate with {provider}?</div>
|
||||||
|
<div className="text-muted-foreground text-xs">{children}</div>
|
||||||
|
</div>
|
||||||
|
<Button onClick={handleSetupClick} className="self-start w-full">
|
||||||
|
Set up {provider}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@ import { DyadRename } from "./DyadRename";
|
|||||||
import { DyadDelete } from "./DyadDelete";
|
import { DyadDelete } from "./DyadDelete";
|
||||||
import { DyadAddDependency } from "./DyadAddDependency";
|
import { DyadAddDependency } from "./DyadAddDependency";
|
||||||
import { DyadExecuteSql } from "./DyadExecuteSql";
|
import { DyadExecuteSql } from "./DyadExecuteSql";
|
||||||
|
import { DyadAddIntegration } from "./DyadAddIntegration";
|
||||||
import { CodeHighlight } from "./CodeHighlight";
|
import { CodeHighlight } from "./CodeHighlight";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { isStreamingAtom } from "@/atoms/chatAtoms";
|
import { isStreamingAtom } from "@/atoms/chatAtoms";
|
||||||
@@ -75,6 +76,7 @@ function preprocessUnclosedTags(content: string): {
|
|||||||
"dyad-delete",
|
"dyad-delete",
|
||||||
"dyad-add-dependency",
|
"dyad-add-dependency",
|
||||||
"dyad-execute-sql",
|
"dyad-execute-sql",
|
||||||
|
"dyad-add-integration",
|
||||||
];
|
];
|
||||||
|
|
||||||
let processedContent = content;
|
let processedContent = content;
|
||||||
@@ -134,6 +136,7 @@ function parseCustomTags(content: string): ContentPiece[] {
|
|||||||
"dyad-delete",
|
"dyad-delete",
|
||||||
"dyad-add-dependency",
|
"dyad-add-dependency",
|
||||||
"dyad-execute-sql",
|
"dyad-execute-sql",
|
||||||
|
"dyad-add-integration",
|
||||||
];
|
];
|
||||||
|
|
||||||
const tagPattern = new RegExp(
|
const tagPattern = new RegExp(
|
||||||
@@ -287,6 +290,19 @@ function renderCustomTag(
|
|||||||
</DyadExecuteSql>
|
</DyadExecuteSql>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case "dyad-add-integration":
|
||||||
|
return (
|
||||||
|
<DyadAddIntegration
|
||||||
|
node={{
|
||||||
|
properties: {
|
||||||
|
provider: attributes.provider || "",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</DyadAddIntegration>
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useNavigate, useSearch } from "@tanstack/react-router";
|
import { useNavigate, useRouter, useSearch } from "@tanstack/react-router";
|
||||||
import { useAtom, useAtomValue } from "jotai";
|
import { useAtom, useAtomValue } from "jotai";
|
||||||
import { appBasePathAtom, appsListAtom } from "@/atoms/appAtoms";
|
import { appBasePathAtom, appsListAtom } from "@/atoms/appAtoms";
|
||||||
import { IpcClient } from "@/ipc/ipc_client";
|
import { IpcClient } from "@/ipc/ipc_client";
|
||||||
@@ -32,6 +32,7 @@ import { SupabaseConnector } from "@/components/SupabaseConnector";
|
|||||||
|
|
||||||
export default function AppDetailsPage() {
|
export default function AppDetailsPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const router = useRouter();
|
||||||
const search = useSearch({ from: "/app-details" as const });
|
const search = useSearch({ from: "/app-details" as const });
|
||||||
const [appsList] = useAtom(appsListAtom);
|
const [appsList] = useAtom(appsListAtom);
|
||||||
const { refreshApps } = useLoadApps();
|
const { refreshApps } = useLoadApps();
|
||||||
@@ -142,7 +143,7 @@ export default function AppDetailsPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="relative min-h-screen p-8">
|
<div className="relative min-h-screen p-8">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => navigate({ to: "/", search: {} })}
|
onClick={() => router.history.back()}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="absolute top-4 left-4 flex items-center gap-2 bg-(--background-lightest) py-5"
|
className="absolute top-4 left-4 flex items-center gap-2 bg-(--background-lightest) py-5"
|
||||||
@@ -160,7 +161,7 @@ export default function AppDetailsPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="relative min-h-screen p-8 w-full">
|
<div className="relative min-h-screen p-8 w-full">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => navigate({ to: "/", search: {} })}
|
onClick={() => router.history.back()}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="absolute top-4 left-4 flex items-center gap-2 bg-(--background-lightest) py-5"
|
className="absolute top-4 left-4 flex items-center gap-2 bg-(--background-lightest) py-5"
|
||||||
|
|||||||
Reference in New Issue
Block a user