2929<script language =" JavaScript" type =" text/javascript" >
3030
3131/* *----------------------------**/
32- /* * Last Modified: 2025-Mar-10 **/
32+ /* * Last Modified: 2025-Mar-29 **/
3333/* * Intended for 1.4.x Release **/
3434/* *----------------------------**/
3535
@@ -796,41 +796,42 @@ const fwUpdateDirPath =
796796 }
797797};
798798
799- function fetchChangelog (startTime ) {
799+ function FetchChangelog (startTime )
800+ {
800801 $ .ajax ({
801802 url: ' /ext/MerlinAU/changelog.htm' ,
802803 dataType: ' text' ,
803- timeout: 1500 , // each attempt times out after 9 seconds
804- success : function (data ) {
804+ timeout: 1500 , // each attempt times out after 9 seconds //
805+ success : function (data )
806+ {
805807 $ (' #changelogData' ).html (' <pre>' + data + ' </pre>' );
806808 },
807- error : function () {
809+ error : function ()
810+ {
808811 var currentTime = new Date ().getTime ();
809- // if less than 10 seconds have elapsed since we started, retry after 500ms
810- if (currentTime - startTime < 10000 ) {
811- setTimeout (function () {
812- fetchChangelog (startTime);
813- }, 500 );
814- } else {
815- $ (' #changelogData' ).html (' <p>Failed to load the changelog.</p>' );
816- }
812+ // if less than 10 sec. have elapsed since we started, retry after 500ms //
813+ if (currentTime - startTime < 10000 )
814+ { setTimeout (function () { FetchChangelog (startTime); }, 500 ); }
815+ else
816+ { $ (' #changelogData' ).html (' <p>Failed to load the changelog.</p>' ); }
817817 }
818818 });
819819}
820820
821- function ShowLatestChangelog (e ) {
821+ function ShowLatestChangelog (e )
822+ {
822823 if (e) e .preventDefault ();
823824
824- // Define the loading message
825- var loadingMessage = ' <p>Please wait and allow up to 10 seconds for the changelog to load.<br>' +
825+ let loadingMessage = ' <p>Please wait and allow up to 10 seconds for the changelog to load.<br>' +
826826 ' Click on "Cancel" button to stop and exit this dialog.</p>' ;
827827
828- // If the modal already exists, update its content for a fresh fetch.
829- if ( $ ( ' #changelogModal ' ). length ) {
828+ if ( $ ( ' #changelogModal ' ). length )
829+ {
830830 $ (' #changelogData' ).html (loadingMessage);
831831 $ (' #closeChangelogModal' ).text (" Cancel" );
832- } else {
833- // Create modal overlay if it doesn't exist
832+ }
833+ else
834+ { // Create modal overlay if it doesn't exist //
834835 $ (' body' ).append (
835836 ' <div id="changelogModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; ' +
836837 ' background:rgba(0,0,0,0.8); z-index:10000;">' +
@@ -848,11 +849,10 @@ function ShowLatestChangelog(e) {
848849 $ (' #changelogModal' ).hide ();
849850 });
850851 }
851-
852- // Show the modal overlay
852+
853853 $ (' #changelogModal' ).show ();
854854
855- // Trigger the backend shell script via form submission (using AJAX)
855+ // Trigger the backend shell script via form submission //
856856 var formData = $ (' form[name="form"]' ).serializeArray ();
857857 formData .push ({ name: " action_script" , value: " start_MerlinAUdownloadchangelog" });
858858 formData .push ({ name: " action_wait" , value: " 10" });
@@ -865,10 +865,10 @@ function ShowLatestChangelog(e) {
865865 console .error (" Failed to submit changelog trigger." );
866866 });
867867
868- // Record the start time and wait 8 seconds before attempting to fetch the changelog
868+ // Record the start time and wait 8 seconds before attempting to fetch the changelog //
869869 var startTime = new Date ().getTime ();
870870 setTimeout (function () {
871- fetchChangelog (startTime);
871+ FetchChangelog (startTime);
872872 // Once the changelog has loaded, update the button text to "Close"
873873 $ (' #closeChangelogModal' ).text (" Close" );
874874 }, 8000 );
@@ -2019,71 +2019,78 @@ function initial()
20192019/* *----------------------------------------**/
20202020/* * Modified by Martinski W. [2025-Mar-07] **/
20212021/* *----------------------------------------**/
2022- function SaveCombinedConfig () {
2023- // Clear the hidden field before saving
2022+ function SaveCombinedConfig ()
2023+ {
2024+ // Clear the hidden field before saving //
20242025 document .getElementById (' amng_custom' ).value = ' ' ;
20252026
2026- /* ==============================
2027- ACTIONS CONFIG SECTION
2028- ============================== */
2027+ /** ========================* */
2028+ /** ACTIONS CONFIG SECTION * */
2029+ /** ========================* */
20292030 var passwordElem = document .getElementById (' routerPassword' );
20302031 var usernameElem = document .getElementById (' http_username' );
20312032 var usernameStr = usernameElem ? usernameElem .value .trim () : ' admin' ;
20322033
2033- // Validate that Username is not empty
2034- if (usernameStr === null || usernameStr . length === 0 ) {
2034+ if (usernameStr === null || usernameStr . length === 0 )
2035+ {
20352036 console .error (" HTTP Username is missing." );
20362037 alert (" HTTP Username is not set. Please contact your administrator." );
20372038 return false ;
20382039 }
2039- if (! ValidatePasswordString (passwordElem, ' onSAVE' )) {
2040+ if (! ValidatePasswordString (passwordElem, ' onSAVE' ))
2041+ {
20402042 alert (` ${ validationErrorMsg} \n\n ` + loginPassword .ErrorMsg ());
20412043 return false ;
20422044 }
2043- if (! ValidatePostponedDays (document .form .fwUpdatePostponement )) {
2045+ if (! ValidatePostponedDays (document .form .fwUpdatePostponement ))
2046+ {
20442047 alert (` ${ validationErrorMsg} \n\n ` + fwPostponedDays .ErrorMsg ());
20452048 return false ;
20462049 }
20472050 if (document .form .fwScheduleHOUR .disabled === false &&
2048- ! ValidateFWUpdateTime (document .form .fwScheduleHOUR , ' HOUR' )) {
2051+ ! ValidateFWUpdateTime (document .form .fwScheduleHOUR , ' HOUR' ))
2052+ {
20492053 alert (` ${ validationErrorMsg} \n\n ` + fwScheduleTime .ErrorMsg (' HOUR' ));
20502054 return false ;
20512055 }
20522056 if (document .form .fwScheduleMINS .disabled === false &&
2053- ! ValidateFWUpdateTime (document .form .fwScheduleMINS , ' MINS' )) {
2057+ ! ValidateFWUpdateTime (document .form .fwScheduleMINS , ' MINS' ))
2058+ {
20542059 alert (` ${ validationErrorMsg} \n\n ` + fwScheduleTime .ErrorMsg (' MINS' ));
20552060 return false ;
20562061 }
20572062 if (document .getElementById (' fwSchedBoxDAYSX' ).checked &&
2058- ! ValidateFWUpdateXDays (document .form .fwScheduleXDAYS , ' DAYS' )) {
2063+ ! ValidateFWUpdateXDays (document .form .fwScheduleXDAYS , ' DAYS' ))
2064+ {
20592065 alert (` ${ validationErrorMsg} \n\n ` + fwScheduleTime .ErrorMsg (' DAYS' ));
20602066 return false ;
20612067 }
20622068
2063- // Process FW update cron schedule conversion
2069+ // F/W Update cron schedule //
20642070 let fwUpdateRawCronSchedule = custom_settings .FW_New_Update_Cron_Job_Schedule ;
20652071 fwUpdateRawCronSchedule = FWConvertWebUISettingsToCronSchedule (fwUpdateRawCronSchedule);
20662072
2067- // Encode credentials in Base64
2073+ // Encode credentials in Base64 //
20682074 var credentials = usernameStr + ' :' + passwordElem .value ;
20692075 var encodedCredentials = btoa (credentials);
20702076
2071- // Build the Actions settings object
2072- var action_settings = {
2077+ // Build the Actions settings object //
2078+ var action_settings =
2079+ {
20732080 credentials_base64: encodedCredentials,
20742081 FW_New_Update_Cron_Job_Schedule: fwUpdateRawCronSchedule,
20752082 FW_New_Update_Postponement_Days: document .getElementById (' fwUpdatePostponement' )? .value || ' 0' ,
20762083 CheckChangeLog: document .getElementById (' changelogCheckEnabled' ).checked ? ' ENABLED' : ' DISABLED' ,
20772084 FW_Update_Check: document .getElementById (' FW_AutoUpdate_Check' ).checked ? ' ENABLED' : ' DISABLED'
20782085 };
20792086
2080- // Prefix the Actions settings
2087+ // Prefix Actions settings //
20812088 var prefixedActionSettings = PrefixCustomSettings (action_settings, ' MerlinAU_' );
20822089
2083- /* ==============================
2084- ADVANCED CONFIG SECTION
2085- ============================== */
2086- // Process Email Notification settings (only if enabled)
2090+ /** =========================* */
2091+ /** ADVANCED CONFIG SECTION * */
2092+ /** =========================* */
2093+ // Email Notifications (only if enabled) //
20872094 let emailFormat = document .getElementById (' emailFormat' );
20882095 let secondaryEmail = document .getElementById (' secondaryEmail' );
20892096 let emailNotificationsEnabled = document .getElementById (' emailNotificationsEnabled' );
@@ -2098,53 +2105,57 @@ function SaveCombinedConfig() {
20982105 advanced_settings .FW_New_Update_EMail_CC_Address = secondaryEmail .value || ' TBD' ;
20992106 }
21002107
2101- // Process F/W Update ZIP Directory
2108+ // F/W Update ZIP Directory //
21022109 let fwUpdateZIPdirectory = document .getElementById (' fwUpdateZIPDirectory' );
2103- if (fwUpdateZIPdirectory !== null && typeof fwUpdateZIPdirectory !== ' undefined' ) {
2110+ if (fwUpdateZIPdirectory !== null && typeof fwUpdateZIPdirectory !== ' undefined' )
2111+ {
21042112 if (ValidateDirectoryPath (fwUpdateZIPdirectory, ' ZIP' )) {
21052113 advanced_settings .FW_New_Update_ZIP_Directory_Path = fwUpdateZIPdirectory .value ;
2106- } else {
2114+ }
2115+ else {
21072116 alert (` ${ validationErrorMsg} \n\n ` + fwUpdateDirPath .ErrorMsg (' ZIP' ));
21082117 return false ;
21092118 }
21102119 }
21112120
2112- // Process F/W Update LOG Directory
2121+ // F/W Update LOG Directory //
21132122 let fwUpdateLOGdirectory = document .getElementById (' fwUpdateLOGDirectory' );
2114- if (fwUpdateLOGdirectory !== null && typeof fwUpdateLOGdirectory !== ' undefined' ) {
2123+ if (fwUpdateLOGdirectory !== null && typeof fwUpdateLOGdirectory !== ' undefined' )
2124+ {
21152125 if (ValidateDirectoryPath (fwUpdateLOGdirectory, ' LOG' )) {
21162126 advanced_settings .FW_New_Update_LOG_Directory_Path = fwUpdateLOGdirectory .value ;
2117- } else {
2127+ }
2128+ else {
21182129 alert (` ${ validationErrorMsg} \n\n ` + fwUpdateDirPath .ErrorMsg (' LOG' ));
21192130 return false ;
21202131 }
21212132 }
21222133
2123- // Process Tailscale/ZeroTier VPN Access
2134+ // Tailscale/ZeroTier VPN Access //
21242135 let tailscaleVPNEnabled = document .getElementById (' tailscaleVPNEnabled' );
21252136 if (tailscaleVPNEnabled && ! tailscaleVPNEnabled .disabled ) {
21262137 advanced_settings .Allow_Updates_OverVPN = tailscaleVPNEnabled .checked ? ' ENABLED' : ' DISABLED' ;
21272138 }
21282139
2129- // Process Automatic Script Updates
2140+ // Automatic Script Updates //
21302141 let script_AutoUpdate_Check = document .getElementById (' Script_AutoUpdate_Check' );
21312142 if (script_AutoUpdate_Check && ! script_AutoUpdate_Check .disabled ) {
21322143 advanced_settings .Allow_Script_Auto_Update = script_AutoUpdate_Check .checked ? ' ENABLED' : ' DISABLED' ;
21332144 }
21342145
2135- // Process Beta-to-Release Updates
2146+ // Beta-to-Release Updates //
21362147 let betaToReleaseUpdatesEnabled = document .getElementById (' betaToReleaseUpdatesEnabled' );
21372148 if (betaToReleaseUpdatesEnabled && ! betaToReleaseUpdatesEnabled .disabled ) {
21382149 advanced_settings .FW_Allow_Beta_Production_Up = betaToReleaseUpdatesEnabled .checked ? ' ENABLED' : ' DISABLED' ;
21392150 }
21402151
2141- // Process Automatic Backups
2152+ // Automatic Backups //
21422153 let autobackupEnabled = document .getElementById (' autobackupEnabled' );
21432154 if (autobackupEnabled && ! autobackupEnabled .disabled ) {
21442155 advanced_settings .FW_Auto_Backupmon = autobackupEnabled .checked ? ' ENABLED' : ' DISABLED' ;
21452156 }
21462157
2147- // Process ROG/TUF F/W Build Types (if the rows are visible)
2158+ // ROG/TUF F/W Build Types (if rows are visible) //
21482159 let rogFWBuildRow = document .getElementById (' rogFWBuildRow' );
21492160 let rogFWBuildType = document .getElementById (' rogFWBuildType' );
21502161 if (rogFWBuildRow && rogFWBuildRow .style .display !== ' none' && rogFWBuildType) {
@@ -2156,26 +2167,25 @@ function SaveCombinedConfig() {
21562167 advanced_settings .TUFBuild = (tuffFWBuildType .value === ' TUF' ) ? ' ENABLED' : ' DISABLED' ;
21572168 }
21582169
2159- // Prefix the Advanced settings
2170+ // Prefix Advanced settings //
21602171 var prefixedAdvancedSettings = PrefixCustomSettings (advanced_settings, ' MerlinAU_' );
21612172
2162- /* ==============================
2163- MERGE SETTINGS & SUBMIT FORM
2164- ==============================*/
2165- // Merge shared settings with both prefixed Action and Advanced settings
2173+ /** ==============================* */
2174+ /** MERGE SETTINGS & SUBMIT FORM * */
2175+ /** ==============================* */
2176+ // Merge shared settings with prefixed Action and Advanced settings //
21662177 var updatedSettings = Object .assign ({}, shared_custom_settings, prefixedActionSettings, prefixedAdvancedSettings);
21672178 ConsoleLogDEBUG (" Combined Config Form submitted with settings:" , updatedSettings);
21682179
2169- // Save merged settings to the hidden input field
2180+ // Save merged settings to the hidden input field //
21702181 document .getElementById (' amng_custom' ).value = JSON .stringify (updatedSettings);
21712182
2172- // Determine action script based on the RunLoginTestOnSave checkbox
2183+ // Action script is based on ' RunLoginTestOnSave' checkbox //
21732184 let actionScriptValue;
2174- if (! document .getElementById (' RunLoginTestOnSave' ).checked ) {
2175- actionScriptValue = ' start_MerlinAUconfig' ;
2176- } else {
2177- actionScriptValue = ' start_MerlinAUconfig_runLoginTest' ;
2178- }
2185+ if (! document .getElementById (' RunLoginTestOnSave' ).checked )
2186+ { actionScriptValue = ' start_MerlinAUconfig' ; }
2187+ else
2188+ { actionScriptValue = ' start_MerlinAUconfig_runLoginTest' ; }
21792189 document .form .action_script .value = actionScriptValue;
21802190 document .form .action_wait .value = 10 ;
21812191
@@ -2708,39 +2718,25 @@ function initializeCollapsibleSections()
27082718 <br>
27092719 <label style=" margin-left:0px; " >
27102720 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_SUN " value=" Sun " class=" input "
2711- style=" margin-left:55px; margin-bottom:7px " />
2712- Sun
2713- </label>
2721+ style=" margin-left:55px; margin-bottom:7px " />Sun</label>
27142722 <label style=" margin-left:0px; " >
27152723 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_MON " value=" Mon " class=" input "
2716- style=" margin-left:14px; margin-bottom:7px " />
2717- Mon
2718- </label>
2724+ style=" margin-left:14px; margin-bottom:7px " />Mon</label>
27192725 <label style=" margin-left:0px; " >
27202726 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_TUE " value=" Tue " class=" input "
2721- style=" margin-left:14px; margin-bottom:7px " />
2722- Tue
2723- </label>
2727+ style=" margin-left:14px; margin-bottom:7px " />Tue</label>
27242728 <label style=" margin-left:0px; " >
27252729 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_WED " value=" Wed " class=" input "
2726- style=" margin-left:14px; margin-bottom:7px " />
2727- Wed
2728- </label>
2730+ style=" margin-left:14px; margin-bottom:7px " />Wed</label>
27292731 <label style=" margin-left:0px; " >
27302732 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_THU " value=" Thu " class=" input "
2731- style=" margin-left:14px; margin-bottom:7px " />
2732- Thu
2733- </label>
2733+ style=" margin-left:14px; margin-bottom:7px " />Thu</label>
27342734 <label style=" margin-left:0px; " >
27352735 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_FRI " value=" Fri " class=" input "
2736- style=" margin-left:14px; margin-bottom:7px " />
2737- Fri
2738- </label>
2736+ style=" margin-left:14px; margin-bottom:7px " />Fri</label>
27392737 <label style=" margin-left:0px; " >
27402738 <input type=" checkbox " name=" fwSchedDAYWEEK " id=" fwSched_SAT " value=" Sat " class=" input "
2741- style=" margin-left:14px; margin-bottom:7px " />
2742- Sat
2743- </label>
2739+ style=" margin-left:14px; margin-bottom:7px " />Sat</label>
27442740 </br>
27452741 </div>
27462742 <div id=" fwCronScheduleHOUR " >
0 commit comments