Compare commits
	
		
			3 Commits
		
	
	
		
			11_0_0-92_
			...
			11_0_0-95_
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0f2e2b82aa | |||
| 0341d02608 | |||
| c208419704 | 
| @@ -37,7 +37,7 @@ use esmith::NavigationDB; # no UTF8 raw is ok for ASCII only flat file | ||||
| use SrvMngr_Auth qw(check_admin_access); | ||||
|  | ||||
| #this is overwrittrn with the "release" by the spec file - release can be "99.el8.sme" | ||||
| our $VERSION = '91.el8.sme';  | ||||
| our $VERSION = '94.el8.sme';  | ||||
| #Extract the release value | ||||
| if ($VERSION =~ /^(\d+)/) { | ||||
|     $VERSION = $1;  # $1 contains the matched numeric digits | ||||
| @@ -325,8 +325,11 @@ sub setup_routing { | ||||
|     $if_admin->get('/clamav')->to('clamav#main')->name('clamav'); | ||||
|     $if_admin->post('/clamav')->to('clamav#do_update')->name('clamav2'); | ||||
|  | ||||
|     #$if_admin->get('/datetime')->to('datetime#main')->name('datetime'); | ||||
|     #$if_admin->post('/datetime')->to('datetime#do_update')->name('datetime2'); | ||||
|     $if_admin->get('/datetime')->to('datetime#main')->name('datetime'); | ||||
|     $if_admin->post('/datetimeu')->to('datetime#do_update')->name('datetimeu'); | ||||
|     $if_admin->get('/datetimed')->to('datetime#do_display')->name('datetimed'); | ||||
|     $if_admin->post('/datetimet')->to('datetime#do_testntp')->name('datetimet'); | ||||
|  | ||||
|  | ||||
|     $if_admin->get('/directory')->to('directory#main')->name('directory'); | ||||
|     $if_admin->post('/directory')->to('directory#do_update')->name('directory2'); | ||||
| @@ -421,28 +424,59 @@ sub setup_routing { | ||||
|     # additional routes (for contribs) got from 'routes' db | ||||
|     #my @routes = @{SrvMngr::get_routes_list()}; | ||||
|  | ||||
|     foreach (@{SrvMngr::get_routes_list()}) { | ||||
|  | ||||
| 	if ( defined $_->{method} and defined $_->{url} and defined $_->{ctlact} and defined $_->{name} ) { | ||||
| 	    my $menu = defined $_->{menu} ? $_->{menu} : 'A'; | ||||
| 	    if ( $menu eq 'N' ) { | ||||
| 	    	$r->get($_->{url})->to($_->{ctlact})->name($_->{name})  | ||||
| 			if ( $_->{method} eq 'get'); | ||||
| 		$r->post($_->{url})->to($_->{ctlact})->name($_->{name}) | ||||
| 			if ( $_->{method} eq 'post'); | ||||
| 	    } elsif ( $menu eq 'U' ) { | ||||
| 	    	$if_logged_in->get($_->{url})->to($_->{ctlact})->name($_->{name})  | ||||
| 			if ( $_->{method} eq 'get'); | ||||
| 		$if_logged_in->post($_->{url})->to($_->{ctlact})->name($_->{name}) | ||||
| 			if ( $_->{method} eq 'post'); | ||||
| 	    } else { | ||||
| 	    	$if_admin->get($_->{url})->to($_->{ctlact})->name($_->{name})  | ||||
| 			if ( $_->{method} eq 'get'); | ||||
| 		$if_admin->post($_->{url})->to($_->{ctlact})->name($_->{name}) | ||||
| 			if ( $_->{method} eq 'post'); | ||||
| 	    } | ||||
|     #foreach (@{SrvMngr::get_routes_list()}) { | ||||
| 		#if ( defined $_->{method} and defined $_->{url} and defined $_->{ctlact} and defined $_->{name} ) { | ||||
| 			#my $menu = defined $_->{menu} ? $_->{menu} : 'A'; | ||||
| 			#if ( $menu eq 'N' ) { | ||||
| 				#$r->get($_->{url})->to($_->{ctlact})->name($_->{name})  | ||||
| 				#if ( $_->{method} eq 'get'); | ||||
| 			#$r->post($_->{url})->to($_->{ctlact})->name($_->{name}) | ||||
| 				#if ( $_->{method} eq 'post'); | ||||
| 			#} elsif ( $menu eq 'U' ) { | ||||
| 				#$if_logged_in->get($_->{url})->to($_->{ctlact})->name($_->{name})  | ||||
| 				#if ( $_->{method} eq 'get'); | ||||
| 			#$if_logged_in->post($_->{url})->to($_->{ctlact})->name($_->{name}) | ||||
| 				#if ( $_->{method} eq 'post'); | ||||
| 			#} else { | ||||
| 				#$if_admin->get($_->{url})->to($_->{ctlact})->name($_->{name})  | ||||
| 				#if ( $_->{method} eq 'get'); | ||||
| 			#$if_admin->post($_->{url})->to($_->{ctlact})->name($_->{name}) | ||||
| 				#if ( $_->{method} eq 'post'); | ||||
| 			#} | ||||
| 		#} | ||||
|     #} | ||||
|      | ||||
|     foreach my $route (@{SrvMngr::get_routes_list()}) { | ||||
| 		if (defined $route->{method} && defined $route->{url} && defined $route->{ctlact} && defined $route->{name}) { | ||||
| 			my $menu = defined $route->{menu} ? $route->{menu} : 'A'; | ||||
| 			 | ||||
| 			# Fix controller case: convert "ControllerName" to "controllername" in "ControllerName#action" | ||||
| 			# this is so that AdminLTE breadcrumb works  - it appears that perl Packages names are NOT case sensitive  | ||||
| 			# and that the breadcrumb package assumes that the package name is the same as the main route. | ||||
| 			my ($controller, $action) = split /#/, $route->{ctlact}, 2; | ||||
| 			my $fixed_ctlact = lc($controller) . '#' . $action; | ||||
| 			 | ||||
| 			if ($menu eq 'N') { | ||||
| 				$r->get($route->{url})->to($fixed_ctlact)->name($route->{name})  | ||||
| 					if $route->{method} eq 'get'; | ||||
| 				$r->post($route->{url})->to($fixed_ctlact)->name($route->{name}) | ||||
| 					if $route->{method} eq 'post'; | ||||
| 			} | ||||
| 			elsif ($menu eq 'U') { | ||||
| 				$if_logged_in->get($route->{url})->to($fixed_ctlact)->name($route->{name})  | ||||
| 					if $route->{method} eq 'get'; | ||||
| 				$if_logged_in->post($route->{url})->to($fixed_ctlact)->name($route->{name}) | ||||
| 					if $route->{method} eq 'post'; | ||||
| 			} | ||||
| 			else {  # Default: menu 'A' | ||||
| 				$if_admin->get($route->{url})->to($fixed_ctlact)->name($route->{name})  | ||||
| 					if $route->{method} eq 'get'; | ||||
| 				$if_admin->post($route->{url})->to($fixed_ctlact)->name($route->{name}) | ||||
| 					if $route->{method} eq 'post'; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|  | ||||
|     $if_admin->get('/config/:key' => {key => qr/[a-z0-9]{2,32}/})->to('request#getconfig')->name('getconfig'); | ||||
|     $if_admin->get('/account/:key' => {key => qr/[a-z0-9]{2,32}/})->to('request#getaccount')->name('getaccount'); | ||||
|   | ||||
| @@ -13,6 +13,8 @@ use esmith::NetworksDB::UTF8; | ||||
| use esmith::HostsDB; | ||||
| use esmith::DomainsDB::UTF8; | ||||
|  | ||||
| use DateTime; | ||||
|  | ||||
| use constant FALSE => 0; | ||||
| use constant TRUE  => 1; | ||||
|  | ||||
| @@ -79,6 +81,7 @@ my $ddb; | ||||
| 		my $now_sec     = sprintf('%02d', $today_sec); | ||||
| 		my $current_year = $today_year; | ||||
| 		my $ntpserverurl = $cdb->get_prop('ntpd','NTPServer'); | ||||
| 		my $now = DateTime->now( time_zone => 'local' ); | ||||
| 		my %ret = ( | ||||
| 			# fields from Inputs  | ||||
| 			'time_mode'=>($ntpserverurl eq '' ? 'dat_manually_set' : 'dat_ntp_server'), | ||||
| @@ -90,6 +93,8 @@ my $ddb; | ||||
| 			'minute'=>"$now_min", | ||||
| 			'second'=>"$now_sec", | ||||
| 			'ntpstatus' => $cdb->get_prop('ntpd','status') || 'disabled', | ||||
| 			# and the current time as a full format  | ||||
| 			'currentdatetime' => $now->strftime('%Y-%m-%dT%H:%M:%S') | ||||
| 			 | ||||
| 		); | ||||
| 		return %ret; | ||||
| @@ -224,38 +229,12 @@ sub validate_change_datetime { | ||||
|         $timezone = "US/Eastern"; | ||||
|     } | ||||
|     my $month = $c->param('month'); | ||||
|  | ||||
|     if ($month =~ /^(\d{1,2})$/) { | ||||
|         $month = $1; | ||||
|     } else { | ||||
|         $month = "1"; | ||||
|     } | ||||
|  | ||||
|     if (($month < 1) || ($month > 12)) { | ||||
|         return $c->l('dat_INVALID_MONTH') . " $month. " . $c->l('dat_MONTH_BETWEEN_1_AND_12'); | ||||
|     } | ||||
|     my $day = $c->param('day'); | ||||
|  | ||||
|     if ($day =~ /^(\d{1,2})$/) { | ||||
|         $day = $1; | ||||
|     } else { | ||||
|         $day = "1"; | ||||
|     } | ||||
|  | ||||
|     if (($day < 1) || ($day > 31)) { | ||||
|         return $c->l('dat_INVALID_DAY') . " $day. " . $c->l('dat_BETWEEN_1_AND_31'); | ||||
|     } | ||||
|     my $year = $c->param('year'); | ||||
|     if (!is_valid_date($year, $month, $day)){ | ||||
| 		return $c->l('dat_Invalid_date') | ||||
| 	} | ||||
|  | ||||
|     if ($year =~ /^(\d{4})$/) { | ||||
|         $year = $1; | ||||
|     } else { | ||||
|         $year = "2000"; | ||||
|     } | ||||
|  | ||||
|     if (($year < 1900) || ($year > 2200)) { | ||||
|         return $c->l('dat_INVALID_YEAR') . " $year. " . $c->l('dat_FOUR_DIGIT_YEAR'); | ||||
|     } | ||||
|     my $hour = $c->param('hour'); | ||||
|  | ||||
|     if ($hour =~ /^(\d{1,2})$/) { | ||||
| @@ -289,24 +268,6 @@ sub validate_change_datetime { | ||||
|     if (($second < 0) || ($second > 59)) { | ||||
|         return $c->l('dat_INVALID_SECOND') . " $second. " . $c->l('dat_BETWEEN_0_AND_59'); | ||||
|     } | ||||
|     #my $ampm = $c->param('Ampm'); | ||||
|  | ||||
| 	#Move to 24 hours clock  - not using AM/PM. | ||||
|     #if ($ampm =~ /^(AM|PM)$/) { | ||||
|         #$ampm = $1; | ||||
|     #} else { | ||||
|         #$ampm = "AM"; | ||||
|     #} | ||||
|     # force AM so that it actually works on 24hr clock. | ||||
|     #$ampm = "AM"; | ||||
|      | ||||
|  | ||||
|     # convert to 24 hour time | ||||
|     #$hour = $hour % 12; | ||||
|  | ||||
|     #if ($ampm eq "PM") { | ||||
|     #    $hour = $hour + 12; | ||||
|     #} | ||||
|  | ||||
|     #-------------------------------------------------- | ||||
|     # Store time zone in configuration database | ||||
| @@ -325,10 +286,27 @@ sub validate_change_datetime { | ||||
|     # and hardware clock | ||||
|     #-------------------------------------------------- | ||||
|     my $newdate = sprintf "%02d%02d%02d%02d%04d.%02d", $month, $day, $hour, $minute, $year, $second; | ||||
|     esmith::util::backgroundCommand(2, "/sbin/e-smith/signal-event", "timezone-update", $newdate); | ||||
|     $c->app->log->info("Changing date manually to $newdate"); | ||||
|     esmith::util::backgroundCommand(2, "/sbin/e-smith/signal-event", "timezone-update", $newdate); #TEMP!!! | ||||
|     return ''; | ||||
| } ## end sub validate_change_datetime | ||||
|  | ||||
| sub is_valid_date { | ||||
|   my ($year, $month, $day) = @_; | ||||
|  | ||||
|   # Check if all parts are defined and integers | ||||
|   return 0 unless defined $year && defined $month && defined $day; | ||||
|   return 0 unless $year =~ /^\d+$/ && $month =~ /^\d+$/ && $day =~ /^\d+$/; | ||||
|  | ||||
|   # Try to construct a DateTime object | ||||
|   eval { | ||||
|     DateTime->new(year => $year, month => $month, day => $day); | ||||
|     1; | ||||
|   } or return 0; | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| sub update_ntpserver { | ||||
|     my $c         = shift; | ||||
|     my $ntpserver = shift; | ||||
| @@ -378,6 +356,4 @@ sub disable_ntp { | ||||
|     return ''; | ||||
| } ## end sub disable_ntp | ||||
|  | ||||
|  | ||||
|  | ||||
| 1; | ||||
| @@ -8,6 +8,9 @@ package SrvMngr::Controller::Datetime; | ||||
| # heading     : System | ||||
| # description : Date and time | ||||
| # navigation  : 4000 300 | ||||
| # | ||||
| # ######name   : datetimet,    method : post,   url : /datetimet,     ctlact : datetime#testntp | ||||
| # | ||||
| # routes : end | ||||
| # | ||||
| # Documentation: https://wiki.contribs.org/Datetime | ||||
| @@ -115,7 +118,7 @@ sub do_update { | ||||
|     my $c = shift; | ||||
|     $c->app->log->info($c->log_req); | ||||
|      | ||||
|     $c->app->log->info($c->param('month')); | ||||
|     #$c->app->log->info($c->param('month')); | ||||
|      | ||||
|  | ||||
| 	#The most common ones - you might want to delete some of these if they are not used. | ||||
| @@ -173,7 +176,7 @@ sub do_update { | ||||
| 					$c->render(template => "datetime");	 | ||||
| 					return | ||||
| 				} else { | ||||
| 					if ($c->param('time_mode') eq 'data_manually_set') { | ||||
| 					if ($c->param('time_mode') eq 'dat_manually_set') { | ||||
| 						$c->stash( success => $c->l('dat_UPDATING_CLOCK'));  | ||||
| 					} else { | ||||
| 						$c->stash( success => $c->l('dat_SETTINGS_CHANGED'));  | ||||
| @@ -279,5 +282,52 @@ sub do_display { | ||||
| 		dat_data  => \%dat_data | ||||
| 	); | ||||
| 	$c->render(template => "datetime"); | ||||
| }     | ||||
| }   | ||||
|  | ||||
| sub do_testntp { | ||||
|     my $c = shift; | ||||
|     my $server = $c->req->json->{ntpserver} // ''; | ||||
|  | ||||
|     # Strict validation: hostname or IPv4 | ||||
|     unless ($server =~ /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*|\d{1,3}(?:\.\d{1,3}){3})$/) { | ||||
|         return $c->render(json => { success => 0, error => 'Invalid server name or IP' }); | ||||
|     } | ||||
|  | ||||
|     my $timeout = 5; | ||||
|     my @cmd = ('timeout', $timeout, 'ntpdate', '-q', $server); | ||||
|  | ||||
|     # Run ntpdate and capture output | ||||
|     my $output = qx{@cmd 2>&1}; | ||||
|     $c->app->log->info($output); | ||||
|     my $exit_code = $? >> 8; | ||||
|  | ||||
|     # Parse for known errors | ||||
|     if ($exit_code == 124) { | ||||
|         return $c->render(json => { success => 0, error => "Timeout: NTP server did not respond within $timeout seconds" }); | ||||
|     } | ||||
|     if ($output =~ /no server suitable for synchronization found/i) { | ||||
|         return $c->render(json => { success => 0, error => "No suitable NTP server found or server unreachable" }); | ||||
|     } | ||||
|     if ($output =~ /Name or service not known|Temporary failure in name resolution/i) { | ||||
|         return $c->render(json => { success => 0, error => "DNS resolution failed for $server" }); | ||||
|     } | ||||
|     if ($output =~ /ntpdig: no eligible servers/i) { | ||||
|         return $c->render(json => { success => 0, error => "Not a an NTP server" }); | ||||
|     } | ||||
|     if ($output =~ /permission denied/i) { | ||||
|         return $c->render(json => { success => 0, error => "Permission denied running ntpdate" }); | ||||
|     } | ||||
|     if ($exit_code != 0) { | ||||
|         return $c->render(json => { success => 0, error => "ntpdate failed (exit code $exit_code): $output" }); | ||||
|     } | ||||
|  | ||||
|     # Extract date and time down to seconds from adjust line | ||||
| 	my ($datetime) = $output =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/m; | ||||
|  | ||||
| 	if ($datetime) { | ||||
| 		return $c->render(json => { success => 1, time => $datetime }); | ||||
| 	} else { | ||||
| 		return $c->render(json => { success => 0, error => "Could not parse date/time from NTP server response." });} | ||||
| } | ||||
|  | ||||
| 1; | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| 'dat_FORM_TITLE' => 'Date and time configuration', | ||||
| 'dat_The_time_is_currently' => 'The time is currently:', | ||||
| 'dat_INITIAL_DESC' => 'This is where you configure the date and time of this server. You may use an existing network time server or | ||||
| manually set the date and time for your time zone.', | ||||
| 'dat_SET_DATE_TITLE' => 'Set Date and Time', | ||||
| @@ -58,4 +58,5 @@ clock, and <b>will not</b> try to synchronize from a time server.', | ||||
| 'dat_ntp_server' => 'NTP server', | ||||
| 'dat_manually_set' => 'Set manually', | ||||
| 'dat_NTP_Server_URL' =>'NTP Server URL:', | ||||
| 'dat_set_manually' =>'Set Date and Time:', | ||||
| 'dat_set_manually' =>'Set Date and Time:', | ||||
| 'dat_Invalid_date' => 'Invalid date', | ||||
| @@ -7,7 +7,7 @@ | ||||
| .datetime-label-col { | ||||
|   background: #e8f3e2; /* light green */ | ||||
|   padding: 1em 0em 0em 0em; | ||||
|   min-width: 192px; | ||||
|   min-width: 30%; | ||||
|   display: flex; | ||||
|   align-items: flex-start; | ||||
|   justify-content: flex-end; | ||||
| @@ -16,7 +16,7 @@ | ||||
| } | ||||
|  | ||||
| .datetime-label { | ||||
|   display: block; | ||||
| 	display:inline-flex; | ||||
| } | ||||
|  | ||||
| .datetime-fields-col { | ||||
| @@ -26,4 +26,26 @@ | ||||
|   border: 1px solid #ccc; | ||||
|   border-left: none; | ||||
|   border-radius: 0 4px 4px 0; | ||||
| } | ||||
| } | ||||
|  | ||||
| .datetime-clock { | ||||
| 	min-width: 20em; | ||||
| 	display:inline-flex; | ||||
| 	border:0px; | ||||
| 	padding:5px; | ||||
| } | ||||
|  | ||||
| .datetime-clock-label { | ||||
| 	background-color:#e8f3e2; | ||||
| 	display:inline-flex; | ||||
| 	width:30%; | ||||
| 	font-weight:bold; | ||||
| 	text-align:right; | ||||
| 	 | ||||
| 	 | ||||
| } | ||||
|  | ||||
| .ntp-test-result { font-weight: bold; } | ||||
| .ntp-test-success { color: green; } | ||||
| .ntp-test-error   { color: red; } | ||||
| .ntp-test-wait    { color: #333; } | ||||
| @@ -15,4 +15,87 @@ document.addEventListener('DOMContentLoaded', function() { | ||||
|  | ||||
|   select.addEventListener('change', toggleSections); | ||||
|   toggleSections(); // Set initial state | ||||
| }); | ||||
|  | ||||
| document.addEventListener('DOMContentLoaded', function() { | ||||
|   // Parse the initial server time from the input value | ||||
|   const clockElement = document.getElementById('real-time-clock'); | ||||
|   if (!clockElement) return; | ||||
|  | ||||
|   // Get the initial server time from the input's value | ||||
|   let serverTime = new Date(clockElement.value.replace(' ', 'T')); | ||||
|  | ||||
|   function updateDateTime() { | ||||
|     // Format the date/time string as desired | ||||
|     const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; | ||||
|     const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; | ||||
|  | ||||
|     const dayOfWeek = daysOfWeek[serverTime.getDay()]; | ||||
|     const month = months[serverTime.getMonth()]; | ||||
|     const day = serverTime.getDate(); | ||||
|     const year = serverTime.getFullYear(); | ||||
|  | ||||
|     let hours = serverTime.getHours(); | ||||
|     const ampm = hours >= 12 ? 'PM' : 'AM'; | ||||
|     hours = hours % 12 || 12; | ||||
|  | ||||
|     const minutes = serverTime.getMinutes().toString().padStart(2, '0'); | ||||
|     const seconds = serverTime.getSeconds().toString().padStart(2, '0'); | ||||
|  | ||||
|     const dateTimeString = `${dayOfWeek}, ${month} ${day}, ${year} ${hours}:${minutes}:${seconds} ${ampm}`; | ||||
|     clockElement.value = dateTimeString; | ||||
|  | ||||
|     // Advance serverTime by one second | ||||
|     serverTime.setSeconds(serverTime.getSeconds() + 1); | ||||
|   } | ||||
|  | ||||
|   updateDateTime(); | ||||
|   setInterval(updateDateTime, 1000); | ||||
| }); | ||||
|  | ||||
| document.addEventListener('DOMContentLoaded', function() { | ||||
|   const btn = document.getElementById('test-ntp-btn'); | ||||
|   const input = document.getElementById('ntpserver'); | ||||
|   const result = document.getElementById('ntp-test-result'); | ||||
|  | ||||
|   btn.addEventListener('click', function() { | ||||
|     const server = input.value.trim(); | ||||
|     result.className = 'ntp-test-result'; // reset | ||||
|  | ||||
|     if (!server) { | ||||
|       result.textContent = "Please enter a server address."; | ||||
|       result.classList.add('ntp-test-error'); | ||||
|       return; | ||||
|     } | ||||
|     result.textContent = "Testing..."; | ||||
|     result.classList.add('ntp-test-wait'); | ||||
|  | ||||
|     fetch('/smanager/datetimet', { | ||||
|       method: 'POST', | ||||
|       headers: {'Content-Type': 'application/json'}, | ||||
|       body: JSON.stringify({ ntpserver: server }) | ||||
|     }) | ||||
|     .then(response => { | ||||
|       if (!response.ok) { | ||||
|         // HTTP error, e.g., 404, 500 | ||||
|         throw new Error(`HTTP error: ${response.status} ${response.statusText}`); | ||||
|       } | ||||
|       return response.json(); | ||||
|     }) | ||||
|     .then(data => { | ||||
|       result.className = 'ntp-test-result'; // reset | ||||
|       if (data.success) { | ||||
|         result.textContent = `Server time: ${data.time}`; | ||||
|         result.classList.add('ntp-test-success'); | ||||
|       } else { | ||||
|         result.textContent = `Error: ${data.error}`; | ||||
|         result.classList.add('ntp-test-error'); | ||||
|       } | ||||
|     }) | ||||
|     .catch(error => { | ||||
|       // Network error or thrown HTTP error | ||||
|       result.className = 'ntp-test-result ntp-test-error'; | ||||
|       result.textContent = `Request failed: ${error.message}`; | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
| @@ -27,7 +27,15 @@ | ||||
| 		<h1><%= $title %></h1><br> | ||||
| 		%= $modul | ||||
| 		<% my $btn = l('SAVE'); %> | ||||
| 		<p> | ||||
| 		<br /><br /> | ||||
| 		<span> | ||||
| 			%= label_for 'real-time-clock' => $c->l('dat_The_time_is_currently'), class => 'datetime-clock-label' | ||||
| 		</span><span class=data2> | ||||
| <!-- | ||||
| 			<div id="real-time-clock"></div> | ||||
| --> | ||||
| 			%= text_field 'clock', id => 'real-time-clock', readonly => 'readonly', class => 'datetime-clock' , value => $dat_data->{currentdatetime} | ||||
| 		</span> | ||||
| 		% if ($dat_data->{ntpstatus} eq 'disabled') { | ||||
| 			<div class='datetime-set-ntp'> | ||||
| 				%=l 'dat_NTP_ENABLE_DESC' | ||||
| @@ -68,7 +76,9 @@ | ||||
| 						<div class=datetime-fields-col> | ||||
| 							% my $server_check = '^([a-zA-Z0-9][a-zA-Z0-9\.\-]{0,253}[a-zA-Z0-9]|(\d{1,3}\.){3}\d{1,3})$'; | ||||
| 							% param 'ntpserver' => $dat_data->{ntpserver} unless param 'ntpserver'; | ||||
| 							%= text_field ntpserver => placeholder => 'e.g. smeserver.pool.ntp.org',id => 'ntpserver', pattern => $server_check, title => 'Enter a valid hostname or IPv4 address',required => 'required' | ||||
| 							%= text_field ntpserver => placeholder => 'e.g. smeserver.pool.ntp.org', id => 'ntpserver', pattern => $server_check, title => 'Enter a valid hostname or IPv4 address', required => 'required' | ||||
| 							<button type="button" id="test-ntp-btn" class="btn btn-primary ml-2">Test Server</button> | ||||
| 							<span id="ntp-test-result" class="ntp-test-result ml-2"></span> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
|   | ||||
| @@ -2,7 +2,7 @@ Summary: Sme server  navigation module : manager 2 | ||||
| %define name smeserver-manager | ||||
| Name: %{name} | ||||
| %define version 11.0.0 | ||||
| %define release 92 | ||||
| %define release 95 | ||||
| Version: %{version} | ||||
| Release: %{release}%{?dist} | ||||
| License: GPL | ||||
| @@ -144,6 +144,17 @@ true | ||||
| %defattr(-,root,root) | ||||
|  | ||||
| %changelog | ||||
| * Tue Jun 24 2025 Brian Read <brianr@koozali.org> 11.0.0-95.sme | ||||
| - Add clock ticker to datetime panel [SME: 13054] | ||||
| - Add Test Server button for ntp server [SME: 13048] | ||||
| - Add checking that date is fully valid [SME: 13055] | ||||
|  | ||||
| * Thu Jun 19 2025 Brian Read <brianr@koozali.org> 11.0.0-94.sme | ||||
| - re-instate datetime routes in SrvMngr.pm - removed by mistake [SME: 13053] | ||||
|  | ||||
| * Thu Jun 19 2025 Brian Read <brianr@koozali.org> 11.0.0-93.sme | ||||
| - Sort out case of first letter of ctlact in routes added in from header on controller file [SME: 13053] | ||||
|  | ||||
| * Sun Jun 15 2025 Brian Read <brianr@koozali.org> 11.0.0-92.sme | ||||
| - rework datetime panel [SME: 13020] | ||||
| - Fix errors in error messages for local networks panel [SME: 13044] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user