@@ -67,6 +67,7 @@ norn_config.initialize = function (callback) {
6767 fcSelect . append ( `<option value="GEPRCF722">GEPRCF722</option>` ) ;
6868 fcSelect . on ( "change" , function ( ) {
6969 self . analyticsChanges [ "NornFC" ] = $ ( this ) . val ( ) || null ;
70+ clearMandatoryFieldValidation ( ) ;
7071 } ) ;
7172 }
7273
@@ -95,6 +96,7 @@ norn_config.initialize = function (callback) {
9596 manticoreSelect . append ( `<option value="GPIO">GPIO</option>` ) ;
9697 manticoreSelect . on ( "change" , function ( ) {
9798 self . analyticsChanges [ "NornManticore" ] = $ ( this ) . val ( ) || null ;
99+ clearMandatoryFieldValidation ( ) ;
98100 } ) ;
99101 }
100102
@@ -108,6 +110,7 @@ norn_config.initialize = function (callback) {
108110 vtxSelect . append ( `<option value="OPTICA">Optica</option>` ) ;
109111 vtxSelect . on ( "change" , function ( ) {
110112 self . analyticsChanges [ "NornVtx" ] = $ ( this ) . val ( ) || null ;
113+ clearMandatoryFieldValidation ( ) ;
111114 } ) ;
112115 }
113116
@@ -146,6 +149,7 @@ norn_config.initialize = function (callback) {
146149 controllerSelect . append ( `<option value="TX12">TX12</option>` ) ;
147150 controllerSelect . on ( "change" , function ( ) {
148151 self . analyticsChanges [ "NornController" ] = $ ( this ) . val ( ) || null ;
152+ clearMandatoryFieldValidation ( ) ;
149153 } ) ;
150154 }
151155
@@ -201,9 +205,58 @@ norn_config.initialize = function (callback) {
201205 return { fcKey, droneSize, manticoreKey, vtxKey, gpsEnabled, craftName, mbId, controller, failSafe } ;
202206 }
203207
208+ function updateMandatoryFieldValidation ( ) {
209+ // Clear previous validation
210+ clearMandatoryFieldValidation ( ) ;
211+
212+ // Check mandatory fields and highlight missing ones
213+ const mandatoryFields = [
214+ { selector : "select[name='norn_fc']" , label : "Flight Controller" } ,
215+ { selector : "select[name='norn_manticore']" , label : "Manticore" } ,
216+ { selector : "select[name='norn_vtx']" , label : "VTX" } ,
217+ { selector : "select[name='norn_controller']" , label : "Radio Controller" } ,
218+ ] ;
219+
220+ mandatoryFields . forEach ( ( field ) => {
221+ const element = $ ( field . selector ) ;
222+ if ( ! element . val ( ) ) {
223+ element . closest ( ".gui_box" ) . addClass ( "mandatory-missing" ) ;
224+ element . addClass ( "mandatory-missing" ) ;
225+ }
226+ } ) ;
227+ }
228+
229+ function clearMandatoryFieldValidation ( ) {
230+ // Remove validation highlighting
231+ $ ( ".gui_box" ) . removeClass ( "mandatory-missing" ) ;
232+ $ ( "select, input" ) . removeClass ( "mandatory-missing" ) ;
233+ }
234+
204235 function on_generate_handler ( e ) {
205236 e ?. preventDefault ?. ( ) ;
206237
238+ // Validate mandatory fields
239+ const fcKey = $ ( "select[name='norn_fc']" ) . val ( ) ;
240+ const manticoreKey = $ ( "select[name='norn_manticore']" ) . val ( ) ;
241+ const vtxKey = $ ( "select[name='norn_vtx']" ) . val ( ) ;
242+ const controller = $ ( "select[name='norn_controller']" ) . val ( ) ;
243+
244+ const missingFields = [ ] ;
245+ if ( ! fcKey ) missingFields . push ( "Flight Controller" ) ;
246+ if ( ! manticoreKey ) missingFields . push ( "Manticore" ) ;
247+ if ( ! vtxKey ) missingFields . push ( "VTX" ) ;
248+ if ( ! controller ) missingFields . push ( "Radio Controller" ) ;
249+
250+ if ( missingFields . length > 0 ) {
251+ // Highlight missing mandatory fields
252+ updateMandatoryFieldValidation ( ) ;
253+ alert ( `Please select the following mandatory fields:\n${ missingFields . join ( ", " ) } ` ) ;
254+ return ;
255+ }
256+
257+ // Clear any validation highlighting
258+ clearMandatoryFieldValidation ( ) ;
259+
207260 const templatePath = Object . keys ( templateFiles ) [ 0 ] ;
208261 let result ;
209262 if ( templatePath ) {
0 commit comments