@@ -7,78 +7,158 @@ import {
77 Button ,
88 ToggleButton ,
99 ToggleButtonGroup ,
10+ TextField ,
11+ Box ,
12+ Typography ,
1013} from "@mui/material" ;
1114import Editor from "@monaco-editor/react" ;
1215import yaml from "js-yaml" ;
1316
17+ const RenderFields = ( { data, onChange, path = [ ] } ) => {
18+ return Object . entries ( data || { } ) . map ( ( [ key , value ] ) => {
19+ // Skip internal Kubernetes metadata
20+ if ( key === "managedFields" || key . startsWith ( "f:" ) ) {
21+ return null ;
22+ }
23+
24+ const currentPath = [ ...path , key ] ;
25+
26+ if ( Array . isArray ( value ) ) {
27+ return (
28+ < Box key = { currentPath . join ( "." ) } sx = { { mb : 2 , pl : 2 , borderLeft : "2px solid #ccc" } } >
29+ < Typography variant = "subtitle2" > { key } (Array)</ Typography >
30+ { value . map ( ( item , index ) => {
31+ const itemPath = [ ...currentPath , index ] ;
32+ if ( typeof item === "object" && item !== null ) {
33+ return (
34+ < Box key = { itemPath . join ( "." ) } sx = { { pl : 2 , mb : 1 , borderLeft : "1px dashed #999" } } >
35+ < Typography variant = "caption" > Item { index } </ Typography >
36+ < RenderFields data = { item } onChange = { onChange } path = { itemPath } />
37+ </ Box >
38+ ) ;
39+ } else {
40+ return (
41+ < TextField
42+ key = { itemPath . join ( "." ) }
43+ label = { `${ key } [${ index } ]` }
44+ value = { item }
45+ fullWidth
46+ margin = "dense"
47+ onChange = { ( e ) => onChange ( itemPath , e . target . value ) }
48+ />
49+ ) ;
50+ }
51+ } ) }
52+ </ Box >
53+ ) ;
54+ }
55+
56+ if ( typeof value === "object" && value !== null ) {
57+ return (
58+ < Box key = { currentPath . join ( "." ) } sx = { { mb : 2 , pl : 2 , borderLeft : "2px solid #ccc" } } >
59+ < Typography variant = "subtitle2" > { key } </ Typography >
60+ < RenderFields data = { value } onChange = { onChange } path = { currentPath } />
61+ </ Box >
62+ ) ;
63+ }
64+
65+ return (
66+ < TextField
67+ key = { currentPath . join ( "." ) }
68+ label = { currentPath . join ( "." ) }
69+ value = { value }
70+ fullWidth
71+ margin = "dense"
72+ onChange = { ( e ) => onChange ( currentPath , e . target . value ) }
73+ />
74+ ) ;
75+ } ) ;
76+ } ;
77+
78+
79+ const updateNestedValue = ( obj , path , value ) => {
80+ const lastKey = path . pop ( ) ;
81+ const nested = path . reduce ( ( acc , key ) => ( acc [ key ] = acc [ key ] || { } ) , obj ) ;
82+ nested [ lastKey ] = value ;
83+ return { ...obj } ;
84+ } ;
85+
1486const EditQueueDialog = ( { open, queue, onClose, onSave } ) => {
1587 const [ editorValue , setEditorValue ] = useState ( "" ) ;
1688 const [ editMode , setEditMode ] = useState ( "yaml" ) ;
89+ const [ formState , setFormState ] = useState ( { } ) ;
1790
1891 useEffect ( ( ) => {
1992 if ( open && queue ) {
20- const content = yaml . dump ( queue ) ; // Always YAML
21- setEditorValue ( content ) ;
93+ const yamlContent = yaml . dump ( queue ) ;
94+ setEditorValue ( yamlContent ) ;
95+ setFormState ( queue ) ;
96+ setEditMode ( "yaml" ) ;
2297 }
2398 } , [ open , queue ] ) ;
2499
25100 const handleModeChange = ( event , newMode ) => {
26- if ( newMode !== null ) {
27- setEditMode ( newMode ) ; // Only for syntax highlighting
101+ if ( ! newMode ) return ;
102+ if ( newMode === "form" ) {
103+ try {
104+ const parsed = yaml . load ( editorValue ) ;
105+ setFormState ( parsed || { } ) ;
106+ setEditMode ( "form" ) ;
107+ } catch ( err ) {
108+ alert ( "Invalid YAML. Cannot switch to Form view." ) ;
109+ }
110+ } else if ( newMode === "yaml" ) {
111+ setEditorValue ( yaml . dump ( formState ) ) ;
112+ setEditMode ( "yaml" ) ;
28113 }
29114 } ;
30115
116+ const handleNestedChange = ( path , value ) => {
117+ setFormState ( ( prev ) => updateNestedValue ( { ...prev } , [ ...path ] , value ) ) ;
118+ } ;
119+
31120 const handleSave = ( ) => {
32121 try {
33- const updatedQueue = yaml . load ( editorValue ) ; // Always parse as YAML
34- onSave ( updatedQueue ) ;
122+ const updated = editMode === " yaml" ? yaml . load ( editorValue ) : formState ;
123+ onSave ( updated ) ;
35124 onClose ( ) ;
36125 } catch ( error ) {
37- console . error ( "Error parsing edited content :" , error ) ;
38- alert ( "Invalid YAML format. Please check your input. " ) ;
126+ console . error ( "Invalid YAML :" , error ) ;
127+ alert ( "Invalid YAML format." ) ;
39128 }
40129 } ;
41130
42131 return (
43132 < Dialog open = { open } onClose = { onClose } maxWidth = "md" fullWidth >
44- < DialogTitle
45- sx = { {
46- display : "flex" ,
47- justifyContent : "space-between" ,
48- alignItems : "center" ,
49- } }
50- >
133+ < DialogTitle sx = { { display : "flex" , justifyContent : "space-between" , alignItems : "center" } } >
51134 Edit Queue
52- < ToggleButtonGroup
53- value = { editMode }
54- exclusive
55- onChange = { handleModeChange }
56- color = "primary"
57- >
135+ < ToggleButtonGroup value = { editMode } exclusive onChange = { handleModeChange } >
58136 < ToggleButton value = "yaml" > YAML</ ToggleButton >
137+ < ToggleButton value = "form" > Form</ ToggleButton >
59138 </ ToggleButtonGroup >
60139 </ DialogTitle >
61- < DialogContent sx = { { height : "500px" } } >
62- < Editor
63- height = "100%"
64- language = { editMode } // only affects syntax highlighting
65- value = { editorValue }
66- onChange = { ( value ) => setEditorValue ( value || "" ) }
67- options = { {
68- minimap : { enabled : false } ,
69- automaticLayout : true ,
70- } }
71- />
140+
141+ < DialogContent sx = { { height : 500 } } >
142+ { editMode === "yaml" ? (
143+ < Editor
144+ height = "100%"
145+ language = "yaml"
146+ value = { editorValue }
147+ onChange = { ( v ) => setEditorValue ( v || "" ) }
148+ options = { { minimap : { enabled : false } , automaticLayout : true } }
149+ />
150+ ) : (
151+ < Box sx = { { mt : 2 } } >
152+ < RenderFields data = { formState } onChange = { handleNestedChange } />
153+ </ Box >
154+ ) }
72155 </ DialogContent >
156+
73157 < DialogActions >
74158 < Button onClick = { onClose } color = "primary" variant = "contained" >
75159 Cancel
76160 </ Button >
77- < Button
78- onClick = { handleSave }
79- color = "primary"
80- variant = "contained"
81- >
161+ < Button onClick = { handleSave } color = "primary" variant = "contained" >
82162 Update
83163 </ Button >
84164 </ DialogActions >
0 commit comments