Files
bifrost/ui/app/workspace/plugins/fragments/pluginFormFragments.tsx
Beyhan Oğur 880f412e2c first commit
2026-04-26 21:52:23 +03:00

137 lines
3.6 KiB
TypeScript

import { Button } from "@/components/ui/button";
import { CodeEditor } from "@/components/ui/codeEditor";
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Info, PlusIcon } from "lucide-react";
import { useState } from "react";
import { UseFormReturn } from "react-hook-form";
interface PluginFormData {
name: string;
path: string;
config?: string;
hasConfig: boolean;
}
interface PluginFormFragmentProps {
form: UseFormReturn<PluginFormData>;
isEditMode?: boolean;
}
export function PluginFormFragment({ form, isEditMode = false }: PluginFormFragmentProps) {
const [showConfig, setShowConfig] = useState(form.getValues("hasConfig") || false);
return (
<div className="space-y-4">
<div className="bg-muted/50 flex items-start gap-2 rounded-md border p-3">
<Info className="text-muted-foreground mt-0.5 h-4 w-4 shrink-0" />
<p className="text-muted-foreground text-sm">
{isEditMode
? "Update your plugin configuration. Plugin name and path are read-only."
: "Install a custom plugin by providing an absolute file path or HTTP URL accessible to Bifrost deployment (.so)."}{" "}
<a
href="https://docs.getbifrost.ai/plugins"
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline"
data-testid="plugins-form-docs-link"
>
Learn more
</a>
</p>
</div>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Plugin Name *</FormLabel>
<FormControl>
<Input placeholder="e.g., my-custom-plugin" {...field} disabled={isEditMode} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="path"
render={({ field }) => (
<FormItem>
<FormLabel>Plugin Path/URL *</FormLabel>
<FormControl>
<Input placeholder="e.g., /path/to/plugin.so or https://example.com/plugin.so" {...field} disabled={isEditMode} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{!showConfig ? (
<Button
type="button"
variant="outline"
size="sm"
onClick={() => {
setShowConfig(true);
form.setValue("hasConfig", true);
if (!form.getValues("config")) {
form.setValue("config", "{}");
}
}}
className="w-full"
>
<PlusIcon className="mr-2 h-4 w-4" />
Add Configuration
</Button>
) : (
<FormField
control={form.control}
name="config"
render={({ field }) => (
<FormItem>
<div className="flex items-center justify-between">
<FormLabel>Configuration (JSON)</FormLabel>
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => {
setShowConfig(false);
form.setValue("hasConfig", false);
form.setValue("config", undefined);
}}
className="h-auto p-1 text-xs"
>
Remove
</Button>
</div>
<FormControl>
<div className="rounded-sm border">
<CodeEditor
className="z-0 w-full"
minHeight={200}
maxHeight={400}
wrap={true}
code={field.value || "{}"}
lang="json"
onChange={field.onChange}
options={{
scrollBeyondLastLine: false,
collapsibleBlocks: true,
lineNumbers: "on",
alwaysConsumeMouseWheel: false,
}}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
)}
</div>
);
}