@@ -31,6 +31,15 @@ $(document).ready(function () {
3131 requestWriteConfig ( conf_editor . getValue ( ) ) ;
3232 } ) ;
3333
34+ createTable ( 'ithead' , 'itbody' , 'itable' ) ;
35+
36+ // Initialize the table header
37+ if ( $ ( '#ithead' ) . length === 0 ) {
38+ $ ( '.ithead' ) . html ( createTableRow ( [ $ . i18n ( 'conf_general_inst_namehead' ) , "" , $ . i18n ( 'conf_general_inst_actionhead' ) , "" ] , true , true ) ) ;
39+ }
40+
41+ buildInstanceList ( ) ;
42+
3443 // Instance handling functions
3544 function handleInstanceRename ( instance ) {
3645 showInfoDialog ( 'renInst' , $ . i18n ( 'conf_general_inst_renreq_t' ) , getInstanceName ( instance ) ) ;
@@ -59,81 +68,75 @@ $(document).ready(function () {
5968 // Build the instance list
6069 function buildInstanceList ( ) {
6170
62- const instances = serverInfo . instance ;
63-
64- // Ensure .itbody exists and clear it
6571 const $itbody = $ ( '.itbody' ) ;
6672 if ( $itbody . length === 0 ) {
6773 console . warn ( "Element '.itbody' does not exist. Aborting instance list build." ) ;
6874 return ;
6975 }
70- $itbody . empty ( ) ; // Explicitly clear the content before adding new rows
7176
72- // Collect rows in a document fragment for efficient DOM updates
73- const $rows = $ ( document . createDocumentFragment ( ) ) ;
77+ const data = window . serverInfo . instance ;
78+ if ( data ) {
79+ const instances = Object . values ( data ) ;
80+
81+ // Sort instances by friendly_name (case-insensitive)
82+ instances . sort ( ( a , b ) => a . friendly_name . toLowerCase ( ) . localeCompare ( b . friendly_name . toLowerCase ( ) ) ) ;
83+
84+ $itbody . empty ( ) ; // Explicitly clear the content before adding new rows
85+
86+ // Collect rows in a document fragment for efficient DOM updates
87+ const $rows = $ ( document . createDocumentFragment ( ) ) ;
7488
75- for ( const instance in instances ) {
76- const instanceID = instances [ instance ] . instance ;
77- const enableStyle = instances [ instance ] . running ? "checked" : "" ;
78- const renameBtn = `<button id="instren_${ instanceID } " type="button" class="btn btn-primary">
89+ // Build all instance rows
90+ for ( const instance of instances ) {
91+ const instanceID = instance . instance ;
92+ const enableStyle = instance . running ? "checked" : "" ;
93+ const renameBtn = `<button id="instren_${ instanceID } " type="button" class="btn btn-primary">
7994 <i class="mdi mdi-lead-pencil"></i>
8095 </button>` ;
81- const delBtn = `<button id="instdel_${ instanceID } " type="button" class="btn btn-danger">
96+ const delBtn = `<button id="instdel_${ instanceID } " type="button" class="btn btn-danger">
8297 <i class="mdi mdi-delete-forever"></i>
8398 </button>` ;
84- const startBtn = `<input id="inst_${ instanceID } " ${ enableStyle } type="checkbox"
99+ const startBtn = `<input id="inst_${ instanceID } " ${ enableStyle } type="checkbox"
100+ class="toggle-instance"
85101 data-toggle="toggle" data-onstyle="success font-weight-bold"
86102 data-on="${ $ . i18n ( 'general_btn_on' ) } " data-offstyle="default font-weight-bold"
87103 data-off="${ $ . i18n ( 'general_btn_off' ) } ">` ;
88104
89- // Generate a table row and add it to the document fragment
90- const $row = createTableRow (
91- [
92- instances [ instance ] . friendly_name ,
93- startBtn ,
94- renameBtn ,
95- delBtn
96- ] ,
97- false ,
98- true
99- ) ;
100-
101- $rows . append ( $row ) ;
102- }
103-
104- // Append all rows to .itbody in one operation
105- $itbody . append ( $rows ) ;
106-
107- // Reapply event listeners
108- for ( const instance in instances ) {
109- const instanceID = instances [ instance ] . instance ;
110-
111- const readOnly = window . readOnlyMode ;
112- $ ( '#instren_' + instanceID ) . prop ( 'disabled' , readOnly ) ;
113- $ ( '#inst_' + instanceID ) . prop ( 'disabled' , readOnly ) ;
114- $ ( '#instdel_' + instanceID ) . prop ( 'disabled' , readOnly ) ;
115-
116- $ ( '#instren_' + instanceID ) . off ( ) . on ( 'click' , function ( ) {
117- handleInstanceRename ( instanceID ) ;
118- } ) ;
119-
120- $ ( '#instdel_' + instanceID ) . off ( ) . on ( 'click' , function ( ) {
121- handleInstanceDelete ( instanceID ) ;
122- } ) ;
123-
124- $ ( '#inst_' + instanceID ) . bootstrapToggle ( ) ;
125- $ ( '#inst_' + instanceID ) . change ( function ( ) {
126- const isChecked = $ ( this ) . prop ( 'checked' ) ;
127- requestInstanceStartStop ( instanceID , isChecked ) ;
128- } ) ;
105+ const $row = createTableRow (
106+ [ instance . friendly_name , startBtn , renameBtn , delBtn ] ,
107+ false ,
108+ true
109+ ) ;
110+
111+ $rows . append ( $row ) ;
112+ }
113+
114+ $itbody . append ( $rows ) ;
115+
116+ // Apply Bootstrap toggles and event handlers
117+ for ( const instance of instances ) {
118+ const instanceID = instance . instance ;
119+ const readOnly = window . readOnlyMode ;
120+
121+ $ ( '#instren_' + instanceID ) . prop ( 'disabled' , readOnly ) . off ( ) . on ( 'click' , function ( ) {
122+ handleInstanceRename ( instanceID ) ;
123+ } ) ;
124+
125+ $ ( '#instdel_' + instanceID ) . prop ( 'disabled' , readOnly ) . off ( ) . on ( 'click' , function ( ) {
126+ handleInstanceDelete ( instanceID ) ;
127+ } ) ;
128+
129+ const $toggle = $ ( '#inst_' + instanceID ) ;
130+ $toggle . prop ( 'disabled' , readOnly ) ;
131+ $toggle . bootstrapToggle ( ) ; // Reapply toggle
132+ $toggle . off ( 'change' ) . on ( 'change' , function ( ) {
133+ const isChecked = $ ( this ) . prop ( 'checked' ) ;
134+ requestInstanceStartStop ( instanceID , isChecked ) ;
135+ } ) ;
136+ }
129137 }
130138 }
131139
132- // Initialize table
133- createTable ( 'ithead' , 'itbody' , 'itable' ) ;
134- $ ( '.ithead' ) . html ( createTableRow ( [ $ . i18n ( 'conf_general_inst_namehead' ) , "" , $ . i18n ( 'conf_general_inst_actionhead' ) , "" ] , true , true ) ) ;
135- buildInstanceList ( ) ;
136-
137140 // Instance name input validation
138141 $ ( '#inst_name' ) . off ( ) . on ( 'input' , function ( e ) {
139142 const isValid = e . currentTarget . value . length >= 5 && ! window . readOnlyMode ;
0 commit comments