import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import type { CreateInstanceOptions, Instance } from "@/types/instance"; import { getBasicFields, getAdvancedFields } from "@/lib/zodFormUtils"; import { ChevronDown, ChevronRight } from "lucide-react"; import ZodFormField from "@/components/ZodFormField"; interface InstanceModalProps { open: boolean; onOpenChange: (open: boolean) => void; onSave: (name: string, options: CreateInstanceOptions) => void; instance?: Instance; // For editing existing instance } const InstanceModal: React.FC = ({ open, onOpenChange, onSave, instance, }) => { const isEditing = !!instance; const isRunning = instance?.running || true; // Assume running if instance exists const [instanceName, setInstanceName] = useState(""); const [formData, setFormData] = useState({}); const [showAdvanced, setShowAdvanced] = useState(false); const [nameError, setNameError] = useState(""); // Get field lists dynamically from the type const basicFields = getBasicFields(); const advancedFields = getAdvancedFields(); // Reset form when modal opens/closes or when instance changes useEffect(() => { if (open) { if (instance) { // Populate form with existing instance data setInstanceName(instance.name); setFormData(instance.options || {}); } else { // Reset form for new instance setInstanceName(""); setFormData({ auto_restart: true, // Default value }); } setShowAdvanced(false); // Always start with basic view setNameError(""); // Reset any name errors } }, [open, instance]); const handleFieldChange = (key: keyof CreateInstanceOptions, value: any) => { setFormData((prev) => ({ ...prev, [key]: value, })); }; const handleNameChange = (name: string) => { setInstanceName(name); // Validate instance name if (!name.trim()) { setNameError("Instance name is required"); } else if (!/^[a-zA-Z0-9-_]+$/.test(name)) { setNameError( "Instance name can only contain letters, numbers, hyphens, and underscores" ); } else { setNameError(""); } }; const handleSave = () => { // Validate instance name before saving if (!instanceName.trim()) { setNameError("Instance name is required"); return; } // Clean up undefined values to avoid sending empty fields const cleanOptions: CreateInstanceOptions = {}; Object.entries(formData).forEach(([key, value]) => { if (value !== undefined && value !== "" && value !== null) { // Handle arrays - don't include empty arrays if (Array.isArray(value) && value.length === 0) { return; } (cleanOptions as any)[key] = value; } }); onSave(instanceName, cleanOptions); onOpenChange(false); }; const handleCancel = () => { onOpenChange(false); }; const toggleAdvanced = () => { setShowAdvanced(!showAdvanced); }; // Check if auto_restart is enabled const isAutoRestartEnabled = formData.auto_restart === true; return ( {isEditing ? "Edit Instance" : "Create New Instance"} {isEditing ? "Modify the instance configuration below." : "Configure your new llama-server instance below."}
{/* Instance Name - Special handling since it's not in CreateInstanceOptions */}
handleNameChange(e.target.value)} placeholder="my-instance" disabled={isEditing} // Don't allow name changes when editing className={nameError ? "border-red-500" : ""} /> {nameError &&

{nameError}

}

Unique identifier for the instance

{/* Auto Restart Configuration Section */}

Auto Restart Configuration

{/* Auto Restart Toggle */} {/* Show restart options only when auto restart is enabled */} {isAutoRestartEnabled && (
)}
{/* Basic Fields - Automatically generated from type (excluding auto restart options) */}

Basic Configuration

{basicFields .filter( (fieldKey) => fieldKey !== "auto_restart" && fieldKey !== "max_restarts" && fieldKey !== "restart_delay" ) // Exclude auto_restart, max_restarts, and restart_delay as they're handled above .map((fieldKey) => ( ))}
{/* Advanced Fields Toggle */}
{/* Advanced Fields - Automatically generated from type (excluding restart options) */} {showAdvanced && (
{advancedFields .filter( (fieldKey) => !["max_restarts", "restart_delay"].includes( fieldKey as string ) ) // Exclude restart options as they're handled above .sort() .map((fieldKey) => ( ))}
)}
); }; export default InstanceModal;