Compare commits
	
		
			14 Commits
		
	
	
		
			11_0_0-11_
			...
			11_0_0-18_
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b9f6392c1d | |||
| 659f060eb6 | |||
| 1087a8a5a2 | |||
| 6a5a756438 | |||
| 91ca26de27 | |||
| 8b93232bbe | |||
| ed1c3e13b1 | |||
| 095a0a1499 | |||
| d16ea6a847 | |||
| e70cc67430 | |||
| b097acafab | |||
| 5d7655a709 | |||
| a58df95aa9 | |||
| 251b454470 | 
| @@ -27,10 +27,10 @@ It is based on the perl Mojolicious package. Mojolicious is a real-time web fram | ||||
| smeserver-manager provides an intuitive and user-friendly web interface that allows administrators to manage various aspects of the server without needing deep technical knowledge or command-line skills. | ||||
|  | ||||
| #### User and Group Management: | ||||
| Easily add, remove, and manage user accounts and groups. The interface simplifies creating email accounts, setting passwords, and configuring user permissions. | ||||
| It allows you to easily add, remove, and manage user accounts and groups. The interface simplifies creating email accounts, setting passwords, and configuring user permissions. | ||||
|  | ||||
| #### Network Configuration: | ||||
| Configures network settings such as IP addresses, DNS, DHCP, and gateway settings. The interface also provides options for setting up VPNs, remote access, and firewall rules. | ||||
| You can configures network settings such as IP addresses, DNS, DHCP, and gateway settings. The interface also provides options for setting up VPNs, remote access, and firewall rules. | ||||
|  | ||||
| #### File Sharing and Storage: | ||||
| Enables and manages file sharing services like Samba (for Windows file sharing) and NFS (for Unix/Linux file sharing). Administrators can easily create shared folders and manage permissions. | ||||
|   | ||||
							
								
								
									
										2
									
								
								clog
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								clog
									
									
									
									
									
								
							| @@ -1,2 +0,0 @@ | ||||
