@@ -19,8 +19,10 @@ export class ManagerViewportPanels {
1919 public edgeClicked : boolean = false ;
2020 // Variables to store the current selection for dropdowns.
2121 private panelNodeEditorKind : string = "nokia_srlinux" ;
22+ private panelNodeEditorType : string = "" ;
23+ private panelNodeEditorUseDropdownForType : boolean = false ;
2224 private panelNodeEditorTopoViewerRole : string = "pe" ;
23-
25+ private nodeSchemaData : any = null ;
2426 /**
2527 * Creates an instance of ManagerViewportPanels.
2628 * @param viewportButtons - The ManagerViewportButtons instance.
@@ -125,6 +127,12 @@ export class ManagerViewportPanels {
125127 panelNodeEditorImageLabel . value = 'ghcr.io/nokia/srlinux:latest' ;
126128 }
127129
130+ // Set the node type in the editor.
131+ const extraData = node . data ( 'extraData' ) || { } ;
132+ this . panelNodeEditorKind = extraData . kind || this . panelNodeEditorKind ;
133+ this . panelNodeEditorType = extraData . type || '' ;
134+ this . panelNodeEditorUseDropdownForType = false ;
135+
128136 // Set the node group in the editor.
129137 const panelNodeEditorGroupLabel = document . getElementById ( "panel-node-editor-group" ) as HTMLInputElement ;
130138 if ( panelNodeEditorGroupLabel ) {
@@ -149,21 +157,24 @@ export class ManagerViewportPanels {
149157 }
150158 const jsonData = await response . json ( ) ;
151159
160+ this . nodeSchemaData = jsonData ;
161+
152162 // Get kind enums from the JSON schema.
153163 const { kindOptions } = this . panelNodeEditorGetKindEnums ( jsonData ) ;
154164 console . log ( 'Kind Enum:' , kindOptions ) ;
155165 // Populate the kind dropdown.
156166 this . panelNodeEditorPopulateKindDropdown ( kindOptions ) ;
157167
168+ const typeOptions = this . panelNodeEditorGetTypeEnumsByKindPattern ( jsonData , `(${ this . panelNodeEditorKind } )` ) ;
169+ this . panelNodeEditorSetupTypeField ( typeOptions ) ;
170+
158171 // Then call the function:
159172 const nodeIcons = extractNodeIcons ( ) ;
160173 console . log ( "Extracted node icons:" , nodeIcons ) ;
161174
162175 this . panelNodeEditorPopulateTopoViewerRoleDropdown ( nodeIcons ) ;
163176
164- // List type enums based on a kind pattern.
165- const typeOptions = this . panelNodeEditorGetTypeEnumsByKindPattern ( jsonData , '(srl|nokia_srlinux)' ) ;
166- console . log ( 'Type Enum for (srl|nokia_srlinux):' , typeOptions ) ;
177+
167178
168179 // Register the close button event.
169180 const panelNodeEditorCloseButton = document . getElementById ( "panel-node-editor-close-button" ) ;
@@ -214,7 +225,7 @@ export class ManagerViewportPanels {
214225 const panelLinkEditorIdLabelSaveBtn = document . getElementById ( "panel-link-editor-save-button" ) ;
215226
216227 // if (!panelLinkEditorIdLabel || !panelLinkEditor || !panelLinkEditorIdLabelSrcInput || !panelLinkEditorIdLabelTgtInput || !panelLinkEditorIdLabelCloseBtn || !panelLinkEditorIdLabelSaveBtn) {
217- if ( ! panelLinkEditorIdLabel || ! panelLinkEditor || ! panelLinkEditorIdLabelSrcInput || ! panelLinkEditorIdLabelTgtInput || ! panelLinkEditorIdLabelSaveBtn ) {
228+ if ( ! panelLinkEditorIdLabel || ! panelLinkEditor || ! panelLinkEditorIdLabelSrcInput || ! panelLinkEditorIdLabelTgtInput || ! panelLinkEditorIdLabelSaveBtn ) {
218229
219230 console . error ( "panelEdgeEditor: missing required DOM elements" ) ;
220231 return ;
@@ -314,6 +325,8 @@ export class ManagerViewportPanels {
314325 // Get the input values.
315326 const nodeNameInput = document . getElementById ( "panel-node-editor-name" ) as HTMLInputElement ;
316327 const nodeImageInput = document . getElementById ( "panel-node-editor-image" ) as HTMLInputElement ;
328+ const typeDropdownTrigger = document . querySelector ( "#panel-node-type-dropdown .dropdown-trigger button span" ) ;
329+ const typeInput = document . getElementById ( "panel-node-editor-type-input" ) as HTMLInputElement ;
317330
318331 // Retrieve dropdown selections.
319332 const kindDropdownTrigger = document . querySelector ( "#panel-node-kind-dropdown .dropdown-trigger button span" ) ;
@@ -325,13 +338,23 @@ export class ManagerViewportPanels {
325338 const newName = nodeNameInput . value ; // the new name
326339
327340 // Build updated extraData, preserving other fields.
341+ const typeValue = this . panelNodeEditorUseDropdownForType
342+ ? ( typeDropdownTrigger ? ( typeDropdownTrigger as HTMLElement ) . textContent || '' : '' )
343+ : ( typeInput ? typeInput . value : '' ) ;
344+
328345 const updatedExtraData = {
329346 ...currentData . extraData ,
330347 name : nodeNameInput . value ,
331348 image : nodeImageInput . value ,
332349 kind : kindDropdownTrigger ? kindDropdownTrigger . textContent : 'nokia_srlinux' ,
333350 } ;
334351
352+ if ( this . panelNodeEditorUseDropdownForType || typeValue . trim ( ) !== '' ) {
353+ updatedExtraData . type = typeValue ;
354+ } else if ( 'type' in updatedExtraData ) {
355+ delete updatedExtraData . type ;
356+ }
357+
335358 // Build the updated data object.
336359 const updatedData = {
337360 ...currentData ,
@@ -428,6 +451,73 @@ export class ManagerViewportPanels {
428451 console . log ( `${ this . panelNodeEditorKind } selected` ) ;
429452 dropdownTrigger . textContent = this . panelNodeEditorKind ;
430453 dropdownContainer . classList . remove ( "is-active" ) ;
454+ const typeOptions = this . panelNodeEditorGetTypeEnumsByKindPattern ( this . nodeSchemaData , `(${ option } )` ) ;
455+ // Reset the stored type when kind changes
456+ this . panelNodeEditorType = "" ;
457+ this . panelNodeEditorSetupTypeField ( typeOptions ) ;
458+ } ) ;
459+
460+ dropdownContent . appendChild ( optionElement ) ;
461+ } ) ;
462+ }
463+
464+ private panelNodeEditorSetupTypeField ( options : string [ ] ) : void {
465+ const dropdown = document . getElementById ( "panel-node-type-dropdown" ) ;
466+ const input = document . getElementById ( "panel-node-editor-type-input" ) as HTMLInputElement ;
467+
468+ if ( ! dropdown || ! input ) {
469+ console . error ( "Type input elements not found in the DOM." ) ;
470+ return ;
471+ }
472+
473+ if ( options . length > 0 ) {
474+ dropdown . style . display = "" ;
475+ input . style . display = "none" ;
476+ this . panelNodeEditorUseDropdownForType = true ;
477+ // Ensure type matches available options
478+ if ( ! options . includes ( this . panelNodeEditorType ) ) {
479+ this . panelNodeEditorType = options [ 0 ] ;
480+ }
481+ this . panelNodeEditorPopulateTypeDropdown ( options ) ;
482+ } else {
483+ dropdown . style . display = "none" ;
484+ input . style . display = "" ;
485+ this . panelNodeEditorUseDropdownForType = false ;
486+ input . value = this . panelNodeEditorType || "" ;
487+ input . oninput = ( ) => {
488+ this . panelNodeEditorType = input . value ;
489+ } ;
490+ }
491+ }
492+
493+ private panelNodeEditorPopulateTypeDropdown ( options : string [ ] ) : void {
494+ const dropdownTrigger = document . querySelector ( "#panel-node-type-dropdown .dropdown-trigger button span" ) ;
495+ const dropdownContent = document . getElementById ( "panel-node-type-dropdown-content" ) ;
496+ const dropdownButton = document . querySelector ( "#panel-node-type-dropdown .dropdown-trigger button" ) ;
497+ const dropdownContainer = dropdownButton ? dropdownButton . closest ( ".dropdown" ) : null ;
498+
499+ if ( ! dropdownTrigger || ! dropdownContent || ! dropdownButton || ! dropdownContainer ) {
500+ console . error ( "Dropdown elements not found in the DOM." ) ;
501+ return ;
502+ }
503+
504+ if ( ! options . includes ( this . panelNodeEditorType ) ) {
505+ this . panelNodeEditorType = options . length > 0 ? options [ 0 ] : "" ;
506+ }
507+ dropdownTrigger . textContent = this . panelNodeEditorType || "" ;
508+ dropdownContent . innerHTML = "" ;
509+
510+ options . forEach ( option => {
511+ const optionElement = document . createElement ( "a" ) ;
512+ optionElement . classList . add ( "dropdown-item" , "label" , "has-text-weight-normal" , "is-small" , "py-0" ) ;
513+ optionElement . textContent = option ;
514+ optionElement . href = "#" ;
515+
516+ optionElement . addEventListener ( "click" , ( event ) => {
517+ event . preventDefault ( ) ;
518+ this . panelNodeEditorType = option ;
519+ dropdownTrigger . textContent = this . panelNodeEditorType ;
520+ dropdownContainer . classList . remove ( "is-active" ) ;
431521 } ) ;
432522
433523 dropdownContent . appendChild ( optionElement ) ;
@@ -525,13 +615,18 @@ export class ManagerViewportPanels {
525615 condition . if . properties . kind &&
526616 condition . if . properties . kind . pattern === pattern
527617 ) {
528- if (
529- condition . then &&
530- condition . then . properties &&
531- condition . then . properties . type &&
532- condition . then . properties . type . enum
533- ) {
534- return condition . then . properties . type . enum ;
618+ if ( condition . then && condition . then . properties && condition . then . properties . type ) {
619+ const typeProp = condition . then . properties . type ;
620+ if ( typeProp . enum ) {
621+ return typeProp . enum ;
622+ }
623+ if ( Array . isArray ( typeProp . anyOf ) ) {
624+ for ( const sub of typeProp . anyOf ) {
625+ if ( sub . enum ) {
626+ return sub . enum ;
627+ }
628+ }
629+ }
535630 }
536631 }
537632 }
0 commit comments