Skip to content

Commit dcd568e

Browse files
committed
feat: fetch directories and add dropdown to select directory
1 parent e56510f commit dcd568e

File tree

2 files changed

+88
-27
lines changed

2 files changed

+88
-27
lines changed

site/src/DynamicForm.tsx

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,55 @@ import {
99
} from "./types/preview";
1010
import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectItem } from "./components/Select/Select";
1111
import { Input } from "./components/Input/Input";
12+
1213
export function DynamicForm() {
14+
const [testdata, setTestdata] = useState<string>("conditional");
15+
const [directories, setDirectories] = useState<string[]>([]);
16+
1317
const serverAddress = "localhost:8100";
14-
const directoryPath = "conditional";
18+
19+
// Fetch directories when component mounts
20+
useEffect(() => {
21+
fetch(`http://${serverAddress}/directories`)
22+
.then(response => {
23+
if (!response.ok) {
24+
throw new Error(`Failed to fetch directories: ${response.status} ${response.statusText}`);
25+
}
26+
return response.json();
27+
})
28+
.then(data => {
29+
setDirectories(data);
30+
// If testdata is not in the list of directories, set it to the first directory
31+
if (data.length > 0 && !data.includes(testdata)) {
32+
setTestdata(data[0]);
33+
}
34+
})
35+
.catch(error => {
36+
console.error('Error fetching directories:', error);
37+
// Fallback to some default directories if fetch fails
38+
setDirectories(["conditional"]);
39+
});
40+
}, []);
41+
1542
const planPath = "";
16-
const wsUrl = `ws://${serverAddress}/ws/${encodeURIComponent(directoryPath)}${planPath ? `?plan=${encodeURIComponent(planPath)}` : ''}`;
43+
const wsUrl = `ws://${serverAddress}/ws/${encodeURIComponent(testdata)}${planPath ? `?plan=${encodeURIComponent(planPath)}` : ''}`;
1744

1845
const { message: serverResponse, sendMessage, connectionStatus } = useWebSocket<Response>(wsUrl);
1946

2047
const [response, setResponse] = useState<Response | null>(null);
21-
48+
const [currentId, setCurrentId] = useState<number>(0);
49+
2250
// Initialize React Hook Form
2351
const methods = useForm<Record<string, string>>({
2452
defaultValues: {}
2553
});
2654
const { watch, reset } = methods;
2755

28-
// Whenever we get a new server response, update local state
2956
useEffect(() => {
30-
if (serverResponse) {
57+
if (serverResponse && serverResponse.id >= currentId) {
3158
setResponse(serverResponse);
3259
}
33-
}, [serverResponse]);
60+
}, [serverResponse, currentId]);
3461

3562
// Reset form state whenever "response" changes
3663
useEffect(() => {
@@ -44,31 +71,41 @@ export function DynamicForm() {
4471

4572
// Use RHF's `reset` to update the entire form
4673
reset(defaultValues);
74+
75+
// Also update prevValues to match the initial form state
76+
// This prevents the initial values from being detected as changes
77+
setPrevValues(defaultValues);
4778
}
4879
}, [response, reset]);
4980

5081
// Watch all fields and send changes to the server
5182
const watchedValues = watch();
52-
console.log("serverResponse", serverResponse);
53-
83+
5484
// Track previous values to detect changes
5585
const [prevValues, setPrevValues] = useState<Record<string, string>>({});
5686

5787
useEffect(() => {
58-
if (response) {
59-
const hasChanged = Object.keys(watchedValues).some(
60-
key => watchedValues[key] !== prevValues[key]
61-
);
62-
63-
if (hasChanged) {
88+
if (!response) return;
89+
90+
// Skip if this is the first render or if prevValues is empty
91+
if (Object.keys(prevValues).length === 0) return;
92+
93+
const hasChanged = Object.keys(watchedValues).some(
94+
key => watchedValues[key] !== prevValues[key]
95+
);
96+
if (hasChanged) {
97+
setCurrentId(prevId => {
98+
const newId = prevId + 1;
6499
const request: Request = {
65-
id: 1,
100+
id: newId,
66101
inputs: watchedValues
67102
};
68-
sendMessage(request);
69103

70-
setPrevValues({...watchedValues});
71-
}
104+
sendMessage(request);
105+
return newId;
106+
});
107+
108+
setPrevValues({...watchedValues});
72109
}
73110
}, [watchedValues, response, sendMessage, prevValues]);
74111

@@ -170,7 +207,6 @@ export function DynamicForm() {
170207
);
171208
};
172209

173-
// 8) Optionally display diagnostics from the server
174210
const renderDiagnostics = (diagnostics: Diagnostics) => {
175211
return (
176212
<div>
@@ -199,13 +235,40 @@ export function DynamicForm() {
199235
const sortedParams = [...response.parameters].sort((a, b) => a.order - b.order);
200236

201237
return (
202-
<FormProvider {...methods}>
203-
<form className="flex flex-col gap-4">
204-
{response.diagnostics && renderDiagnostics(response.diagnostics)}
238+
<>
239+
<div>
240+
<Select
241+
onValueChange={(value) => {
242+
setTestdata(value);
243+
// Reset response when changing testdata to avoid showing stale data
244+
setResponse(null);
245+
}}
246+
value={testdata}
247+
defaultValue={testdata}
248+
>
249+
<SelectTrigger className="w-fit">
250+
<SelectValue />
251+
</SelectTrigger>
252+
<SelectContent>
253+
<SelectGroup>
254+
{directories.map((name, idx) => {
255+
return (
256+
<SelectItem key={idx} value={name}>{name}</SelectItem>
257+
);
258+
})}
259+
</SelectGroup>
260+
</SelectContent>
261+
</Select>
262+
</div>
263+
264+
<FormProvider {...methods}>
265+
<form className="flex flex-col gap-4">
266+
{response.diagnostics && renderDiagnostics(response.diagnostics)}
205267

206-
{sortedParams && sortedParams.map((param) => renderParameter(param))}
207-
</form>
208-
</FormProvider>
268+
{sortedParams && sortedParams.map((param) => renderParameter(param))}
269+
</form>
270+
</FormProvider>
271+
</>
209272
);
210273
}
211274

site/src/useWebSocket.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ export function useWebSocket<T>(url: string, reconnectDelay = 3000) {
6363
}
6464
}, [reconnectDelay]); // Only depends on reconnectDelay, not url
6565

66-
// Set up the WebSocket connection
6766
useEffect(() => {
6867
// Close any existing connection when the URL changes
6968
if (wsRef.current) {
@@ -85,7 +84,6 @@ export function useWebSocket<T>(url: string, reconnectDelay = 3000) {
8584
const sendMessage = (data: unknown) => {
8685
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
8786
wsRef.current.send(JSON.stringify(data));
88-
8987
} else {
9088
console.warn("Cannot send message: WebSocket is not connected");
9189
}

0 commit comments

Comments
 (0)