| * Sat Jul 27 2024 Brian Read <brianr@koozali.org> 11.0.0-11.sme | ||||
| - Add in flag icon indication of locale [SME: 12706] | ||||
| @@ -230,14 +230,6 @@ hr.sme-copyrightbar { | ||||
|     font-size: 10px;  | ||||
| } | ||||
|  | ||||
| #flag-icon { | ||||
|     font-size: 20px; | ||||
|     float: right; | ||||
|     margin-top: 0.67em; | ||||
|     margin-right: 1%; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*These style definitions were found int he old css file (manager.css) | ||||
| but don't seem to ever be referenced in the code.  They're here | ||||
| for reference. | ||||
|   | ||||
| @@ -67,5 +67,21 @@ hr.sme-copyrightbar { | ||||
| color: #8ebe43; | ||||
| background-color: #8ebe43; | ||||
|     } | ||||
|        | ||||
| /* flag container no flag */ | ||||
| #flag-container span { | ||||
|   font-size: 24px; | ||||
| } | ||||
|  | ||||
| .fallback-box { | ||||
|   display: inline-block; /* Make it inline-block to fit around the content */ | ||||
|   border: 2px solid gray; /* Change the border color as desired */ | ||||
|   padding: 10px; /* Add some padding */ | ||||
|   border-radius: 10px; /* Round the corners of the box */ | ||||
|   font-size: 60px; /* Adjust size if needed */ | ||||
|   margin-top: 10px; /* Add some margin */ | ||||
|   text-align: center; /* Center text inside the box */ | ||||
| } | ||||
|  | ||||
| HERE | ||||
| } | ||||
|   | ||||
| @@ -234,7 +234,7 @@ a.menu-title { | ||||
|     width: 100%; | ||||
| } | ||||
| #h2e11 { | ||||
|     width: 70%; | ||||
|     width: 50%; | ||||
|     float: left; | ||||
| } | ||||
| #h2e12 { | ||||
| @@ -257,9 +257,9 @@ a.menu-title { | ||||
|     width: 70%; | ||||
| } | ||||
|  | ||||
| #h2e22,#h2e23 { | ||||
| #h2e22,#h2e23,#h2e12 { | ||||
|     float: left; | ||||
|     width: 10%; | ||||
|     width: 14em; | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| @@ -273,6 +273,7 @@ a.menu-title { | ||||
|     left: 2px; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*end*/ | ||||
| EOF | ||||
| } | ||||
|   | ||||
| @@ -23,14 +23,16 @@ use File::Basename; | ||||
|  | ||||
| our $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
| my $dnf_status_file  = '/var/cache/dnf/dnf.status'; | ||||
|  | ||||
| #use File::stat; | ||||
|  | ||||
| our %dbs; | ||||
|  | ||||
| for ( qw(available installed updates) ) | ||||
| { | ||||
|     $dbs{$_} = esmith::ConfigDB->open_ro("yum_$_") or | ||||
| 	die "Couldn't open yum_$_ DB\n"; | ||||
|     $dbs{$_} = esmith::ConfigDB->open_ro("dnf_$_") or | ||||
| 	die "Couldn't open dnf_$_ DB\n"; | ||||
| } | ||||
|  | ||||
| for ( qw(repositories) ) | ||||
| @@ -52,10 +54,11 @@ sub main { | ||||
|  | ||||
|     $yum_datas{'trt'} = 'STAT'; | ||||
|  | ||||
|     if ( -e "/var/run/yum.pid" ) { | ||||
|     | ||||
|     if ( $c->is_dnf_running()) { | ||||
| 	$yum_datas{'trt'} = 'LOGF'; | ||||
| 	$dest = 'yumlogfile'; | ||||
|     } elsif ($cdb->get_prop('yum', 'LogFile')) { | ||||
|     } elsif ($cdb->get_prop('dnf', 'LogFile')) { | ||||
| 	$yum_datas{'trt'} = 'PSTU'; | ||||
| 	$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes'); | ||||
| 	$dest = 'yumpostupg'; | ||||
| @@ -83,9 +86,9 @@ sub do_display { | ||||
|     $yum_datas{'trt'} = $trt; | ||||
|  | ||||
|     # force $trt if current logfile | ||||
|     if ( -e "/var/run/yum.pid" ) { | ||||
|     if ( $c->is_dnf_running() ) { | ||||
| 	$trt = 'LOGF'; | ||||
|     } elsif ($cdb->get_prop('yum', 'LogFile')) { | ||||
|     } elsif ($cdb->get_prop('dnf', 'LogFile')) { | ||||
| 	$trt = 'PSTU'; | ||||
|     } | ||||
|  | ||||
| @@ -106,13 +109,13 @@ sub do_display { | ||||
| 	} | ||||
|  | ||||
|         if ( $trt eq 'LOGF' ) { | ||||
| 	    if (-e "/var/run/yum.pid") { | ||||
| 	    if ($c->is_dnf_running()) { | ||||
| 	    $dest = 'yumlogfile'; | ||||
| 	    } | ||||
| 	} | ||||
| 	 | ||||
|         if ( $trt eq 'PSTU') { | ||||
| 	    if ($cdb->get_prop('yum', 'LogFile')) { | ||||
| 	    if ($cdb->get_prop('dnf', 'LogFile')) { | ||||
| 		$dest = 'yumpostupg'; | ||||
| 		$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes'); | ||||
| 	    } | ||||
| @@ -221,7 +224,7 @@ sub do_update { | ||||
|     if ( $trt eq 'LOGF' ) { | ||||
|  | ||||
|     	$dest = 'yumlogfile'; | ||||
|         if ( ! -e "/var/run/yum.pid") { | ||||
|         if ( ! $c->is_dnf_running()) { | ||||
| 	    $yum_datas{trt} = 'SUC'; | ||||
| 	    $result = $c->l('yum_SUCCESS'); | ||||
|         } | ||||
| @@ -247,6 +250,24 @@ sub do_update { | ||||
|  | ||||
| }; | ||||
|  | ||||
| sub get_dnf_status { | ||||
|     #interrogate status file created and maintained by smeserver.py plugin for dnf. | ||||
|     my ($c) = @_; | ||||
|     my $file_name = $dnf_status_file; | ||||
|     my $content = "resolved"; | ||||
|     if ( -e "$file_name") { | ||||
| 	open my $fh, '<', $file_name or die "Can't open file: $!"; | ||||
| 	$content = <$fh>; | ||||
| 	close $fh; | ||||
|     } | ||||
|     return $content; | ||||
| } | ||||
|  | ||||
| sub is_dnf_running { | ||||
|     my ($c) = @_; | ||||
|     my $dnf_status = $c->get_dnf_status(); | ||||
|     return $dnf_status ne "resolved" && $dnf_status ne "config" && $dnf_status ne "sack"; | ||||
| } | ||||
|  | ||||
| sub is_empty { | ||||
|  | ||||
| @@ -289,7 +310,7 @@ sub package_functions_enabled { | ||||
|  | ||||
|     my ($c) = @_; | ||||
|  | ||||
|     return ($cdb->get_prop("yum", "PackageFunctions") eq "enabled"); | ||||
|     return ($cdb->get_prop("dnf", "PackageFunctions") eq "enabled"); | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -298,7 +319,7 @@ sub get_status { | ||||
|  | ||||
|     my ($c, $prop, $localise) = @_; | ||||
|  | ||||
|     my $status = $cdb->get_prop("yum", $prop) || 'disabled'; | ||||
|     my $status = $cdb->get_prop("dnf", $prop) || 'disabled'; | ||||
|  | ||||
|     return $status unless $localise; | ||||
|  | ||||
| @@ -433,7 +454,7 @@ sub change_settings { | ||||
| 			PackageFunctions | ||||
|             	) ) | ||||
|     { | ||||
| 	$cdb->set_prop('yum', $param, $c->param("yum_$param")); | ||||
| 	$cdb->set_prop("dnf", $param, $c->param("yum_$param")); | ||||
|     } | ||||
|  | ||||
|     my $check4updates = $c->param("yum_check4updates"); | ||||
| @@ -441,21 +462,21 @@ sub change_settings { | ||||
|  | ||||
|     if ($check4updates ne 'disabled') { $status = 'enabled'; } | ||||
|  | ||||
|     $cdb->set_prop('yum', 'check4updates', $check4updates); | ||||
|     $cdb->set_prop("dnf", 'check4updates', $check4updates); | ||||
|  | ||||
|     my $deltarpm = $c->param("yum_DeltaRpmProcess"); | ||||
|     $cdb->set_prop('yum', 'DeltaRpmProcess', $deltarpm); | ||||
|     $cdb->set_prop("dnf", 'DeltaRpmProcess', $deltarpm); | ||||
|  | ||||
|     my $downloadonly = $c->param("yum_DownloadOnly"); | ||||
|     if ($downloadonly ne 'disabled') { $status = 'enabled'; } | ||||
|  | ||||
|     $cdb->set_prop('yum', 'DownloadOnly', $downloadonly); | ||||
|     $cdb->set_prop("dnf", 'DownloadOnly', $downloadonly); | ||||
|  | ||||
|     my $AutoInstallUpdates = $c->param("yum_AutoInstallUpdates"); | ||||
|     if ($AutoInstallUpdates ne 'disabled') { $status = 'enabled'; } | ||||
|  | ||||
|     $cdb->set_prop('yum', 'AutoInstallUpdates', $AutoInstallUpdates); | ||||
|     $cdb->set_prop('yum', 'status', $status); | ||||
|     $cdb->set_prop("dnf", 'AutoInstallUpdates', $AutoInstallUpdates); | ||||
|     $cdb->set_prop("dnf", 'status', $status); | ||||
|  | ||||
|     my %selected = map {$_ => 1} @{$c->every_param('SelectedRepositories')}; | ||||
|  | ||||
| @@ -469,7 +490,7 @@ sub change_settings { | ||||
|  | ||||
|     $dbs{repositories}->reload; | ||||
|  | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "yum-modify" ) == 0 ) | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "dnf-modify" ) == 0 ) | ||||
|     { | ||||
| 	return $c->l('yum_ERROR_UPDATING_CONFIGURATION'); | ||||
|     } | ||||
| @@ -484,11 +505,11 @@ sub do_yum { | ||||
|  | ||||
|     for ( qw(SelectedGroups SelectedPackages) ) | ||||
|     { | ||||
| 	$cdb->set_prop("yum", $_, join(',', (@{$c->every_param($_)} ))); | ||||
| 	$cdb->set_prop("dnf", $_, join(',', (@{$c->every_param($_)} ))); | ||||
|     } | ||||
|  | ||||
|     esmith::util::backgroundCommand(0, | ||||
|         "/sbin/e-smith/signal-event", "yum-$function"); | ||||
|         "/sbin/e-smith/signal-event", "dnf-$function"); | ||||
|  | ||||
|     for ( qw(available installed updates) ) { | ||||
| 	$dbs{$_}->reload; | ||||
| @@ -517,7 +538,7 @@ sub format_yum_log { | ||||
|  | ||||
|     $cdb->reload; | ||||
|  | ||||
|     my $filepage = $cdb->get_prop('yum', 'LogFile'); | ||||
|     my $filepage = $cdb->get_prop('dnf', 'LogFile'); | ||||
|     return '' unless $filepage and ( -e "$filepage" ); | ||||
|  | ||||
|     my $out = sprintf "<PRE>"; | ||||
| @@ -537,7 +558,7 @@ sub post_upgrade_reboot { | ||||
|  | ||||
|     my $c = shift; | ||||
|  | ||||
|     $cdb->get_prop_and_delete('yum', 'LogFile'); | ||||
|     $cdb->get_prop_and_delete('dnf', 'LogFile'); | ||||
|     $cdb->reload; | ||||
|  | ||||
|     if (fork == 0) { | ||||
| @@ -552,7 +573,7 @@ sub post_upgrade_reboot { | ||||
| sub show_yum_log { | ||||
|     my $c = shift; | ||||
|     my $out = $c->format_yum_log(); | ||||
|     my $yum_log = $cdb->get_prop_and_delete('yum', 'LogFile'); | ||||
|     my $yum_log = $cdb->get_prop_and_delete('dnf', 'LogFile'); | ||||
|     return $out; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,63 +1,278 @@ | ||||
| document.addEventListener('DOMContentLoaded', () => { | ||||
|   const flagContainer = document.getElementById('flag-container'); | ||||
|  | ||||
|   // Function to get the browser's locale | ||||
|   function getBrowserLocale() { | ||||
|     return navigator.language || navigator.userLanguage; | ||||
|   } | ||||
|         async function getCountryName(countryCode) { | ||||
|             try { | ||||
|                 const response = await fetch(`https://restcountries.com/v3.1/alpha/${countryCode}`); | ||||
|                 if (!response.ok) throw new Error('Country not found'); | ||||
|                 const data = await response.json(); | ||||
|                 // Return the name in the native language | ||||
|                 return data[0].name.common;  | ||||
|             } catch (error) { | ||||
|                 console.error(error); | ||||
|                 return 'Unknown Country'; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   // Function to map locale to country code | ||||
|   function getCountryCodeFromLocale(locale) { | ||||
|     const localeParts = locale.split('-'); | ||||
|     return localeParts.length > 1 ? localeParts[1] : localeParts[0]; | ||||
|   } | ||||
|         function getFlagEmoji(locale) { | ||||
|             // Split the locale to get the language and country code | ||||
|             const parts = locale.split('-'); | ||||
|             let countryCode; | ||||
|  | ||||
|   // Function to fetch country names from a CDN | ||||
|   async function fetchCountryNames() { | ||||
|     const response = await fetch('https://restcountries.com/v3.1/all'); | ||||
|     const countries = await response.json(); | ||||
|     const countryNames = {}; | ||||
|     for (const country of countries) { | ||||
|       const code = country.cca2.toLowerCase(); // Country code (ISO 3166-1 alpha-2) | ||||
|       const name = country.name.common; // Common name of the country | ||||
|       countryNames[code] = name; | ||||
|     } | ||||
|     return countryNames; | ||||
|   } | ||||
|             // Handle single subtag (language only) or double subtag (language-country) | ||||
|             if (parts.length === 1) { | ||||
|                 countryCode = getCountryCodeFromLanguage(parts[0]); | ||||
|             } else if (parts.length === 2) { | ||||
|                 countryCode = parts[1].toLowerCase(); // Use the country code | ||||
|             } | ||||
|  | ||||
|   // Function to create and display the flag icon | ||||
|   function displayFlagIcon(countryCode, countryName) { | ||||
|     const flagIcon = document.createElement('span'); | ||||
|     flagIcon.className = `flag-icon flag-icon-${countryCode.toLowerCase()}`; | ||||
|     flagIcon.id = 'flag-icon'; | ||||
|     flagIcon.title = countryName; // Set the title for the tooltip | ||||
|             // If country code is not found, set a fallback output | ||||
|             if (!countryCode) { | ||||
|                 const fallback = `? ${locale.toUpperCase()}`; // Just a question mark and the full locale | ||||
|                 return { flag: fallback, isUnknown: true, countryName: 'Unknown Country' }; | ||||
|             } | ||||
|  | ||||
|     // If you want a custom tooltip instead (uncomment the lines below): | ||||
|     /* | ||||
|     const tooltip = document.createElement('span'); | ||||
|     tooltip.className = 'tooltip'; | ||||
|     tooltip.innerText = countryName; | ||||
|     flagIcon.appendChild(tooltip); | ||||
|             // Convert the country code to a flag emoji | ||||
|             return { | ||||
|                 flag: String.fromCodePoint(...[...countryCode.toUpperCase()].map(char => 0x1F1E6 + char.charCodeAt(0) - 'A'.charCodeAt(0))), | ||||
|                 isUnknown: false, | ||||
|                 countryCode: countryCode | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|     flagIcon.addEventListener('mouseenter', () => { | ||||
|       tooltip.style.display = 'block'; | ||||
|     }); | ||||
|         function getCountryCodeFromLanguage(language) { | ||||
|             // Map languages to countries (this is an example, extend as needed) | ||||
|             const languageToCountryMap = { | ||||
|                   // Add more mappings as needed | ||||
|     "af": "NA", | ||||
|     "agq": "CM", | ||||
|     "ak": "GH", | ||||
|     "am": "ET", | ||||
|     "ar": "01", | ||||
|     "as": "IN", | ||||
|     "asa": "TZ", | ||||
|     "ast": "ES", | ||||
|     "az": "rl", | ||||
|     "bas": "CM", | ||||
|     "be": "BY", | ||||
|     "bem": "ZM", | ||||
|     "bez": "TZ", | ||||
|     "bg": "BG", | ||||
|     "bm": "ML", | ||||
|     "bn": "BD", | ||||
|     "bo": "CN", | ||||
|     "br": "FR", | ||||
|     "brx": "IN", | ||||
|     "bs": "rl", | ||||
|     "ca": "AD", | ||||
|     "ccp": "BD", | ||||
|     "ce": "RU", | ||||
|     "cgg": "UG", | ||||
|     "chr": "US", | ||||
|     "ckb": "IQ", | ||||
|     "cs": "CZ", | ||||
|     "cy": "GB", | ||||
|     "da": "DK", | ||||
|     "dav": "KE", | ||||
|     "de": "DE", | ||||
|     "dje": "NE", | ||||
|     "dsb": "DE", | ||||
|     "dua": "CM", | ||||
|     "dyo": "SN", | ||||
|     "dz": "BT", | ||||
|     "ebu": "KE", | ||||
|     "ee": "GH", | ||||
|     "el": "CY", | ||||
|     "en": "01", | ||||
|     "es": "ES", | ||||
|     "et": "EE", | ||||
|     "eu": "ES", | ||||
|     "ewo": "CM", | ||||
|     "fa": "AF", | ||||
|     "ff": "CM", | ||||
|     "fi": "FI", | ||||
|     "fil": "PH", | ||||
|     "fo": "FO", | ||||
|     "fr": "FR", | ||||
|     "fur": "IT", | ||||
|     "fy": "NL", | ||||
|     "ga": "IE", | ||||
|     "gd": "GB", | ||||
|     "gl": "ES", | ||||
|     "gsw": "CH", | ||||
|     "gu": "IN", | ||||
|     "guz": "KE", | ||||
|     "gv": "IM", | ||||
|     "ha": "GH", | ||||
|     "haw": "US", | ||||
|     "he": "IL", | ||||
|     "hi": "IN", | ||||
|     "hr": "HR", | ||||
|     "hsb": "DE", | ||||
|     "hu": "HU", | ||||
|     "hy": "AM", | ||||
|     "id": "ID", | ||||
|     "ig": "NG", | ||||
|     "ii": "CN", | ||||
|     "is": "IS", | ||||
|     "it": "IT", | ||||
|     "ja": "JP", | ||||
|     "jgo": "CM", | ||||
|     "jmc": "TZ", | ||||
|     "ka": "GE", | ||||
|     "kab": "DZ", | ||||
|     "kam": "KE", | ||||
|     "kde": "TZ", | ||||
|     "kea": "CV", | ||||
|     "khq": "ML", | ||||
|     "ki": "KE", | ||||
|     "kk": "KZ", | ||||
|     "kkj": "CM", | ||||
|     "kl": "GL", | ||||
|     "kln": "KE", | ||||
|     "km": "KH", | ||||
|     "kn": "IN", | ||||
|     "ko": "KP", | ||||
|     "kok": "IN", | ||||
|     "ks": "IN", | ||||
|     "ksb": "TZ", | ||||
|     "ksf": "CM", | ||||
|     "ksh": "DE", | ||||
|     "kw": "GB", | ||||
|     "ky": "KG", | ||||
|     "lag": "TZ", | ||||
|     "lb": "LU", | ||||
|     "lg": "UG", | ||||
|     "lkt": "US", | ||||
|     "ln": "AO", | ||||
|     "lo": "LA", | ||||
|     "lrc": "IQ", | ||||
|     "lt": "LT", | ||||
|     "lu": "CD", | ||||
|     "luo": "KE", | ||||
|     "Luo": "KE", | ||||
|     "luy": "KE", | ||||
|     "lv": "LV", | ||||
|     "mas": "KE", | ||||
|     "mer": "KE", | ||||
|     "mfe": "MU", | ||||
|     "mg": "MG", | ||||
|     "mgh": "MZ", | ||||
|     "mgo": "CM", | ||||
|     "mk": "MK", | ||||
|     "ml": "IN", | ||||
|     "mn": "MN", | ||||
|     "mr": "IN", | ||||
|     "ms": "BN", | ||||
|     "mt": "MT", | ||||
|     "mua": "CM", | ||||
|     "my": "MM", | ||||
|     "mzn": "IR", | ||||
|     "naq": "NA", | ||||
|     "nb": "NO", | ||||
|     "nd": "ZW", | ||||
|     "nds": "DE", | ||||
|     "ne": "IN", | ||||
|     "nl": "NL", | ||||
|     "nmg": "CM", | ||||
|     "nn": "NO", | ||||
|     "nnh": "CM", | ||||
|     "nus": "SS", | ||||
|     "nyn": "UG", | ||||
|     "om": "ET", | ||||
|     "or": "IN", | ||||
|     "os": "GE", | ||||
|     "pa": "ab", | ||||
|     "pl": "PL", | ||||
|     "ps": "AF", | ||||
|     "pt": "PT", | ||||
|     "qu": "BO", | ||||
|     "rm": "CH", | ||||
|     "rn": "BI", | ||||
|     "ro": "RO", | ||||
|     "rof": "TZ", | ||||
|     "ru": "RU", | ||||
|     "rw": "RW", | ||||
|     "rwk": "TZ", | ||||
|     "sah": "RU", | ||||
|     "saq": "KE", | ||||
|     "sbp": "TZ", | ||||
|     "se": "SE", | ||||
|     "seh": "MZ", | ||||
|     "ses": "ML", | ||||
|     "sg": "CF", | ||||
|     "shi": "tn", | ||||
|     "si": "LK", | ||||
|     "sk": "SK", | ||||
|     "sl": "SI", | ||||
|     "smn": "FI", | ||||
|     "sn": "ZW", | ||||
|     "so": "SO", | ||||
|     "sq": "AL", | ||||
|     "sr": "rl", | ||||
|     "sv": "AX", | ||||
|     "sw": "CD", | ||||
|     "ta": "IN", | ||||
|     "te": "IN", | ||||
|     "teo": "KE", | ||||
|     "tg": "TJ", | ||||
|     "th": "TH", | ||||
|     "ti": "ER", | ||||
|     "to": "TO", | ||||
|     "tr": "TR", | ||||
|     "tt": "RU", | ||||
|     "twq": "NE", | ||||
|     "tzm": "MA", | ||||
|     "ug": "CN", | ||||
|     "uk": "UA", | ||||
|     "ur": "IN", | ||||
|     "uz": "ab", | ||||
|     "vai": "tn", | ||||
|     "Vai": "tn", | ||||
|     "vi": "VN", | ||||
|     "vun": "TZ", | ||||
|     "wae": "CH", | ||||
|     "wo": "SN", | ||||
|     "xog": "UG", | ||||
|     "yav": "CM", | ||||
|     "yi": "01", | ||||
|     "yo": "BJ", | ||||
|     "yue": "ns", | ||||
|     "zgh": "MA", | ||||
|     "zh": "ns", | ||||
|     "zu": "ZA" | ||||
|  | ||||
|     flagIcon.addEventListener('mouseleave', () => { | ||||
|       tooltip.style.display = 'none'; | ||||
|     }); | ||||
|     */ | ||||
|  | ||||
|     flagContainer.appendChild(flagIcon); | ||||
|   } | ||||
|             }; | ||||
|  | ||||
|   // Main logic | ||||
|   (async () => { | ||||
|     const locale = getBrowserLocale(); | ||||
|     const countryCode = getCountryCodeFromLocale(locale); | ||||
|     const countryNames = await fetchCountryNames(); // Fetch country names | ||||
|             return languageToCountryMap[language] || null; | ||||
|         } | ||||
|  | ||||
|     const countryName = countryNames[countryCode.toLowerCase()] || 'Unknown Country'; // Get the country name | ||||
|     displayFlagIcon(countryCode, countryName); // Display the flag with country name | ||||
|   })(); | ||||
|         async function displayLocaleAndFlag() { | ||||
|             // Get the browser locale | ||||
|             const userLocale = navigator.language || navigator.userLanguage; | ||||
|             const { flag, isUnknown, countryCode } = getFlagEmoji(userLocale); | ||||
|  | ||||
|             // Display the locale and the corresponding flag (or fallback) | ||||
|             //document.getElementById('locale').textContent = `Your Locale: ${userLocale}`; | ||||
|  | ||||
|             if (isUnknown) { | ||||
|                 const fallbackDiv = document.createElement('div'); | ||||
|                 fallbackDiv.className = 'fallback-box'; | ||||
|                 fallbackDiv.textContent = `? ${userLocale.toUpperCase()}`; // Only show ? and locale code inside the box | ||||
|                 //document.getElementById('flag-container').textContent = "Flag: "; | ||||
|                 document.getElementById('flag-container').appendChild(fallbackDiv); | ||||
|                 // Tooltip for fallback | ||||
|                 fallbackDiv.title = "Unknown Country"; // Tooltip for fallback | ||||
|             } else { | ||||
|                 const countryName = await getCountryName(countryCode); | ||||
|                 const flagSpan = document.createElement('span'); | ||||
|                 flagSpan.textContent = flag; // Use flag emoji | ||||
|                 flagSpan.title = countryName; // Tooltip for the flag in country language | ||||
|                 //document.getElementById('flag-container').textContent = "Flag: "; | ||||
|                 document.getElementById('flag-container').appendChild(flagSpan); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         displayLocaleAndFlag(); | ||||
| }); | ||||
|   | ||||
| @@ -1,30 +1,128 @@ | ||||
| <style> | ||||
| #h2l1 { | ||||
|     display: flex;                  /* Use flexbox layout */ | ||||
|     justify-content: space-between; /* Space between child elements */ | ||||
|     align-items: center;           /* Center items vertically */ | ||||
| } | ||||
|  | ||||
| #h2e11 { | ||||
|     flex: 1;                       /* Allow the first div to take available space on the left */ | ||||
| } | ||||
|  | ||||
| #h2e12 {  | ||||
|     display: flex;                 /* Make this div a flex container */ | ||||
|     align-items: center;           /* Vertically center content in this div */ | ||||
|     margin-left: 20px;            /* Add margin to the left of this div */ | ||||
| } | ||||
|  | ||||
| #flag-container { | ||||
|     display: flex;                 /* Make this div a flex container */ | ||||
|     align-items: center;           /* Vertically center content in this div */ | ||||
|     margin-left: 20px;             /* Add margin to the left of the flag container */ | ||||
|     padding-right: 20px;           /* Add padding to the right side of the flag container */ | ||||
| } | ||||
|  | ||||
| .flag-icon { | ||||
|     width: 43px; | ||||
|     font-size: 20px; | ||||
| } | ||||
|  | ||||
| #legacy-button button { | ||||
|     background-color: #98d36e; /* Button background color */ | ||||
|     font-weight: lighter;      /* Lighter text for the button */ | ||||
|     color: #063;               /* Button text color */ | ||||
|     padding: 5px 10px;         /* Padding for the button */ | ||||
|     border: none;              /* Remove default button border */ | ||||
|     border-radius: 4px;        /* Rounded corners for button */ | ||||
|     cursor: pointer;           /* Change cursor on hover */ | ||||
| } | ||||
|  | ||||
| #legacy-button button:hover { | ||||
|     background-color: #82c961; /* Change color on hover */ | ||||
| } | ||||
|  | ||||
| .infobar { | ||||
|     display: flex;                  /* Use flexbox for alignment */ | ||||
|     justify-content: space-between; /* Space between child elements */ | ||||
|     align-items: center;            /* Center items vertically */ | ||||
|     padding: 10px;                  /* Adjust padding as desired */ | ||||
| } | ||||
|  | ||||
| #h2e21 { | ||||
|     flex: 1;                        /* Allow the first div to take available space on the left */ | ||||
| } | ||||
|  | ||||
| #h2e22 { | ||||
|     display: flex;                  /* Make this div a flex container */ | ||||
|     justify-content: center;        /* Center the help button */ | ||||
|     align-items: center;            /* Center vertically */ | ||||
|     flex: none;                    /* Prevent this div from growing */ | ||||
|     position: relative;             /* Relative position for centering */ | ||||
|     width: 100px;                  /* Set a width for the help button container */ | ||||
| } | ||||
|  | ||||
| #h2e23 { | ||||
|     margin-left: auto;              /* Push the third div to the right */ | ||||
| } | ||||
|  | ||||
| .login-button { | ||||
|     background-color: #98d36e;     /* Button background color */ | ||||
|     font-weight: bold;              /* Bold text */ | ||||
|     xxcolor: #ffffff;                 /* Button text color */ | ||||
|     padding: 8px 12px;              /* Adjust padding for button height */ | ||||
|     border: none;                   /* Remove default border */ | ||||
|     border-radius: 4px;             /* Rounded corners */ | ||||
|     cursor: pointer;                /* Change cursor on hover */ | ||||
| } | ||||
|  | ||||
| .login-button:hover { | ||||
|     background-color: #82c961;      /* Change color on hover */ | ||||
| } | ||||
|  | ||||
| #help-button { | ||||
|     text-decoration: none;          /* Remove underline from link */ | ||||
|     font-size: 20px;                /* Adjust font size as needed */ | ||||
|     padding: 8px 12px;              /* Add padding to the help link */ | ||||
|     background-color: #98d36e;      /* Background for visibility */ | ||||
|     border-radius: 4px;             /* Rounded corners */ | ||||
|     color: #000;                    /* Button text color */ | ||||
| } | ||||
|  | ||||
| #help-button:hover { | ||||
|     background-color: #82c961;      /* Change background on hover */ | ||||
| } | ||||
| </style> | ||||
|  | ||||
| <div id="header2" class="hd2"> | ||||
|     <div id="h2l1">  | ||||
| 		<div id="h2e11"> | ||||
| 			<a target='_blank' href="http://www.koozali.org"><img src="images/smeserver_logo.jpg" height="40" alt="SME Server"></a> | ||||
| 		</div>      | ||||
|         <div id="h2e12" style="float:right;"> | ||||
| 			<br><a href="/server-manager" target='_blank'><button style="background-color:#98d36e;font-weight:bold;color:#063;">Legacy SM</button></a> | ||||
| 		</div>  | ||||
|  | ||||
| 		<div id="h2e22"> | ||||
| 			<a id="help-button" target="_parent" href="manual"><button> ? </button></a> | ||||
| 		</div> | ||||
|      | ||||
|         <div id="h2e12"> | ||||
| 			<a id="legacy-button" href="/server-manager" target='_blank'><button>Legacy SM</button></a> | ||||
|         </div> | ||||
| 		<div id="h2e23"> | ||||
| 			% if ( not defined $c->session->{username} ) { | ||||
| 				<a target="_parent" href="login"><button class="login-button">Login</button></a> | ||||
| 			% } else { | ||||
| 				<a target="_parent" href="logout"><button class="login-button"><%= $c->session->{username} %> Logout</button></a> | ||||
| 			% } | ||||
| 		</div> | ||||
| 		<div id="flag-container"> | ||||
| 			<!-- The flag icon will be inserted here --> | ||||
| 		</div> | ||||
|     </div> | ||||
|     <div id="h2l2" class="infobar">  | ||||
| 	<div id="h2l2" class="infobar">  | ||||
| 		<div id="h2e21"> | ||||
| 			<b> | ||||
| 			<%= session 'SystemName' %>@<%= session 'DomainName' %></b>  | ||||
| 			</div> | ||||
| 				<div id="h2e22"> | ||||
| 				  <a target="_parent" href="manual">  <b> ? </b>  </a>  | ||||
| 			</div> | ||||
| 			<div id="h2e23"> | ||||
| 		%    if ( not defined $c->session->{username} ) { | ||||
| 				  <a target="_parent" href="login"><b>Login</b></a>  | ||||
| 		%    } else { | ||||
| 				  <a target="_parent" href="logout"><b><%= $c->session->{username} %> Logout</b></a>  | ||||
| 		%    } | ||||
| 			</div> | ||||
| 				<%= session 'SystemName' %>@<%= session 'DomainName' %></b>  | ||||
| 		</div> | ||||
| 		 | ||||
| 		 | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -79,9 +79,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'CONF' | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!--<div class='center'>--> | ||||
| 	%= submit_button $c->l('SAVE'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -47,9 +47,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'INST' | ||||
| 	<br><br> | ||||
|     <div class='center'> | ||||
|     <!-- <div class='center'>--> | ||||
| 	%= submit_button $c->l('yum_INSTALL_SOFTWARE'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -34,9 +34,9 @@ | ||||
|     	%=  hidden_field 'trt' => 'PSTU' | ||||
|     	%=  hidden_field 'reconf' => $yum_datas->{reconf} | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!-- <div class='center'>--> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -46,9 +46,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'REMO' | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!--<div class='center'>--> | ||||
| 	%= submit_button $c->l('REMOVE'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -33,9 +33,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'UPDT' | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!--<div class='center'>--> | ||||
| 	%= submit_button $c->l('yum_INSTALL_UPDATES'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ Summary: Sme server  navigation module : manager 2 | ||||
| %define name smeserver-manager | ||||
| Name: %{name} | ||||
| %define version 11.0.0 | ||||
| %define release 11 | ||||
| %define release 18 | ||||
| Version: %{version} | ||||
| Release: %{release}%{?dist} | ||||
| License: GPL | ||||
| @@ -108,6 +108,29 @@ true | ||||
| %defattr(-,root,root) | ||||
|  | ||||
| %changelog | ||||
| * Sun Aug 25 2024 Brian Read <brianr@koozali.org> 11.0.0-18.sme | ||||
| - Move flag to emojii from downloaded jpg. Fix singleton locale issue[SME: 12706] | ||||
|  | ||||
| * Thu Aug 22 2024 Brian Read <brianr@koozali.org> 11.0.0-17.sme | ||||
| - Left Align Software Install panels Submit button [SME: 12727] | ||||
|  | ||||
| * Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-16.sme | ||||
| - Typo uc DNF changed to lc dnf in Yum.pm [SME: 127245] | ||||
| - Monitor dnf running using dnf status file  | ||||
|  | ||||
| * Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-15.sme | ||||
| - Migrate SM2 Software installer panel from use of yum to dnf [SME: 12718] | ||||
|  | ||||
| * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-14.sme | ||||
| - Version skipped due to operator error! [SME: <none> ] | ||||
|  | ||||
| * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-13.sme | ||||
| - Fix sysles.css template - overwrote it by mistake [SME: 12706] | ||||
| - Also re-organised login and Legacy SM menus and help on top | ||||
|  | ||||
| * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-12.sme | ||||
| - correct positio of flag-icon [SME: 12706] | ||||
|  | ||||
| * Sat Jul 27 2024 Brian Read <brianr@koozali.org> 11.0.0-11.sme | ||||
| - Add in flag icon indication of locale [SME: 12706] | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user