@@ -13,10 +13,11 @@ import { Input } from "./components/Input/Input";
13
13
import { Switch } from "./components/Switch/Switch" ;
14
14
import { useUsers } from './hooks/useUsers' ;
15
15
import { useDirectories } from './hooks/useDirectories' ;
16
- import { useDebouncedFunction } from './hooks/debounce' ;
17
16
import { CollapsibleSummary } from "./components/CollapsibleSummary/CollapsibleSummary" ;
18
17
import { Slider } from "./components/ui/slider" ;
19
18
import ReactJson from 'react-json-view' ;
19
+ import { RadioGroup , RadioGroupItem } from "./components/ui/radio-group"
20
+ import { Label } from "./components/Label/Label" ;
20
21
21
22
export function DynamicForm ( ) {
22
23
const serverAddress = "localhost:8100" ;
@@ -43,8 +44,6 @@ export function DynamicForm() {
43
44
44
45
const {
45
46
directories,
46
- // testdata,
47
- // setTestdata,
48
47
isLoading,
49
48
fetchError
50
49
} = useDirectories ( serverAddress , urlTestdata ) ;
@@ -134,6 +133,8 @@ export function DynamicForm() {
134
133
// Track previous values to detect changes
135
134
const [ prevValues , setPrevValues ] = useState < Record < string , string > > ( { } ) ;
136
135
136
+ const [ debouncedTimer , setDebouncedTimer ] = useState < NodeJS . Timeout | null > ( null ) ;
137
+
137
138
useEffect ( ( ) => {
138
139
if ( ! response ) return ;
139
140
@@ -144,20 +145,36 @@ export function DynamicForm() {
144
145
key => watchedValues [ key ] !== prevValues [ key ]
145
146
) ;
146
147
if ( hasChanged ) {
147
- setCurrentId ( prevId => {
148
- const newId = prevId + 1 ;
149
- const request : Request = {
150
- id : newId ,
151
- inputs : watchedValues
152
- } ;
153
- console . log ( "request" , request ) ;
154
- sendMessage ( request ) ;
155
- return newId ;
156
- } ) ;
157
-
148
+ if ( debouncedTimer ) {
149
+ clearTimeout ( debouncedTimer ) ;
150
+ }
151
+
152
+ const timer = setTimeout ( ( ) => {
153
+ setCurrentId ( prevId => {
154
+ const newId = prevId + 1 ;
155
+ const request : Request = {
156
+ id : newId ,
157
+ inputs : watchedValues
158
+ } ;
159
+ console . log ( "request" , request ) ;
160
+ sendMessage ( request ) ;
161
+ return newId ;
162
+ } ) ;
163
+ } , 250 ) ;
164
+
165
+ setDebouncedTimer ( timer ) ;
158
166
setPrevValues ( { ...watchedValues } ) ;
159
167
}
160
- } , [ watchedValues , response , sendMessage , prevValues ] ) ;
168
+ } , [ watchedValues , response , sendMessage , prevValues , debouncedTimer ] ) ;
169
+
170
+ // Clean up the timer when component unmounts
171
+ useEffect ( ( ) => {
172
+ return ( ) => {
173
+ if ( debouncedTimer ) {
174
+ clearTimeout ( debouncedTimer ) ;
175
+ }
176
+ } ;
177
+ } , [ debouncedTimer ] ) ;
161
178
162
179
const renderParameter = ( param : Parameter ) => {
163
180
const controlType = param . form_type ;
@@ -177,7 +194,7 @@ export function DynamicForm() {
177
194
render = { ( { field } ) => (
178
195
< Select
179
196
onValueChange = { field . onChange }
180
- defaultValue = { param . value }
197
+ defaultValue = { param . default_value }
181
198
>
182
199
< SelectTrigger className = "w-[300px]" >
183
200
< SelectValue placeholder = { param . description } />
@@ -219,11 +236,18 @@ export function DynamicForm() {
219
236
const values = selectedOptions . map ( opt => opt . value ) . join ( ',' ) ;
220
237
field . onChange ( values ) ;
221
238
} }
222
- defaultOptions = { param . options ?. map ( opt => ( {
239
+ options = { param . options ?. map ( opt => ( {
223
240
value : opt ?. value || '' ,
224
241
label : opt ?. name || '' ,
225
242
disabled : false
226
243
} ) ) || [ ] }
244
+ // defaultOptions={param.default_value ?
245
+ // param.default_value.replace(/[[\]"]/g, '').split(',').map(value => ({
246
+ // value,
247
+ // label: param.options?.find(opt => opt?.value === value)?.name || value,
248
+ // disabled: false
249
+ // }))
250
+ // : [] }
227
251
emptyIndicator = { < p className = "text-sm" > No results found</ p > }
228
252
/>
229
253
</ div >
@@ -248,7 +272,7 @@ export function DynamicForm() {
248
272
control = { methods . control }
249
273
render = { ( { field } ) => (
250
274
< div className = "w-[300px]" >
251
- < Slider defaultValue = { field . value ? [ Number ( field . value ) ] : [ 0 ] } max = { param . validations [ 0 ] . validation_max || undefined } min = { param . validations [ 0 ] . validation_min || undefined } step = { 1 }
275
+ < Slider defaultValue = { param . default_value ? [ Number ( param . default_value ) ] : [ 0 ] } max = { param . validations [ 0 ] . validation_max || undefined } min = { param . validations [ 0 ] . validation_min || undefined } step = { 1 }
252
276
onValueChange = { ( value ) => {
253
277
console . log ( "value" , value [ 0 ] . toString ( ) ) ;
254
278
field . onChange ( value [ 0 ] . toString ( ) ) ;
@@ -258,6 +282,38 @@ export function DynamicForm() {
258
282
/>
259
283
</ div >
260
284
)
285
+ case "radio" :
286
+ return (
287
+ < div key = { param . name } className = "flex flex-col gap-2 items-center" >
288
+ < div className = "flex items-center justify-between gap-2" >
289
+ < label >
290
+ { param . display_name || param . name }
291
+ { param . icon && < img src = { param . icon } alt = "" style = { { marginLeft : 6 } } /> }
292
+ </ label >
293
+ < output className = "text-sm font-medium tabular-nums" > { param . value } </ output >
294
+ </ div >
295
+ { param . description && < div className = "text-sm" > { param . description } </ div > }
296
+ < Controller
297
+ name = { param . name }
298
+ control = { methods . control }
299
+ render = { ( { field } ) => (
300
+ < div className = "w-[300px]" >
301
+ < RadioGroup defaultValue = { param . default_value } onValueChange = { field . onChange } >
302
+ { ( param . options || [ ] ) . map ( ( option , idx ) => {
303
+ if ( ! option ) return null ;
304
+ return (
305
+ < div key = { idx } className = "flex items-center space-x-2" >
306
+ < RadioGroupItem value = { option . value } id = { option . value } />
307
+ < Label htmlFor = { option . value } > { option . name } </ Label >
308
+ </ div >
309
+ ) ;
310
+ } ) }
311
+ </ RadioGroup >
312
+ </ div >
313
+ ) }
314
+ />
315
+ </ div >
316
+ )
261
317
}
262
318
}
263
319
@@ -311,9 +367,13 @@ export function DynamicForm() {
311
367
name = { param . name }
312
368
control = { methods . control }
313
369
render = { ( { field } ) => (
314
- < DebouncedInput
315
- field = { field }
370
+ < Input
371
+ onChange = { ( e ) => {
372
+ field . onChange ( e ) ;
373
+ } }
374
+ className = "w-[300px]"
316
375
type = { mapParamTypeToInputType ( param . type ) }
376
+ value = { field . value }
317
377
defaultValue = { param . default_value }
318
378
/>
319
379
) }
@@ -336,26 +396,6 @@ export function DynamicForm() {
336
396
) ;
337
397
} ;
338
398
339
- const DebouncedInput = ( { field, type, defaultValue } : {
340
- field : { onChange : ( e : React . ChangeEvent < HTMLInputElement > ) => void } ,
341
- type : string ,
342
- defaultValue ?: string
343
- } ) => {
344
- const { debounced } = useDebouncedFunction (
345
- ( e : React . ChangeEvent < HTMLInputElement > ) => field . onChange ( e ) ,
346
- 2000
347
- ) ;
348
-
349
- return (
350
- < Input
351
- onChange = { debounced }
352
- className = "w-[300px]"
353
- type = { type }
354
- defaultValue = { defaultValue }
355
- />
356
- ) ;
357
- } ;
358
-
359
399
if ( isLoading && directories . length === 0 ) {
360
400
return < div > Loading directories...</ div > ;
361
401
}
0 commit comments