"use client" import * as React from "react" import { buttonVariants } from "@/components/ui/button" import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger, SheetFooter, SheetClose, } from "@/components/ui/sheet" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Label } from "@/components/ui/label" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { Input } from "@/components/ui/input" import { Switch } from "@/components/ui/switch" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { useAppDispatch, useAppSelector, } from "@/common" import { cn } from "@/lib/utils" import { SettingsIcon, LoaderCircleIcon, BoxesIcon, Trash2Icon } from "lucide-react" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" import { toast } from "sonner" import { useGraphs } from "@/common/hooks" import { AddonDef, Graph } from "@/common/graph" export function RemotePropertyCfgSheet() { const dispatch = useAppDispatch() const { selectedGraph, update: updateGraph } = useGraphs() const graphName = useAppSelector((state) => state.global.selectedGraphId) const [selectedExtension, setSelectedExtension] = React.useState("") const selectedExtensionNode = selectedGraph?.nodes.find(n => n.name === selectedExtension) const addonModules = useAppSelector((state) => state.global.addonModules) const selectedAddonModule = addonModules.find( (module) => module.name === selectedExtensionNode?.addon, ) const hasProperty = !!selectedAddonModule?.api?.property && Object.keys(selectedAddonModule?.api?.property).length > 0 return ( Properties Setting You can adjust extension properties for selected graph here, the values will be written into property.json file when you save.
{hasProperty ? selectedExtensionNode?.["property"] && ( module.name === selectedExtensionNode?.addon, )?.api?.property || {} } onUpdate={async (data) => { // clone the overridenProperties const selectedGraphCopy: Graph = JSON.parse(JSON.stringify(selectedGraph)) const nodes = selectedGraphCopy?.nodes || [] let needUpdate = false for (const node of nodes) { if (node.name === selectedExtension) { node.property = data needUpdate = true } } if (needUpdate) { await updateGraph(selectedGraphCopy.id, selectedGraphCopy) toast.success("Properties updated", { description: `Graph: ${graphName}, Extension: ${selectedExtension}`, }) } }} /> ) : ( No properties found for the selected extension. )}
) } export function RemotePropertyAddCfgSheet({ selectedExtension, extensionNodeData, onUpdate, }: { selectedExtension: string, extensionNodeData: Record, onUpdate: (data: string) => void }) { const dispatch = useAppDispatch() const { selectedGraph } = useGraphs() const selectedExtensionNode = selectedGraph?.nodes.find(n => n.name === selectedExtension) const addonModules = useAppSelector((state) => state.global.addonModules) const selectedAddonModule = addonModules.find( (module) => module.name === selectedExtensionNode?.addon, ) const allProperties = Object.keys(selectedAddonModule?.api?.property || {}) const usedProperties = Object.keys(extensionNodeData) const remainingProperties = allProperties.filter( (prop) => !usedProperties.includes(prop), ) const hasRemainingProperties = remainingProperties.length > 0 const [selectedProperty, setSelectedProperty] = React.useState("") const [isSheetOpen, setSheetOpen] = React.useState(false) // State to control the sheet return (
Property Add You can add a property into a graph extension node and configure its value. {hasRemainingProperties ? ( <> ) : ( <> No remaining properties to add. )}
) } // Helper to convert values based on type const convertToType = (value: any, type: string) => { switch (type) { case "int64": case "int32": return parseInt(value, 10) case "float64": case "float32": return parseFloat(value) case "bool": return value === true || value === "true" case "string": return String(value) default: return value } } const defaultTypeValue = (type: string) => { switch (type) { case "int64": case "int32": return 0 case "float64": return 0.1 case "bool": return false case "string": default: return "" } } import { useState } from "react" const GraphCfgForm = ({ selectedExtension, selectedAddonModule, initialData, metadata, onUpdate, }: { selectedExtension: string, selectedAddonModule: AddonDef.Module | undefined, initialData: Record metadata: Record onUpdate: (data: Record) => void }) => { const formSchema = z.record( z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()]) ) const [formData, setFormData] = useState(initialData) const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: formData, }) const onSubmit = (data: z.infer) => { const convertedData = Object.entries(data).reduce( (acc, [key, value]) => { const type = metadata[key]?.type || "string" acc[key] = value === "" ? defaultTypeValue(type) : convertToType(value, type) return acc }, {} as Record ) onUpdate(convertedData) } const handleDelete = (key: string) => { const updatedData = { ...formData } delete updatedData[key] // Remove the specific key setFormData(updatedData) // Update state form.reset(updatedData) // Reset the form } const initialDataWithType = Object.entries(formData).reduce( (acc, [key, value]) => { acc[key] = { value, type: metadata[key]?.type || "string" } return acc }, {} as Record< string, { value: string | number | boolean | null; type: string } > ) return (
{Object.entries(initialDataWithType).map(([key, { value, type }]) => ( ( {key}
{type === "bool" ? (
) : ( )}
handleDelete(key)} // Delete action >
)} /> ))}
{ let defaultProperty = selectedAddonModule?.defaultProperty || {} let defaultValue = defaultProperty[key] if (defaultValue === undefined) { let schema = selectedAddonModule?.api?.property || {} let schemaType = schema[key]?.type if (schemaType === "bool") { defaultValue = false } } let updatedData = { ...formData } updatedData[key] = defaultValue setFormData(updatedData) form.reset(updatedData) }} />
) }