11import { shallow } from "zustand/shallow" ;
22import useStore , { RFState } from "./store" ;
33import { useCallback , useState } from "react" ;
4- import { DataType } from "./memory" ;
4+ import { DataType , primitveDataTypes } from "./memory" ;
55
66const selector = ( state : RFState ) => ( {
77 updateMemory : state . updateMemory ,
@@ -14,6 +14,21 @@ export const ConfigView = () => {
1414
1515 const [ klasses , setKlasses ] = useState ( memory . klasses ) ;
1616 const [ options , setOptions ] = useState ( memory . options ) ;
17+ const [ addingAttribute , setAddingAttribute ] = useState < string | null > ( null ) ;
18+ const [ editingAttribute , setEditingAttribute ] = useState < {
19+ klassName : string ;
20+ attrName : string ;
21+ currentDataType : DataType ;
22+ } | null > ( null ) ;
23+ const [ newAttrName , setNewAttrName ] = useState ( "" ) ;
24+ const [ newAttrType , setNewAttrType ] = useState < DataType > ( "String" ) ;
25+
26+ // Get available data types: primitives + Array + defined classes
27+ const availableDataTypes = [
28+ ...primitveDataTypes ,
29+ "Array" ,
30+ ...Object . keys ( klasses ) ,
31+ ] ;
1732
1833 const onSave = useCallback ( ( ) => {
1934 updateMemory ( {
@@ -27,10 +42,6 @@ export const ConfigView = () => {
2742 setRoute ( "view" ) ;
2843 } , [ setRoute ] ) ;
2944
30- const onEdit = useCallback ( ( ) => {
31- setRoute ( "edit" ) ;
32- } , [ setRoute ] ) ;
33-
3445 const handleOptionChange = useCallback (
3546 ( key : string , value : boolean ) => {
3647 setOptions ( ( prev ) => ( {
@@ -64,24 +75,33 @@ export const ConfigView = () => {
6475 } , [ ] ) ;
6576
6677 const handleAddAttribute = useCallback ( ( klassName : string ) => {
67- const attrName = window . prompt ( "Enter attribute name:" ) ;
68- if ( attrName && attrName . trim ( ) ) {
69- const dataType = window . prompt (
70- `Enter data type for " ${ attrName } " (e.g., String, int, boolean, or custom class name):`
71- ) ;
72- if ( dataType && dataType . trim ( ) ) {
73- setKlasses ( ( prev ) => ( {
74- ... prev ,
75- [ klassName ] : {
76- ... prev [ klassName ] ,
77- attributes : {
78- ... prev [ klassName ] . attributes ,
79- [ attrName . trim ( ) ] : dataType . trim ( ) as DataType ,
80- } ,
78+ setAddingAttribute ( klassName ) ;
79+ setNewAttrName ( "" ) ;
80+ setNewAttrType ( "String" ) ;
81+ } , [ ] ) ;
82+
83+ const handleConfirmAddAttribute = useCallback ( ( ) => {
84+ if ( addingAttribute && newAttrName . trim ( ) ) {
85+ setKlasses ( ( prev ) => ( {
86+ ... prev ,
87+ [ addingAttribute ] : {
88+ ... prev [ addingAttribute ] ,
89+ attributes : {
90+ ... prev [ addingAttribute ] . attributes ,
91+ [ newAttrName . trim ( ) ] : newAttrType ,
8192 } ,
82- } ) ) ;
83- }
93+ } ,
94+ } ) ) ;
95+ setAddingAttribute ( null ) ;
96+ setNewAttrName ( "" ) ;
97+ setNewAttrType ( "String" ) ;
8498 }
99+ } , [ addingAttribute , newAttrName , newAttrType ] ) ;
100+
101+ const handleCancelAddAttribute = useCallback ( ( ) => {
102+ setAddingAttribute ( null ) ;
103+ setNewAttrName ( "" ) ;
104+ setNewAttrType ( "String" ) ;
85105 } , [ ] ) ;
86106
87107 const handleRemoveAttribute = useCallback (
@@ -108,34 +128,41 @@ export const ConfigView = () => {
108128
109129 const handleEditAttribute = useCallback (
110130 ( klassName : string , attrName : string , currentDataType : DataType ) => {
111- const newDataType = window . prompt (
112- `Edit data type for "${ attrName } " (current: ${ currentDataType } ):` ,
113- currentDataType
114- ) ;
115- if ( newDataType && newDataType . trim ( ) ) {
116- setKlasses ( ( prev ) => ( {
117- ...prev ,
118- [ klassName ] : {
119- ...prev [ klassName ] ,
120- attributes : {
121- ...prev [ klassName ] . attributes ,
122- [ attrName ] : newDataType . trim ( ) as DataType ,
123- } ,
124- } ,
125- } ) ) ;
126- }
131+ setEditingAttribute ( { klassName, attrName, currentDataType } ) ;
132+ setNewAttrType ( currentDataType ) ;
127133 } ,
128134 [ ]
129135 ) ;
130136
137+ const handleConfirmEditAttribute = useCallback ( ( ) => {
138+ if ( editingAttribute ) {
139+ setKlasses ( ( prev ) => ( {
140+ ...prev ,
141+ [ editingAttribute . klassName ] : {
142+ ...prev [ editingAttribute . klassName ] ,
143+ attributes : {
144+ ...prev [ editingAttribute . klassName ] . attributes ,
145+ [ editingAttribute . attrName ] : newAttrType ,
146+ } ,
147+ } ,
148+ } ) ) ;
149+ setEditingAttribute ( null ) ;
150+ setNewAttrType ( "String" ) ;
151+ }
152+ } , [ editingAttribute , newAttrType ] ) ;
153+
154+ const handleCancelEditAttribute = useCallback ( ( ) => {
155+ setEditingAttribute ( null ) ;
156+ setNewAttrType ( "String" ) ;
157+ } , [ ] ) ;
158+
131159 return (
132160 < div style = { { padding : "20px" , maxWidth : "1200px" , margin : "0 auto" } } >
133161 < h1 > Configuration</ h1 >
134162
135163 < div className = "button-group" >
136164 < button onClick = { onSave } > Save</ button >
137165 < button onClick = { onView } > View</ button >
138- < button onClick = { onEdit } > Edit JSON</ button >
139166 </ div >
140167
141168 < div style = { { marginTop : "20px" } } >
@@ -317,6 +344,144 @@ export const ConfigView = () => {
317344 ) ) }
318345 </ div >
319346 </ div >
347+
348+ { /* Add Attribute Modal */ }
349+ { addingAttribute && (
350+ < div
351+ style = { {
352+ position : "fixed" ,
353+ top : 0 ,
354+ left : 0 ,
355+ right : 0 ,
356+ bottom : 0 ,
357+ backgroundColor : "rgba(0, 0, 0, 0.5)" ,
358+ display : "flex" ,
359+ alignItems : "center" ,
360+ justifyContent : "center" ,
361+ zIndex : 1000 ,
362+ } }
363+ onClick = { handleCancelAddAttribute }
364+ >
365+ < div
366+ style = { {
367+ backgroundColor : "white" ,
368+ padding : "20px" ,
369+ borderRadius : "8px" ,
370+ minWidth : "400px" ,
371+ } }
372+ onClick = { ( e ) => e . stopPropagation ( ) }
373+ >
374+ < h3 > Add Attribute to { addingAttribute } </ h3 >
375+ < div style = { { marginTop : "15px" } } >
376+ < label style = { { display : "block" , marginBottom : "5px" } } >
377+ Attribute Name:
378+ </ label >
379+ < input
380+ type = "text"
381+ value = { newAttrName }
382+ onChange = { ( e ) => setNewAttrName ( e . target . value ) }
383+ style = { {
384+ width : "100%" ,
385+ padding : "8px" ,
386+ borderRadius : "4px" ,
387+ border : "1px solid #ccc" ,
388+ } }
389+ placeholder = "Enter attribute name"
390+ autoFocus
391+ />
392+ </ div >
393+ < div style = { { marginTop : "15px" } } >
394+ < label style = { { display : "block" , marginBottom : "5px" } } >
395+ Data Type:
396+ </ label >
397+ < select
398+ value = { newAttrType }
399+ onChange = { ( e ) => setNewAttrType ( e . target . value as DataType ) }
400+ style = { {
401+ width : "100%" ,
402+ padding : "8px" ,
403+ borderRadius : "4px" ,
404+ border : "1px solid #ccc" ,
405+ } }
406+ >
407+ { availableDataTypes . map ( ( type ) => (
408+ < option key = { type } value = { type } >
409+ { type }
410+ </ option >
411+ ) ) }
412+ </ select >
413+ </ div >
414+ < div
415+ className = "button-group"
416+ style = { { marginTop : "20px" , display : "flex" , gap : "8px" } }
417+ >
418+ < button onClick = { handleConfirmAddAttribute } > Add</ button >
419+ < button onClick = { handleCancelAddAttribute } > Cancel</ button >
420+ </ div >
421+ </ div >
422+ </ div >
423+ ) }
424+
425+ { /* Edit Attribute Modal */ }
426+ { editingAttribute && (
427+ < div
428+ style = { {
429+ position : "fixed" ,
430+ top : 0 ,
431+ left : 0 ,
432+ right : 0 ,
433+ bottom : 0 ,
434+ backgroundColor : "rgba(0, 0, 0, 0.5)" ,
435+ display : "flex" ,
436+ alignItems : "center" ,
437+ justifyContent : "center" ,
438+ zIndex : 1000 ,
439+ } }
440+ onClick = { handleCancelEditAttribute }
441+ >
442+ < div
443+ style = { {
444+ backgroundColor : "white" ,
445+ padding : "20px" ,
446+ borderRadius : "8px" ,
447+ minWidth : "400px" ,
448+ } }
449+ onClick = { ( e ) => e . stopPropagation ( ) }
450+ >
451+ < h3 >
452+ Edit Attribute: { editingAttribute . attrName }
453+ </ h3 >
454+ < div style = { { marginTop : "15px" } } >
455+ < label style = { { display : "block" , marginBottom : "5px" } } >
456+ Data Type:
457+ </ label >
458+ < select
459+ value = { newAttrType }
460+ onChange = { ( e ) => setNewAttrType ( e . target . value as DataType ) }
461+ style = { {
462+ width : "100%" ,
463+ padding : "8px" ,
464+ borderRadius : "4px" ,
465+ border : "1px solid #ccc" ,
466+ } }
467+ >
468+ { availableDataTypes . map ( ( type ) => (
469+ < option key = { type } value = { type } >
470+ { type }
471+ </ option >
472+ ) ) }
473+ </ select >
474+ </ div >
475+ < div
476+ className = "button-group"
477+ style = { { marginTop : "20px" , display : "flex" , gap : "8px" } }
478+ >
479+ < button onClick = { handleConfirmEditAttribute } > Save</ button >
480+ < button onClick = { handleCancelEditAttribute } > Cancel</ button >
481+ </ div >
482+ </ div >
483+ </ div >
484+ ) }
320485 </ div >
321486 ) ;
322487} ;
0 commit comments