From a491f294831d22a14bc431c6abeef58deb45c54f Mon Sep 17 00:00:00 2001 From: LordMathis Date: Thu, 2 Oct 2025 23:18:33 +0200 Subject: [PATCH] Add node selection functionality to InstanceSettingsCard and define Node API --- .../instance/InstanceSettingsCard.tsx | 52 ++++++++++++++++++- webui/src/lib/api.ts | 15 ++++++ webui/src/schemas/instanceOptions.ts | 3 ++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/webui/src/components/instance/InstanceSettingsCard.tsx b/webui/src/components/instance/InstanceSettingsCard.tsx index c85eda9..124986b 100644 --- a/webui/src/components/instance/InstanceSettingsCard.tsx +++ b/webui/src/components/instance/InstanceSettingsCard.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState, useEffect } from 'react' import type { CreateInstanceOptions } from '@/types/instance' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Label } from '@/components/ui/label' @@ -7,6 +7,8 @@ import AutoRestartConfiguration from '@/components/instance/AutoRestartConfigura import NumberInput from '@/components/form/NumberInput' import CheckboxInput from '@/components/form/CheckboxInput' import EnvironmentVariablesInput from '@/components/form/EnvironmentVariablesInput' +import SelectInput from '@/components/form/SelectInput' +import { nodesApi, type NodeResponse } from '@/lib/api' interface InstanceSettingsCardProps { instanceName: string @@ -25,6 +27,42 @@ const InstanceSettingsCard: React.FC = ({ onNameChange, onChange }) => { + const [nodes, setNodes] = useState([]) + const [loadingNodes, setLoadingNodes] = useState(true) + + useEffect(() => { + const fetchNodes = async () => { + try { + const fetchedNodes = await nodesApi.list() + setNodes(fetchedNodes) + } catch (error) { + console.error('Failed to fetch nodes:', error) + } finally { + setLoadingNodes(false) + } + } + + fetchNodes() + }, []) + + const nodeOptions = [ + { value: '', label: 'Default (Main Node)' }, + ...nodes.map(node => ({ + value: node.name, + label: node.name + })) + ] + + const handleNodeChange = (value: string | undefined) => { + if (value) { + onChange('nodes', [value]) + } else { + onChange('nodes', undefined) + } + } + + const selectedNode = formData.nodes && formData.nodes.length > 0 ? formData.nodes[0] : '' + return ( @@ -50,6 +88,18 @@ const InstanceSettingsCard: React.FC = ({

+ {/* Node Selection */} + {!loadingNodes && nodes.length > 0 && ( + + )} + {/* Auto Restart Configuration */} apiCall("/nodes"), + + // GET /nodes/{name} + get: (name: string) => apiCall(`/nodes/${name}`), +}; + // Instance API functions export const instancesApi = { // GET /instances diff --git a/webui/src/schemas/instanceOptions.ts b/webui/src/schemas/instanceOptions.ts index 0af09c1..3cbf523 100644 --- a/webui/src/schemas/instanceOptions.ts +++ b/webui/src/schemas/instanceOptions.ts @@ -39,6 +39,9 @@ export const CreateInstanceOptionsSchema = z.object({ // Backend configuration backend_type: z.enum([BackendType.LLAMA_CPP, BackendType.MLX_LM, BackendType.VLLM]).optional(), backend_options: BackendOptionsSchema.optional(), + + // Node configuration + nodes: z.array(z.string()).optional(), }) // Re-export types and schemas from backend files