Compare commits
	
		
			24 Commits
		
	
	
		
			1.1.7
			...
			cb07365020
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cb07365020 | |||
| 46cf0f1f4e | |||
| 5a0d96b6c6 | |||
| c0c8a43c77 | |||
| a91c21ecfd | |||
| 49f466f298 | |||
| f0171a0232 | |||
| c95880d22f | |||
| 2f99a07ef7 | |||
| 97f62b8ee8 | |||
| 198a83b4c7 | |||
| 803e7185d8 | |||
| 30361a9aae | |||
| 115e8367da | |||
| 0d61dd1725 | |||
| d7147b6c81 | |||
| 63ec0ebaa8 | |||
| f925665d23 | |||
| a1aa1c0d14 | |||
| ff97952f67 | |||
| f0ce402830 | |||
| 80147b69eb | |||
| 11d8475c8a | |||
| 8f684513fd | 
							
								
								
									
										86
									
								
								common.js
									
									
									
									
									
								
							
							
						
						| @@ -110,27 +110,33 @@ function check_vpn() { | |||||||
|   var url  = 'scan.php?op=check_vpn'; |   var url  = 'scan.php?op=check_vpn'; | ||||||
|   jQuery.get(url, function(data) { |   jQuery.get(url, function(data) { | ||||||
|         console.log('check_vpn: '+data); |         console.log('check_vpn: '+data); | ||||||
|         if (data=="1") { // save_vpn has finished |         if (data=="1") { // save_vpn has finished or VPN ON | ||||||
| 	  const vpn_div = document.getElementById("vpn"); | 	  const vpn_div = document.getElementById("vpn"); | ||||||
| 	  console.log(vpn_div); | 	  console.log('vpn_div: '+vpn_div); | ||||||
| 	  if (vpn_div) { | 	  if (vpn_div) { | ||||||
| 	  	vpn_div.innerHTML = 'VPN start process has finished'; | 	  	vpn_div.innerHTML = 'VPN start process has finished'; | ||||||
| 		//document.getElementById('installAppsBtn').click(); | 		setTimeout(function() { | ||||||
|  | 			document.getElementById('installAppsBtn').click(); | ||||||
|  | 		}, 2000); | ||||||
|  | 	  } | ||||||
|  | 	  else { | ||||||
|  | 		$('#pro_off').hide(); | ||||||
|  | 		$('#pro_on').show(); | ||||||
|  | 		$('#vpn_off').hide(); | ||||||
|  | 		$('#vpn_on').show(); | ||||||
|  | 		//document.getElementById('vpnToggle').checked = true; | ||||||
|  | 		//document.querySelector(".switch-label").textContent = "ON"; | ||||||
| 	  } | 	  } | ||||||
| 	} | 	} | ||||||
| 	else if (data=="2") { | 	else if (data=="2") { | ||||||
| 		document.getElementById('vpnToggle').checked = true; |  | ||||||
|   		document.querySelector(".switch-label").textContent = "ON"; |  | ||||||
|           $('#vpn_off').hide(); |  | ||||||
|           $('#vpn_on').show(); |  | ||||||
| 		$('#pro_off').hide(); | 		$('#pro_off').hide(); | ||||||
| 		$('#pro_on').show(); | 		$('#pro_on').show(); | ||||||
|         } |  | ||||||
|         else { |  | ||||||
| 		document.getElementById('vpnToggle').checked = false; |  | ||||||
|   		document.querySelector(".switch-label").textContent = "OFF"; |  | ||||||
| 		$('#vpn_on').hide(); | 		$('#vpn_on').hide(); | ||||||
| 		$('#vpn_off').show(); | 		$('#vpn_off').show(); | ||||||
|  | 		//document.getElementById('vpnToggle').checked = false; | ||||||
|  | 		//document.querySelector(".switch-label").textContent = "OFF"; | ||||||
|  |         } | ||||||
|  |         else { // data == 0 | ||||||
| 		$('#pro_on').hide(); | 		$('#pro_on').hide(); | ||||||
| 		$('#pro_off').show(); | 		$('#pro_off').show(); | ||||||
|         } |         } | ||||||
| @@ -211,7 +217,8 @@ function load_template(additional, block) { | |||||||
|   jQuery("div.deployment").each(function(index) { |   jQuery("div.deployment").each(function(index) { | ||||||
|         $(this).html(''); |         $(this).html(''); | ||||||
|   }); |   }); | ||||||
|   jQuery("#"+block).html('Loading '+additional+' template...'); |   //jQuery("#"+block).html('Loading '+additional+' template...'); | ||||||
|  |   jQuery("#"+block).html('<div class="loading">Loading...</div>'); | ||||||
|   var url  = 'scan.php?op=deployment&additional='+additional; |   var url  = 'scan.php?op=deployment&additional='+additional; | ||||||
|   jQuery.get(url, function(data) { |   jQuery.get(url, function(data) { | ||||||
| 	console.log('load_template: '+data); | 	console.log('load_template: '+data); | ||||||
| @@ -237,7 +244,8 @@ function reinstall(additional, block) { | |||||||
|   jQuery("div.deployment").each(function(index) { |   jQuery("div.deployment").each(function(index) { | ||||||
|         $(this).html(''); |         $(this).html(''); | ||||||
|   }); |   }); | ||||||
|   jQuery("#"+block).html('Loading '+additional+' template...'); |   //jQuery("#"+block).html('Loading '+additional+' template...'); | ||||||
|  |   jQuery("#"+block).html('<div class="loading">Loading...</div>'); | ||||||
|   var url  = 'scan.php?op=reinstall&additional='+additional; |   var url  = 'scan.php?op=reinstall&additional='+additional; | ||||||
|   jQuery.get(url, function(data) { |   jQuery.get(url, function(data) { | ||||||
| 	console.log('reinstall '+additional+': '+data); | 	console.log('reinstall '+additional+': '+data); | ||||||
| @@ -271,14 +279,14 @@ function uninstall(additional) { | |||||||
|   jQuery("div.deployment").each(function(index) { |   jQuery("div.deployment").each(function(index) { | ||||||
|         $(this).html(''); |         $(this).html(''); | ||||||
|   }); |   }); | ||||||
| 	data = '<fieldset><form action="#" method="post"><div class="row">YOU ARE GOING TO UNINSTALL '+additional.toUpperCase()+'.<br>ARE YOU SURE? IF YES, PLEASE CLICK ON THE BUTTON BELOW.<br><br></div><div class="row"><div class="mb-3"><button class="btn btn-lg btn-primary btn-block" type="button" onclick="confirm_uninstall(\''+additional+'\')">Uninstall</button></div></div></form></fieldset>'; | 	data = '<form action="#" method="post"><div class="row">YOU ARE GOING TO UNINSTALL '+additional.toUpperCase()+'.<br>ARE YOU SURE? IF YES, PLEASE CLICK ON THE BUTTON BELOW.<br><br></div><div class="row"><div class="mb-3"><button class="save-button" type="button" onclick="confirm_uninstall(\''+additional+'\')">Uninstall</button></div></div></form>'; | ||||||
| 	jQuery("#"+additional).html(data); | 	jQuery("#"+additional).html(data); | ||||||
| 	jQuery("#popupText").html(data); // manage2 | 	jQuery("#popupText").html(data); // manage2 | ||||||
| } | } | ||||||
|  |  | ||||||
| function confirm_uninstall(additional) { | function confirm_uninstall(additional) { | ||||||
|   jQuery("#"+additional).html('Loading...'); |   jQuery("#"+additional).html('<div class="loading">Loading...</div>'); | ||||||
|   jQuery("#popupText").html('Loading'); // manage2 |   jQuery("#popupText").html('<div class="loading">Loading...</div>'); // manage2 | ||||||
|   var url  = 'scan.php?op=uninstall&additional='+additional; |   var url  = 'scan.php?op=uninstall&additional='+additional; | ||||||
|   jQuery.get(url, function(data) { |   jQuery.get(url, function(data) { | ||||||
|         console.log('uninstall '+additional+': '+data); |         console.log('uninstall '+additional+': '+data); | ||||||
| @@ -406,53 +414,52 @@ function get_services() { | |||||||
|  |  | ||||||
| function get_proxy_html() { | function get_proxy_html() { | ||||||
|         proxy_html = ` |         proxy_html = ` | ||||||
| 	<fieldset> |  | ||||||
| 	<legend>Enable proxy</legend> |  | ||||||
|         <div class="input-group"> |  | ||||||
| 	<form class="form-install" action="#" method="post" id="save_vpn"> | 	<form class="form-install" action="#" method="post" id="save_vpn"> | ||||||
|  |         <div class="app-fields"> | ||||||
|  |         	<div class="app-field"> | ||||||
| 		<div class="row"> | 		<div class="row"> | ||||||
| 		    <div class="mb-3"> | 			<label for="vpn_domain">Please add domain url to download the VPN hash from:</label> | ||||||
| 				<label for="vpn_domain">Please add domain url to download the VPN hash from (default: https://portal.safebox.network):</label> | 		    <div class="input-container"> | ||||||
| 				<input type="text" class="form-control" name="VPN_DOMAIN" id="vpn_domain" value="https://portal.safebox.network"> | 				<input type="text" class="form-control" name="VPN_DOMAIN" id="vpn_domain" value="https://portal.safebox.network" size="40"> | ||||||
| 				<div class="invalid-feedback"> |  | ||||||
| 				Please enter a valid domain. |  | ||||||
| 		    </div> | 		    </div> | ||||||
| 		</div> | 		</div> | ||||||
| 		</div> | 		</div> | ||||||
|  |         	<div class="app-field"> | ||||||
| 		<div class="row"> | 		<div class="row"> | ||||||
| 		    <div class="mb-3"> |  | ||||||
| 			<label for="vpn_pass">Please type in the generated VPN passkey (8 digits):</label> | 			<label for="vpn_pass">Please type in the generated VPN passkey (8 digits):</label> | ||||||
|  | 		    <div class="input-container"> | ||||||
| 				<input type="text" class="form-control" name="VPN_PASS" id="vpn_pass" value="" maxlength="8" size="10"> | 				<input type="text" class="form-control" name="VPN_PASS" id="vpn_pass" value="" maxlength="8" size="10"> | ||||||
| 		    </div> | 		    </div> | ||||||
| 		</div> | 		</div> | ||||||
|  | 		</div> | ||||||
|  |         	<div class="app-field"> | ||||||
| 		<div class="row"> | 		<div class="row"> | ||||||
| 		    <div class="mb-3"> |  | ||||||
| 			<label for="letsencrypt_mail">Please add the letsencrypt mail address:</label> | 			<label for="letsencrypt_mail">Please add the letsencrypt mail address:</label> | ||||||
|  | 		    <div class="input-container"> | ||||||
| 				<input type="email" class="form-control" name="LETSENCRYPT_MAIL" id="letsencrypt_mail" value=""> | 				<input type="email" class="form-control" name="LETSENCRYPT_MAIL" id="letsencrypt_mail" value=""> | ||||||
| 				<div class="invalid-feedback"> |  | ||||||
| 				Please enter a valid email. |  | ||||||
| 		    </div> | 		    </div> | ||||||
| 		</div> | 		</div> | ||||||
| 		</div> | 		</div> | ||||||
|  |         	<div class="app-field"> | ||||||
| 		<div class="row"> | 		<div class="row"> | ||||||
| 		    <div class="mb-3"> |  | ||||||
| 			<label for="letsencrypt_servername">Please add letsencrypt server name (default is letsencrypt but you can add zerossl too):</label> | 			<label for="letsencrypt_servername">Please add letsencrypt server name (default is letsencrypt but you can add zerossl too):</label> | ||||||
|  | 		    <div class="input-container"> | ||||||
| 				<input type="text" class="form-control" name="LETSENCRYPT_SERVERNAME" id="letsencrypt_servername" value="letsencrypt"> | 				<input type="text" class="form-control" name="LETSENCRYPT_SERVERNAME" id="letsencrypt_servername" value="letsencrypt"> | ||||||
| 		    </div> | 		    </div> | ||||||
| 		</div> | 		</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
| 	<div class="row buttons"> | 	<div class="row buttons"> | ||||||
| 	    <div class="mb-3"> | 	    <div class="mb-3"> | ||||||
| 		<button class="btn btn-lg btn-primary btn-block" type="button" id="vpn_save_btn"> Save </button> | 		<button class="btn btn-lg btn-primary btn-block" type="button" id="vpn_save_btn"> Save </button> | ||||||
| 	    </div> | 	    </div> | ||||||
| 	</div> | 	</div> | ||||||
| 	</form> | 	</form> | ||||||
| 	</div> |  | ||||||
| 	</fieldset> |  | ||||||
| 	<script> | 	<script> | ||||||
| 	jQuery('#vpn_save_btn').click(function() { | 	jQuery('#vpn_save_btn').click(function() { | ||||||
| 		console.log('vpn save'); | 		console.log('vpn save'); | ||||||
| 		save_vpn(); | 		save_vpn(); | ||||||
| 		jQuery('#vpn').html('VPN start process in progress. Please wait...'); | 		jQuery('#vpn').html('<div class="loading">VPN start process in progress. Please wait...</div>'); | ||||||
| 	}); | 	}); | ||||||
| 	</script> | 	</script> | ||||||
|         `; |         `; | ||||||
| @@ -480,8 +487,17 @@ function get_containers() { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function get_version() { | ||||||
|  |   var url  = 'scan.php?op=version'; | ||||||
|  |   jQuery.get(url, function(data) { | ||||||
|  | 	console.log('version: '+data); | ||||||
|  | 	jQuery('#logo').attr('title',data); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
| jQuery(document).ready(function(){ | jQuery(document).ready(function(){ | ||||||
|  |  | ||||||
|  | 	get_version(); | ||||||
| 	get_repositories(); | 	get_repositories(); | ||||||
| 	get_deployments(); | 	get_deployments(); | ||||||
| 	get_system(); | 	get_system(); | ||||||
| @@ -514,19 +530,19 @@ jQuery(document).ready(function(){ | |||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	jQuery('#update_btn').click(function() { | 	jQuery('#update_btn').click(function() { | ||||||
| 		jQuery('#updates').html('Looking for updates... Please wait...'); | 		jQuery('#updates').html('<div class="loading">Looking for updates...</div>'); | ||||||
| 		get_updates(); | 		get_updates(); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	jQuery('#add_repo').submit(function() { | 	jQuery('#add_repo').submit(function() { | ||||||
| 		jQuery('#repositories').html('Loading...'); | 		jQuery('#repositories').html('<div class="loading">Loading...</div>'); | ||||||
| 		add_repository(); | 		add_repository(); | ||||||
| 		return false; | 		return false; | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	jQuery('#save_vpn').submit(function() { | 	jQuery('#save_vpn').submit(function() { | ||||||
| 		save_vpn(); | 		save_vpn(); | ||||||
| 		jQuery('#vpn').html('Loading...'); | 		jQuery('#vpn').html('<div class="loading">Loading...</div>'); | ||||||
| 		return false; | 		return false; | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								img/grey-box.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										14
									
								
								img/logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								img/monitor.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 50 KiB | 
							
								
								
									
										
											BIN
										
									
								
								img/off.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 914 B | 
							
								
								
									
										
											BIN
										
									
								
								img/on.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 992 B | 
							
								
								
									
										
											BIN
										
									
								
								img/yellow-box.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										13
									
								
								index.html
									
									
									
									
									
								
							
							
						
						| @@ -3,21 +3,26 @@ | |||||||
| <head> | <head> | ||||||
| <meta charset="UTF-8"> | <meta charset="UTF-8"> | ||||||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|  | <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> | ||||||
|  | <meta http-equiv="Pragma" content="no-cache" /> | ||||||
|  | <meta http-equiv="Expires" content="0" /> | ||||||
| <title>Safebox installer</title> | <title>Safebox installer</title> | ||||||
| <style> | <style> | ||||||
| body, html { | html, body { | ||||||
|     margin: 0; |     margin: 0; | ||||||
|     padding: 0; |     padding: 0; | ||||||
|     height: 100%; |     height: 100%; | ||||||
|  |     overflow: hidden; | ||||||
| } | } | ||||||
| iframe { | iframe { | ||||||
|     width: 100%; |     display: block; | ||||||
|     height: 100%; |     width: 100vw; | ||||||
|  |     height: 100vh; | ||||||
|     border: none; |     border: none; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     <iframe src="scan.html"></iframe> |     <iframe src="scan.html?t=1"></iframe> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
							
								
								
									
										145
									
								
								install.html
									
									
									
									
									
								
							
							
						
						| @@ -1,27 +1,33 @@ | |||||||
| <!doctype html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="hu"> | ||||||
| <head> | <head> | ||||||
| <!-- Required meta tags --> | <meta charset="UTF-8" /> | ||||||
| <meta charset="utf-8"> | <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||||
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> | ||||||
| <title>INSTALLER TOOL</title> | <meta http-equiv="Pragma" content="no-cache" /> | ||||||
| <!-- Bootstrap CSS --> | <meta http-equiv="Expires" content="0" /> | ||||||
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> | <title>Safebox - INSTALLER TOOL</title> | ||||||
| <!-- Custom styles for this template --> | <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Switzer:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap"/> | ||||||
| <link href="installer.css?t=3" rel="stylesheet"> | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/> | ||||||
|  | <link rel="stylesheet" href="style.css?t=1" /> | ||||||
| </head> | </head> | ||||||
| <body id="installer" class="text-center"> | <body id="installer"> | ||||||
| <div class="container-fluid"> |   <div class="main" > | ||||||
| <div class="col-md-12"> |     <div id="myAppsContainer"> | ||||||
|  | 	      <div class="logo"> | ||||||
|  | 		<img src="/img/logo.svg" alt="Safebox"/> | ||||||
|  | 		<span>Safebox</span> | ||||||
|  | 	      </div> | ||||||
|  | 		<h3 style="text-align:center">No any previous deployed environment has found</h3> | ||||||
|  | 		<div class="main-header"> | ||||||
|  | 			<h1>Base settings</h1> | ||||||
|  | 		</div> | ||||||
|  |  | ||||||
| <form class="form-install" action="install.php" method="post"> | <form class="form-install" action="install.php" method="post"> | ||||||
|  | <!-- base settings --> | ||||||
| <h1>No any previous deployed environment found</h1> | <div class="input-row"> | ||||||
|  |  | ||||||
| <fieldset> |  | ||||||
| <legend>Base settings</legend> |  | ||||||
| <div class="row"> |  | ||||||
|     <div class="mb-3"> |  | ||||||
| 	<label for="user_auth">User auth (homeguard) enable?</label> | 	<label for="user_auth">User auth (homeguard) enable?</label> | ||||||
|  | 	<div class="input-container"> | ||||||
| 		<select class="custom-select d-block w-100" name="USER_AUTH" id="user_auth"> | 		<select class="custom-select d-block w-100" name="USER_AUTH" id="user_auth"> | ||||||
| 		<option value="yes">Yes</option> | 		<option value="yes">Yes</option> | ||||||
| 		<option value="no" selected>No</option> | 		<option value="no" selected>No</option> | ||||||
| @@ -29,30 +35,30 @@ | |||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| <div id="div_user_auth" class="hidden"> | <div id="div_user_auth" class="hidden"> | ||||||
| 	<div class="row"> | 	<div class="input-row"> | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 		<label for="auth_username">Username:</label> | 		<label for="auth_username">Username:</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 		<input type="text" class="form-control" name="AUTH_USERNAME" id="auth_username" value="" maxlength="20" size="20"> | 		<input type="text" class="form-control" name="AUTH_USERNAME" id="auth_username" value="" maxlength="20" size="20"> | ||||||
| 	    	</div> | 	    	</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div class="row"> | 	<div class="input-row"> | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 		<label for="auth_password">Password:</label> | 		<label for="auth_password">Password:</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 		<input type="text" class="form-control" name="AUTH_PASSWORD" id="auth_password" value="" maxlength="20" size="20"> | 		<input type="text" class="form-control" name="AUTH_PASSWORD" id="auth_password" value="" maxlength="20" size="20"> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div class="row"> | 	<div class="input-row"> | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 		<label for="auth_role">Role:</label> | 		<label for="auth_role">Role:</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 		<select class="custom-select d-block w-100" name="AUTH_ROLE" id="auth_role"> | 		<select class="custom-select d-block w-100" name="AUTH_ROLE" id="auth_role"> | ||||||
| 		<option value="admin">Admin</option> | 		<option value="admin">Admin</option> | ||||||
| 		</select> | 		</select> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| <div class="row"> | <div class="input-row"> | ||||||
|     <div class="mb-3"> |  | ||||||
| 	<label for="vpn">Proxy enable?</label> | 	<label for="vpn">Proxy enable?</label> | ||||||
|  | 	<div class="input-container"> | ||||||
| 		<select class="custom-select d-block w-100" name="VPN_PROXY" id="vpn"> | 		<select class="custom-select d-block w-100" name="VPN_PROXY" id="vpn"> | ||||||
| 		<option value="yes">Yes</option> | 		<option value="yes">Yes</option> | ||||||
| 		<option value="no" selected>No</option> | 		<option value="no" selected>No</option> | ||||||
| @@ -60,63 +66,57 @@ | |||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| <div id="div_vpn" class="hidden"> | <div id="div_vpn" class="hidden"> | ||||||
| 	<div class="row"> | 	<div class="input-row"> | ||||||
| 	    <div class="mb-3"> | 		<label for="vpn_domain">Please add domain url to download the VPN hash from:</label> | ||||||
| 			<label for="vpn_domain">Please add domain url to download the VPN hash from (default: https://portal.safebox.network):</label> | 		<div class="input-container"> | ||||||
| 			<input type="text" class="form-control" name="VPN_DOMAIN" id="vpn_domain" value="https://portal.safebox.network"> | 			<input type="text" class="form-control" name="VPN_DOMAIN" id="vpn_domain" value="https://portal.safebox.network" placeholder="https://portal.safebox.network" size="40"> | ||||||
| 			<div class="invalid-feedback"> |  | ||||||
| 			Please enter a valid domain. |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	</div> | 	<div class="input-row"> | ||||||
| 	<div class="row"> |  | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 		<label for="vpn_pass">Please type in the generated VPN passkey (8 digits):</label> | 		<label for="vpn_pass">Please type in the generated VPN passkey (8 digits):</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 			<input type="text" class="form-control" name="VPN_PASS" id="vpn_pass" value="" maxlength="8" size="10"> | 			<input type="text" class="form-control" name="VPN_PASS" id="vpn_pass" value="" maxlength="8" size="10"> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div class="row"> | 	<div class="input-row"> | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 		<label for="letsencrypt_mail">Please add the letsencrypt mail address:</label> | 		<label for="letsencrypt_mail">Please add the letsencrypt mail address:</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 			<input type="email" class="form-control" name="LETSENCRYPT_MAIL" id="letsencrypt_mail" value=""> | 			<input type="email" class="form-control" name="LETSENCRYPT_MAIL" id="letsencrypt_mail" value=""> | ||||||
| 			<div class="invalid-feedback"> |  | ||||||
| 			Please enter a valid email. |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	</div> | 	<div class="input-row"> | ||||||
| 	<div class="row"> |  | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 		<label for="letsencrypt_servername">Please add letsencrypt server name (default is letsencrypt but you can add zerossl too):</label> | 		<label for="letsencrypt_servername">Please add letsencrypt server name (default is letsencrypt but you can add zerossl too):</label> | ||||||
| 			<input type="text" class="form-control" name="LETSENCRYPT_SERVERNAME" id="letsencrypt_servername" value="letsencrypt"> | 		<div class="input-container"> | ||||||
|  | 			<input type="text" class="form-control" name="LETSENCRYPT_SERVERNAME" id="letsencrypt_servername" value="letsencrypt" placeholder="letsencrypt"> | ||||||
| 	   	</div> | 	   	</div> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| <div class="row"> | <div class="input-row"> | ||||||
|     <div class="mb-3"> |  | ||||||
| 	<label for="diagnostic">Diagnostic mode enable?</label> | 	<label for="diagnostic">Diagnostic mode enable?</label> | ||||||
|  | 	<div class="input-container"> | ||||||
| 		<select class="custom-select d-block w-100" name="DIAGNOSTIC" id="diagnostic"> | 		<select class="custom-select d-block w-100" name="DIAGNOSTIC" id="diagnostic"> | ||||||
| 		<option value="yes">Yes</option> | 		<option value="yes">Yes</option> | ||||||
| 		<option value="no" selected>No</option> | 		<option value="no" selected>No</option> | ||||||
| 		</select> | 		</select> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| </fieldset> | <!-- base settings end --> | ||||||
|  | <br> | ||||||
| <fieldset> | <br> | ||||||
| <legend><a href="javascript:void()" id="advanced">Advanced settings</a></legend> | 		<div class="main-header"> | ||||||
|  | 			<h1 id="advanced" style="cursor:pointer">Advanced settings</h1> | ||||||
|  | 		</div> | ||||||
|  | <!-- advanced settings --> | ||||||
| <div id="advanced_div" style="display:none"> | <div id="advanced_div" style="display:none"> | ||||||
| <div class="row"> | 	<div class="input-row"> | ||||||
|     <div class="mb-3"> |  | ||||||
| 		<label for="registry">Please fill in the docker registry name (default:safebox):</label> | 		<label for="registry">Please fill in the docker registry name (default:safebox):</label> | ||||||
| 		<input type="registry" class="form-control" name="DOCKER_REGISTRY_URL" id="registry" value="safebox" required> | 		<div class="input-container"> | ||||||
| 		<div class="invalid-feedback"> | 			<input type="registry" class="form-control" name="DOCKER_REGISTRY_URL" id="registry" value="safebox" placeholder="safebox" required> | ||||||
| 		Please enter a valid registry url. |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | 	<div class="input-row"> | ||||||
| <div class="row"> |  | ||||||
|     <div class="mb-3"> |  | ||||||
| 		<label for="smarthost">Smarthost proxy?</label> | 		<label for="smarthost">Smarthost proxy?</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 			<select class="custom-select d-block w-100" name="SMARTHOST_PROXY" id="smarthost"> | 			<select class="custom-select d-block w-100" name="SMARTHOST_PROXY" id="smarthost"> | ||||||
| 			<option value="yes" selected>Yes</option> | 			<option value="yes" selected>Yes</option> | ||||||
| 			<option value="no">No</option> | 			<option value="no">No</option> | ||||||
| @@ -124,18 +124,15 @@ | |||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div id="div_smarthost"> | 	<div id="div_smarthost"> | ||||||
| 	<div class="row"> | 		<div class="input-row"> | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 			<label for="domain">Please fill in the domain name</label> | 			<label for="domain">Please fill in the domain name</label> | ||||||
|  | 			<div class="input-container"> | ||||||
| 				<input type="domain" class="form-control" name="DOMAIN" id="domain" value="localhost"> | 				<input type="domain" class="form-control" name="DOMAIN" id="domain" value="localhost"> | ||||||
| 		<div class="invalid-feedback"> |  | ||||||
| 		Please enter a valid domain. |  | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 		<div class="input-row"> | ||||||
| 	<div class="row"> |  | ||||||
| 	    <div class="mb-3"> |  | ||||||
| 			<label for="local_backend">Would you like to run local backend?</label> | 			<label for="local_backend">Would you like to run local backend?</label> | ||||||
|  | 			<div class="input-container"> | ||||||
| 				<select class="custom-select d-block w-100" name="LOCAL_BACKEND" id="local_backend"> | 				<select class="custom-select d-block w-100" name="LOCAL_BACKEND" id="local_backend"> | ||||||
| 				<option value="yes">Yes</option> | 				<option value="yes">Yes</option> | ||||||
| 				<option value="no" selected>No</option> | 				<option value="no" selected>No</option> | ||||||
| @@ -143,18 +140,18 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| <div class="row"> | 	<div class="input-row"> | ||||||
|     <div class="mb-3"> |  | ||||||
| 		<label for="localproxy">Local proxy?</label> | 		<label for="localproxy">Local proxy?</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 			<select class="custom-select d-block w-100" name="LOCAL_PROXY" id="localproxy"> | 			<select class="custom-select d-block w-100" name="LOCAL_PROXY" id="localproxy"> | ||||||
| 			<option value="yes" selected>Yes</option> | 			<option value="yes" selected>Yes</option> | ||||||
| 			<option value="no">No</option> | 			<option value="no">No</option> | ||||||
| 			</select> | 			</select> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| <div class="row"> | 	<div class="input-row"> | ||||||
|     <div class="mb-3"> |  | ||||||
| 		<label for="cron">Cron?</label> | 		<label for="cron">Cron?</label> | ||||||
|  | 		<div class="input-container"> | ||||||
| 			<select class="custom-select d-block w-100" name="CRON" id="cron"> | 			<select class="custom-select d-block w-100" name="CRON" id="cron"> | ||||||
| 			<option value="yes">Yes</option> | 			<option value="yes">Yes</option> | ||||||
| 			<option value="no">No</option> | 			<option value="no">No</option> | ||||||
| @@ -162,14 +159,12 @@ | |||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| </fieldset> | <!-- advanced settings end --> | ||||||
| <br> | 	<button class="save-button" type="submit">Start install</button> | ||||||
| <button class="btn btn-lg btn-primary btn-block" type="submit">Start install</button> |  | ||||||
| </form> | </form> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| <br> |  | ||||||
| <br> |  | ||||||
| <!-- Optional JavaScript --> | <!-- Optional JavaScript --> | ||||||
| <!-- jQuery first, then Popper.js, then Bootstrap JS --> | <!-- jQuery first, then Popper.js, then Bootstrap JS --> | ||||||
| <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | ||||||
|   | |||||||
							
								
								
									
										173
									
								
								install.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,173 @@ | |||||||
|  |  | ||||||
|  | function updateProgress(percentage) { | ||||||
|  |     // Clamp percentage between 0 and 99.9 (never reach 100) | ||||||
|  |     percentage = Math.max(0, Math.min(99.9, percentage)); | ||||||
|  |      | ||||||
|  |     progressBar.style.width = percentage + '%'; | ||||||
|  |     progressText.textContent = Math.round(percentage) + '%'; | ||||||
|  |     currentProgress = percentage; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function setProgress(percentage) { | ||||||
|  |     clearInterval(progressInterval); | ||||||
|  |     updateProgress(percentage); | ||||||
|  |     startProgress(60000); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function startProgress(duration) { | ||||||
|  |     clearInterval(progressInterval); | ||||||
|  |     const startTime = Date.now() - (currentProgress / 100) * duration; | ||||||
|  |      | ||||||
|  |     progressInterval = setInterval(() => { | ||||||
|  | 	const elapsed = Date.now() - startTime; | ||||||
|  | 	// Use exponential approach to 100% - gets slower as it approaches | ||||||
|  | 	let progress = (1 - Math.exp(-4 * elapsed / duration)) * 100; | ||||||
|  | 	 | ||||||
|  | 	// Ensure it never reaches 100% | ||||||
|  | 	progress = Math.min(progress, 99.9); | ||||||
|  | 	 | ||||||
|  | 	updateProgress(progress); | ||||||
|  | 	 | ||||||
|  | 	// Stop when we've been running for 60+ seconds | ||||||
|  | 	if (elapsed >= duration) { | ||||||
|  | 	    clearInterval(progressInterval); | ||||||
|  | 	} | ||||||
|  |     }, 100); // Update every 100ms | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function resetProgress() { | ||||||
|  |     clearInterval(progressInterval); | ||||||
|  |     updateProgress(0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Example: Simulate loading with custom speeds | ||||||
|  | function simulateLoading(duration = 3000) { | ||||||
|  |     clearInterval(progressInterval); | ||||||
|  |     const startTime = Date.now(); | ||||||
|  |      | ||||||
|  |     progressInterval = setInterval(() => { | ||||||
|  | 	const elapsed = Date.now() - startTime; | ||||||
|  | 	const progress = Math.min((elapsed / duration) * 100, 99.9); | ||||||
|  | 	 | ||||||
|  | 	updateProgress(progress); | ||||||
|  | 	 | ||||||
|  | 	if (elapsed >= duration) { | ||||||
|  | 	    clearInterval(progressInterval); | ||||||
|  | 	} | ||||||
|  |     }, 16); // ~60fps | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function redirectToInstall() { | ||||||
|  | 	setProgress(100); | ||||||
|  | 	window.location.href = 'install.html?t='+Date.now(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function redirectToManage() { | ||||||
|  | 	setProgress(100); | ||||||
|  | 	window.location.href = 'manage.html?t='+Date.now(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function start_system() { | ||||||
|  |   var url  = 'scan.php?op=system'; | ||||||
|  |   $.get(url, function(data){ | ||||||
|  |     console.log('start_system: '+data); | ||||||
|  |     if (data=='OK') { | ||||||
|  |       $("#info").html('Scanning for previous install. Please wait...'); | ||||||
|  |       check_system(); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       $("#info").html('Scanning for previous install has aborted...'); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function check_system() { | ||||||
|  |   var url  = 'scan.php?op=check_system'; | ||||||
|  |   $.get(url, function(data){ | ||||||
|  |     console.log('check_system: '+data); | ||||||
|  |     if (data=='NEW') { | ||||||
|  |       $("#info").html('No previous install has found...'); | ||||||
|  |       setTimeout(redirectToInstall, 3000); | ||||||
|  |     } | ||||||
|  |     else if (data=='EXISTS') { | ||||||
|  |       $("#info").html('Previous install has found...'); | ||||||
|  |       setProgress(80); | ||||||
|  |       setTimeout(redirectToManage, 3000); | ||||||
|  |     } | ||||||
|  |     else if (data=='WAIT') { | ||||||
|  |       setTimeout(check_system, 1000); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  | 	    // UNEXPECTED ERROR | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function check_redis() { | ||||||
|  |  | ||||||
|  |   var url  = 'scan.php?op=redis'; | ||||||
|  |   $.get(url, function(data){ | ||||||
|  |     console.log('check_redis: '+data); | ||||||
|  |     if (data=='OK') { | ||||||
|  |       $("#info").html('Redis server - OK'); | ||||||
|  |       check_install(); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       $("#info").html('Redis server is not available...'); | ||||||
|  |       setTimeout(check_redis, 1000); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function check_directory() { | ||||||
|  |  | ||||||
|  |   var url  = 'scan.php?op=directory'; | ||||||
|  |   $.get(url, function(data){ | ||||||
|  |     console.log('check_directory: '+data); | ||||||
|  |     if (data=='OK') { | ||||||
|  |       $("#info").html('Connection is ready - OK'); | ||||||
|  |       check_install(); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       $("#info").html('Shared directory is not available...'); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function check_interface() { | ||||||
|  |  | ||||||
|  |   var url  = 'scan.php?op=get_interface'; | ||||||
|  |   $.get(url, function(data){ | ||||||
|  |     console.log('check_interface: '+data); | ||||||
|  |     if (data=='redis') { | ||||||
|  |   	check_redis(); | ||||||
|  |     } | ||||||
|  |     else if (data=='directory') { | ||||||
|  |   	check_directory(); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  | 	$("#info").html('Invalid interface definition...'); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function check_install() { | ||||||
|  |  | ||||||
|  |     console.log('install: '+install); | ||||||
|  |     if (install==1) { | ||||||
|  | 	  var url  = 'scan.php?op=check_install'; | ||||||
|  | 	  $.get(url, function(data){ | ||||||
|  | 	    console.log('check_install:'+data+' counter: '+counter); | ||||||
|  | 	    if (data=='INSTALLED') { | ||||||
|  | 		redirectToManage(); | ||||||
|  | 	    } | ||||||
|  | 	    else { | ||||||
|  | 	      counter+=1 | ||||||
|  | 	      $("#info").html('Please wait ...'); | ||||||
|  | 	      setTimeout(check_install, 1000); | ||||||
|  | 	    } | ||||||
|  | 	  }); | ||||||
|  |     } | ||||||
|  |     else start_system(); // scan | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										118
									
								
								install.php
									
									
									
									
									
								
							
							
						
						| @@ -46,7 +46,7 @@ else { | |||||||
| 	$header_text="Installing in progress... Please wait..."; | 	$header_text="Installing in progress... Please wait..."; | ||||||
| 	//$key = "install:".date("YmdHis"); | 	//$key = "install:".date("YmdHis"); | ||||||
| 	$key = "install"; | 	$key = "install"; | ||||||
| 	if (set_output($key,$json)) echo "OK"; | 	if (set_output($key,$json)) echo ""; | ||||||
| 	else echo "ERROR"; | 	else echo "ERROR"; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -61,25 +61,33 @@ echo "<pre>".$output."</pre>"; | |||||||
| //echo $output; | //echo $output; | ||||||
| */ | */ | ||||||
|  |  | ||||||
| ?> | ?><!DOCTYPE html> | ||||||
| <!doctype html> |  | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
| <!-- Required meta tags --> |   <meta charset="UTF-8" /> | ||||||
| <meta charset="utf-8"> |   <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||||
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |   <title>Safebox - INSTALLER TOOL</title> | ||||||
| <title>INSTALLER TOOL</title> |   <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Switzer:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap"/> | ||||||
| <!-- Bootstrap CSS --> |   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/> | ||||||
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> |   <link rel="stylesheet" href="style.css?t=4" /> | ||||||
| <!-- Custom styles for this template --> |  | ||||||
| <link href="installer.css?t=1" rel="stylesheet"> |  | ||||||
| </head> | </head> | ||||||
| <body id="install" class="text-center"> | <body id="install" class="text-center"> | ||||||
| <div class="container-fluid"> |   <div class="main"> | ||||||
| <div class="col-md-12"> |     <div id="myAppsContainer"> | ||||||
| 	<h1><?php echo $header_text?></h1> | 	<div class="logo" style="margin:100px 0px 20px 0px;"> | ||||||
| 	<div id="redis"></div> | 		<img src="/img/logo.svg" alt="Safebox"/> | ||||||
| 	<div id="response"></div> | 		<span>Safebox</span> | ||||||
|  | 	</div> | ||||||
|  | 	<div class="progress-box"> | ||||||
|  | 		<div class="progress-title"><?php echo $header_text?></div> | ||||||
|  | 		<div class="progress-description" id="info"></div> | ||||||
|  | 		<div class="progress-container-shadow"> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="progress-container"> | ||||||
|  | 			<div class="progress-bar" id="progressBar"></div> | ||||||
|  | 			<div class="progress-text" id="progressText">0%</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| <!-- Optional JavaScript --> | <!-- Optional JavaScript --> | ||||||
| @@ -87,80 +95,20 @@ echo "<pre>".$output."</pre>"; | |||||||
| <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | ||||||
| <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> | ||||||
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> | ||||||
|  | <script src="install.js?t=7"></script> | ||||||
| <script> | <script> | ||||||
| $(function() { | const progressBar = document.getElementById('progressBar'); | ||||||
|  | const progressText = document.getElementById('progressText'); | ||||||
|  | let currentProgress = 0; | ||||||
|  | let progressInterval; | ||||||
|  | let install = 1; | ||||||
|  |  | ||||||
| function redirectToManage() { | // Initialize | ||||||
|     window.location.href = 'manage.html'; | updateProgress(0); | ||||||
| } | startProgress(90000);// 90 seconds | ||||||
|  |  | ||||||
| function check_install() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=check_install&key=<?php echo $key;?>'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_install:'+data+' counter: '+counter); |  | ||||||
|     if (data=='INSTALLED') { |  | ||||||
| 	redirectToManage(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       counter+=1 |  | ||||||
|       $("#response").html('Please wait... ' + counter); |  | ||||||
|       setTimeout(check_install, 1000); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_redis() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=redis'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_redis: '+data); |  | ||||||
|     if (data=='OK') { |  | ||||||
|       $("#redis").html('Redis server - OK'); |  | ||||||
|       check_install(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       $("#redis").html('Redis server is not available...'); |  | ||||||
|       setTimeout(check_redis, 1000); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_directory() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=directory'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_directory: '+data); |  | ||||||
|     if (data=='OK') { |  | ||||||
|       $("#redis").html('Connection is ready - OK'); |  | ||||||
|       check_install(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       $("#redis").html('Shared directory is not available...'); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_interface() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=get_interface'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_interface: '+data); |  | ||||||
|     if (data=='redis') { |  | ||||||
|   	check_redis(); |  | ||||||
|     } |  | ||||||
|     else if (data=='directory') { |  | ||||||
|   	check_directory(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
| 	$("#redis").html('Invalid interface definition...'); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| check_interface(); | check_interface(); | ||||||
| counter=0; | counter=0; | ||||||
| }); |  | ||||||
| </script> | </script> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
							
								
								
									
										746
									
								
								manage.html
									
									
									
									
									
								
							
							
						
						| @@ -3,683 +3,22 @@ | |||||||
| <head> | <head> | ||||||
| <meta charset="UTF-8" /> | <meta charset="UTF-8" /> | ||||||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||||
|  | <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> | ||||||
|  | <meta http-equiv="Pragma" content="no-cache" /> | ||||||
|  | <meta http-equiv="Expires" content="0" /> | ||||||
| <title>Safebox</title> | <title>Safebox</title> | ||||||
|   <link href="https://fonts.googleapis.com/css2?family=Switzer:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap" rel="stylesheet" /> | <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Switzer:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap"/> | ||||||
|   <style> |  | ||||||
|     :root { |  | ||||||
|       --highlight-color: #F9DB54; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     body { |  | ||||||
|       margin: 0; |  | ||||||
|       font-family: 'Switzer', sans-serif; |  | ||||||
|       font-weight: 500; |  | ||||||
|       font-size: 16px; |  | ||||||
|       background-color: #000; |  | ||||||
|       color: white; |  | ||||||
|       display: flex; |  | ||||||
|       height: 100vh; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     h4 { |  | ||||||
| 	font-size: 16px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	table {border: 1px solid var(--highlight-color); width:100%;} |  | ||||||
| 	table th {padding-left: 20px; text-align: left; color: var(--highlight-color); width: 25%;} |  | ||||||
| 	table td {padding-left: 20px; text-align:left; width: 25%;} |  | ||||||
|  |  | ||||||
|     .sidebar { |  | ||||||
|       width: 250px; |  | ||||||
|       background-color: #101214; |  | ||||||
|       display: flex; |  | ||||||
|       flex-direction: column; |  | ||||||
|       justify-content: space-between; |  | ||||||
|       padding: 20px 0; |  | ||||||
|       margin: 20px; |  | ||||||
|       border-radius: 20px; |  | ||||||
|       transition: width 0.3s; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .logo { |  | ||||||
|       text-align: center; |  | ||||||
|       margin-bottom: 40px; |  | ||||||
|       font-size: 24px; |  | ||||||
|       font-weight: bold; |  | ||||||
|       display: flex; |  | ||||||
|       align-items: center; |  | ||||||
|       justify-content: center; |  | ||||||
|       gap: 10px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .logo img { |  | ||||||
|       height: 30px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu { |  | ||||||
|       display: flex; |  | ||||||
|       flex-direction: column; |  | ||||||
|       gap: 5px; |  | ||||||
|       padding: 0 10px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .vpn-item { |  | ||||||
|       display: flex; |  | ||||||
|       align-items: center; |  | ||||||
|       gap: 10px; |  | ||||||
|       padding: 10px 20px; |  | ||||||
|       cursor: pointer; |  | ||||||
|       color: white; |  | ||||||
|       transition: color 0.3s; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item { |  | ||||||
|       display: flex; |  | ||||||
|       align-items: center; |  | ||||||
|       gap: 10px; |  | ||||||
|       padding: 10px 20px; |  | ||||||
|       cursor: pointer; |  | ||||||
|       color: white; |  | ||||||
|       transition: color 0.3s; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item:hover { |  | ||||||
|       color: var(--highlight-color); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item i { |  | ||||||
|       font-size: 18px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item span { |  | ||||||
|       display: inline; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item img { |  | ||||||
|       width: 24px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item.active { |  | ||||||
|       background-color: var(--highlight-color); |  | ||||||
|       color: black; |  | ||||||
|       border-radius: 10px; |  | ||||||
|       font-weight: bold; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .menu-item.active:hover { |  | ||||||
|       color: black; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| .menu-item span.arrow { |  | ||||||
|   margin-left: auto; |  | ||||||
|   color: gray; |  | ||||||
|   font-size: 20px; |  | ||||||
|   transition: transform 0.3s ease; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .menu-item.open .arrow { |  | ||||||
|   transform: rotate(180deg); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .submenu { |  | ||||||
|   display: none; |  | ||||||
|   margin-left: 40px; |  | ||||||
|   flex-direction: column; |  | ||||||
|   margin-bottom: 10px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .submenu-item { |  | ||||||
|   padding: 5px 14px; |  | ||||||
|   font-size: 14px; |  | ||||||
|   color: #ffffff; |  | ||||||
|   cursor: pointer; |  | ||||||
|   border-radius: 10px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .submenu-item:hover { |  | ||||||
|   color: #000000; |  | ||||||
|   background-color: var(--highlight-color); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Switch container */ |  | ||||||
| .switch { |  | ||||||
|   position: relative; |  | ||||||
|   display: inline-block; |  | ||||||
|   width: 60px; |  | ||||||
|   height: 26px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Hide native checkbox */ |  | ||||||
| .switch input { |  | ||||||
|   opacity: 0; |  | ||||||
|   width: 0; |  | ||||||
|   height: 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Slider background */ |  | ||||||
| .slider-text { |  | ||||||
|   position: absolute; |  | ||||||
|   top: 0; |  | ||||||
|   left: 0; |  | ||||||
|   right: 0; |  | ||||||
|   bottom: 0; |  | ||||||
|   background-color: #ccc; |  | ||||||
|   border-radius: 26px; |  | ||||||
|   transition: background-color 0.3s; |  | ||||||
|   display: flex !important; |  | ||||||
|   align-items: center; |  | ||||||
|   justify-content: flex-end; /* default: OFF on the right */ |  | ||||||
|   padding: 0 8px; |  | ||||||
|   font-size: 12px; |  | ||||||
|   font-weight: bold; |  | ||||||
|   color: #fff; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Circle */ |  | ||||||
| .slider-text::before { |  | ||||||
|   content: ""; |  | ||||||
|   position: absolute; |  | ||||||
|   height: 22px; |  | ||||||
|   width: 22px; |  | ||||||
|   left: 2px; |  | ||||||
|   top: 2px; |  | ||||||
|   background-color: white; |  | ||||||
|   border-radius: 50%; |  | ||||||
|   transition: transform 0.3s; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Checked: move dot, change background and text alignment */ |  | ||||||
| .switch input:checked + .slider-text { |  | ||||||
|   background-color: #4CAF50; |  | ||||||
|   justify-content: flex-start; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Dot animation */ |  | ||||||
| .switch input:checked + .slider-text::before { |  | ||||||
|   transform: translateX(34px); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Status label */ |  | ||||||
| .status-label { |  | ||||||
|   font-size: 12px; |  | ||||||
|   color: #888; |  | ||||||
|   min-width: 28px; |  | ||||||
|   text-align: left; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|     .details { |  | ||||||
|       color: white; |  | ||||||
|       text-decoration: none; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .yellow-row { |  | ||||||
| 	max-width:250px; |  | ||||||
| 	display: flex; |  | ||||||
| 	align-items: flex-start; |  | ||||||
| 	box-sizing: border-box; |  | ||||||
|         margin: 0px; |  | ||||||
| 	width: 100%; |  | ||||||
| 	padding: 0 20px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .yellow-box { |  | ||||||
|       background-color: var(--highlight-color); |  | ||||||
|       color: black; |  | ||||||
|       text-align: left; |  | ||||||
|       margin: 0px; |  | ||||||
|       padding: 10px 18px; |  | ||||||
|       border-radius: 20px 20px 0px 20px; |  | ||||||
|       font-weight: bold; |  | ||||||
|       font-size: 12px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .yellow-corner { |  | ||||||
| 	padding:0px; |  | ||||||
| 	border: 0px; |  | ||||||
| 	display: flex; |  | ||||||
| 	margin: 0px; |  | ||||||
| 	margin-top: auto; |  | ||||||
| 	align-items: flex-end; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .main { |  | ||||||
|       flex: 1; |  | ||||||
|       padding: 30px; |  | ||||||
|       display: flex; |  | ||||||
|       flex-direction: column; |  | ||||||
|       overflow-y: auto; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	#appsContainer { |  | ||||||
| 	  display: flex; |  | ||||||
| 	  flex-wrap: wrap; |  | ||||||
| 	  gap: 16px; |  | ||||||
| 	  padding: 0px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app { |  | ||||||
| 	  border: 1px solid #41464f; |  | ||||||
| 	  border-radius: 15px; |  | ||||||
| 	  text-align: left; |  | ||||||
| 	  padding: 20px; |  | ||||||
| 	  width: 130px; |  | ||||||
| 	  min-height: 200px; |  | ||||||
| 	  text-align: left; |  | ||||||
| 	  display: flex; |  | ||||||
| 	  flex-direction: column; |  | ||||||
| 	  align-items: left; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app-img { |  | ||||||
| 	  padding: 0px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app img { |  | ||||||
| 	  border-radius: 15px; |  | ||||||
| 	  background-color: #101214; |  | ||||||
| 	  width: 70px; |  | ||||||
| 	  height: 70px; |  | ||||||
| 	  object-fit: contain; |  | ||||||
| 	  margin-bottom: 20px; |  | ||||||
| 	  padding: 30px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app-label { |  | ||||||
| 	  font-size: 10px; |  | ||||||
| 	  color: #cccccc; |  | ||||||
| 	  margin-bottom: 10px; |  | ||||||
| 	  align-items: left; |  | ||||||
| 	  text-align: left; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app-name { |  | ||||||
| 	  font-size: 16px; |  | ||||||
| 	  font-weight: bold; |  | ||||||
| 	  margin-bottom: 30px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.more-btn { |  | ||||||
| 	  background-color: inherit; |  | ||||||
| 	  color: #cccccc; |  | ||||||
| 	  border: 1px solid #cccccc; |  | ||||||
| 	  border-radius: 15px; |  | ||||||
| 	  padding: 18px; |  | ||||||
| 	  font-size: 16px; |  | ||||||
| 	  font-weight: 400; |  | ||||||
| 	  cursor: pointer; |  | ||||||
| 	  width: 100%; |  | ||||||
| 	  font-weight: bold; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.more-btn:hover { |  | ||||||
| 	  color: var(--highlight-color); |  | ||||||
| 	  border: 1px solid var(--highlight-color); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app-details { |  | ||||||
| 		padding: 0px 50px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app-fields { |  | ||||||
| 	  border: 1px solid #41464f; |  | ||||||
| 	  border-radius: 15px; |  | ||||||
| 	  text-align: left; |  | ||||||
| 	  padding: 20px; |  | ||||||
| 	  margin: 30px 0px 10px 0px; |  | ||||||
| 	  display: flex; |  | ||||||
| 	  flex-direction: column; |  | ||||||
| 	  align-items: left; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	.app-fields .row { |  | ||||||
|             display: block; |  | ||||||
| 	      justify-content: space-between; |  | ||||||
| 	      align-items: center; |  | ||||||
| 	      padding: 5px 20px; |  | ||||||
| 	      border-radius: 10px; |  | ||||||
| 	      gap: 10px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	#letsencrypt { |  | ||||||
| 		padding-top: 20px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| .header-block { |  | ||||||
|   display: flex; |  | ||||||
|   justify-content: space-between; |  | ||||||
|   align-items: flex-start; |  | ||||||
|   padding: 20px 0px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .logo-and-text { |  | ||||||
|   display: flex; |  | ||||||
|   align-items: flex-start; |  | ||||||
|   gap: 16px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .applogo img { |  | ||||||
|   border-radius: 15px; |  | ||||||
|   background-color: #101214; |  | ||||||
|   width: 70px; |  | ||||||
|   height: 70px; |  | ||||||
|   object-fit: contain; |  | ||||||
|   padding: 40px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .text-content { |  | ||||||
|   display: flex; |  | ||||||
|   flex-direction: column; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .title { |  | ||||||
|   font-size: 28px; |  | ||||||
|   font-weight: bold; |  | ||||||
|   margin: 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .subtitle { |  | ||||||
|   font-size: 18px; |  | ||||||
|   margin: 4px 0; |  | ||||||
|   color: #999; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .description { |  | ||||||
|   font-size: 16px; |  | ||||||
|   margin: 20px 0 0; |  | ||||||
|   color: #999; |  | ||||||
|   line-height: 1.5; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .notification-btn { |  | ||||||
|       background-color: var(--highlight-color); |  | ||||||
|       color: black; |  | ||||||
|       border: none; |  | ||||||
|       padding: 10px 20px; |  | ||||||
|       border-radius: 10px; |  | ||||||
|       cursor: pointer; |  | ||||||
|       font-weight: bold; |  | ||||||
|       display: flex; |  | ||||||
|       align-items: center; |  | ||||||
|       gap: 10px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|     .main-header { |  | ||||||
|       display: flex; |  | ||||||
|       justify-content: space-between; |  | ||||||
|       align-items: center; |  | ||||||
|       margin-bottom: 30px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .main-header h1 { |  | ||||||
|       margin: 0; |  | ||||||
|       font-size: 28px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .main-header button { |  | ||||||
|       background-color: var(--highlight-color); |  | ||||||
|       color: black; |  | ||||||
|       border: none; |  | ||||||
|       padding: 10px 20px; |  | ||||||
|       border-radius: 10px; |  | ||||||
|       cursor: pointer; |  | ||||||
|       font-weight: bold; |  | ||||||
|       display: flex; |  | ||||||
|       align-items: center; |  | ||||||
|       gap: 10px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .input-row, .input-group { |  | ||||||
|       display: flex; |  | ||||||
|       justify-content: space-between; |  | ||||||
|       align-items: center; |  | ||||||
|       border: 1px solid #41464f; |  | ||||||
|       padding: 15px 20px; |  | ||||||
|       margin-bottom: 15px; |  | ||||||
|       border-radius: 10px; |  | ||||||
|       gap: 10px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .input-container { |  | ||||||
|       display: flex; |  | ||||||
|       align-items: center; |  | ||||||
|       gap: 5px; |  | ||||||
|       flex: 1; |  | ||||||
|       justify-content: flex-end; |  | ||||||
|       position: relative; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .input-row input, |  | ||||||
|     .input-row select, |  | ||||||
|     .row input,  |  | ||||||
|     .row select { |  | ||||||
|       background: transparent; |  | ||||||
|       border: 1px solid #41464f; |  | ||||||
|       padding: 8px 30px 8px 8px; |  | ||||||
|       border-radius: 10px; |  | ||||||
|       color: white; |  | ||||||
|       transition: color 0.2s; |  | ||||||
|       max-width: 40%; |  | ||||||
|       box-sizing: border-box; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .row input,  |  | ||||||
|     .row select { |  | ||||||
|       padding: 12px 30px 12px 12px; |  | ||||||
|       font-size: 16px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .input-row input:focus, |  | ||||||
|     .input-row select:focus, |  | ||||||
|     .row input, |  | ||||||
|     .row select { |  | ||||||
|       outline: none; |  | ||||||
|       background-color: black; |  | ||||||
|       color: var(--highlight-color); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .input-row select, |  | ||||||
|     .row select { |  | ||||||
|       appearance: none; |  | ||||||
|       -webkit-appearance: none; |  | ||||||
|       -moz-appearance: none; |  | ||||||
|       background-image: url('data:image/svg+xml;utf8,<svg fill="white" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5-5 5 5zM7 14l5 5 5-5z"/></svg>'); |  | ||||||
|       background-repeat: no-repeat; |  | ||||||
|       background-position: right 8px center; |  | ||||||
|       background-size: 16px; |  | ||||||
|       padding-right: 32px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	.info-container { |  | ||||||
| 		position: relative; |  | ||||||
| 		left: -18px; |  | ||||||
| 		top: -22px; |  | ||||||
| 		display: inline-block; |  | ||||||
| 		font-family: Arial, sans-serif; |  | ||||||
| 		margin: 0px; |  | ||||||
| 		width: 0px; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|     .info-icon { |  | ||||||
|       background-color: var(--highlight-color); |  | ||||||
|       color: black; |  | ||||||
|       border-radius: 50%; |  | ||||||
|       padding: 1px 4px; |  | ||||||
|       cursor: pointer; |  | ||||||
|       font-weight: bold; |  | ||||||
|       font-size: 10px; |  | ||||||
|       text-align: center; |  | ||||||
|       line-height: 1; |  | ||||||
|       display: inline-block; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .tooltip { |  | ||||||
|       visibility: hidden; |  | ||||||
|       background-color: #333; |  | ||||||
|       border-radius: 5px; |  | ||||||
|       padding: 4px 8px; |  | ||||||
|       position: absolute; |  | ||||||
|       z-index: 1; |  | ||||||
|       bottom: 100%; /* above the icon */ |  | ||||||
|       left: 50%; |  | ||||||
|       transform: translateX(-78%); |  | ||||||
|       opacity: 0; |  | ||||||
|       transition: opacity 0.3s; |  | ||||||
|       /*white-space: nowrap;*/ |  | ||||||
|       text-align: right; |  | ||||||
|       width: 300px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .tooltip::after { |  | ||||||
|       content: ""; |  | ||||||
|       position: absolute; |  | ||||||
|       top: 100%; /* bottom of tooltip */ |  | ||||||
|       left: 80%; |  | ||||||
|       margin-left: -5px; |  | ||||||
|       border-width: 5px; |  | ||||||
|       border-style: solid; |  | ||||||
|       border-color: #333 transparent transparent transparent; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .info-container:hover .tooltip { |  | ||||||
|       visibility: visible; |  | ||||||
|       opacity: 1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .clear-btn { |  | ||||||
|       position: absolute; |  | ||||||
|       right: 8px; |  | ||||||
|       background: transparent; |  | ||||||
|       border: none; |  | ||||||
|       color: white; |  | ||||||
|       cursor: pointer; |  | ||||||
|       font-size: 16px; |  | ||||||
|       padding: 0; |  | ||||||
|       width: 20px; |  | ||||||
|       height: 20px; |  | ||||||
|       line-height: 20px; |  | ||||||
|       text-align: center; |  | ||||||
|       user-select: none; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .save-button { |  | ||||||
|       background-color: var(--highlight-color); |  | ||||||
|       color: black; |  | ||||||
|       border: none; |  | ||||||
|       padding: 15px 30px; |  | ||||||
|       font-size: 16px; |  | ||||||
|       border-radius: 10px; |  | ||||||
|       font-weight: bold; |  | ||||||
|       cursor: pointer; |  | ||||||
|       margin-top: 30px; |  | ||||||
|       align-self: flex-start; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .save-button:hover { |  | ||||||
|       background-color: #f5c300; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .buttons .btn { |  | ||||||
|       background-color: black; |  | ||||||
|       border: 1px solid #999; |  | ||||||
|       color: #999; |  | ||||||
|       padding: 10px 15px; |  | ||||||
|       font-size: 14px; |  | ||||||
|       border-radius: 5px; |  | ||||||
|       font-weight: bold; |  | ||||||
|       cursor: pointer; |  | ||||||
|       margin-top: 10px; |  | ||||||
|       align-self: flex-start; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .buttons .btn:hover { |  | ||||||
|       border: 1px solid #f5c300; |  | ||||||
|       color: #f5c300; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|         .hidden { |  | ||||||
|             display: none; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         .popup { |  | ||||||
| 	    width: 100%; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         .popup-content { |  | ||||||
|             width: 100%; |  | ||||||
|             text-align: left; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         #popup .row { |  | ||||||
|             display: flex; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     @media (max-width: 768px) { |  | ||||||
|       .sidebar { |  | ||||||
|         width: 80px; |  | ||||||
|         padding: 20px 5px; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .logo { |  | ||||||
|         font-size: 0; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .logo span { |  | ||||||
|         display: none; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .menu-item { |  | ||||||
|         justify-content: center; |  | ||||||
|         gap: 0; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .menu-item span { |  | ||||||
|         display: none; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .yellow-box { |  | ||||||
|         font-size: 0; |  | ||||||
|         padding: 10px; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .input-row { |  | ||||||
|         flex-direction: column; |  | ||||||
|         align-items: flex-start; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .input-container { |  | ||||||
|         width: 100%; |  | ||||||
|         justify-content: flex-start; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       .input-row input, |  | ||||||
|       .input-row select { |  | ||||||
|         max-width: 100%; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   </style> |  | ||||||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/> | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/> | ||||||
|  | <link rel="stylesheet" href="style.css?t=11" /> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|   <div class="sidebar"> |   <div class="sidebar"> | ||||||
|     <div> |     <div class="sidebar-top"> | ||||||
|       <div class="logo"> |       <div id="logo" class="logo"> | ||||||
|         <img src="/img/logo.png" alt="Safebox"/> |         <img src="/img/logo.svg" alt="Safebox"/> | ||||||
|         <span>Safebox</span> |         <span>Safebox</span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="menu"> |       <div class="menu"> | ||||||
| 	    <div class="menu-item" style="margin-bottom:20px"> |  | ||||||
| 		<img src="/img/globe.png" data-src="/img/globe.png" data-hover="/img/globe.png" alt="VPN" /> |  | ||||||
| 		<div class="menu-label"> |  | ||||||
| 		    <span id="vpnBtn">VPN</span> |  | ||||||
| 		    <label class="switch"> |  | ||||||
| 		      <input type="checkbox" id="vpnToggle"> |  | ||||||
| 		      <span class="slider-text"><span class="switch-label">OFF</span></span> |  | ||||||
| 		    </label> |  | ||||||
| 		</div> |  | ||||||
| 	    </div> |  | ||||||
|  |  | ||||||
| <!-- | <!-- | ||||||
| 	<div class="menu-item"><i class="fas fa-th"></i><span>Applications</span></div> | 	<div class="menu-item"><i class="fas fa-th"></i><span>Applications</span></div> | ||||||
|         <div class="menu-item"><i class="fas fa-hdd"></i><span>Disk Management</span></div> |         <div class="menu-item"><i class="fas fa-hdd"></i><span>Disk Management</span></div> | ||||||
| @@ -699,29 +38,42 @@ | |||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="yellow-row"> |     <div class="yellow-row"> | ||||||
| 	    <div class="yellow-box"> |  | ||||||
| 	<div id="pro_off"> | 	<div id="pro_off"> | ||||||
| 		      <h4>Safebox Pro</h4> | 	    <div class="yellow-box"> | ||||||
|  | 		<div class="pro-text"> | ||||||
|  | 		  <span>Safebox Pro</span> | ||||||
|  | 		</div> | ||||||
| 		      <p>Enjoy benefits and unlock more feature such as remote access, geo-redundant backups etc. <br><br> | 		      <p>Enjoy benefits and unlock more feature such as remote access, geo-redundant backups etc. <br><br> | ||||||
| 		      <a href="" class="details">Read details</a><br><br> | 		      <a href="" class="details">Read details</a><br><br> | ||||||
| 			<img src="/img/upgrade.png" alt="Upgrade now" width="100%"/>	 | 			<img src="/img/upgrade.png" alt="Upgrade now" width="80%" id="upgradeBtn" style="cursor:pointer"/>	 | ||||||
| 		      </p> | 		      </p> | ||||||
| 	    </div> | 	    </div> | ||||||
|  | 	</div> | ||||||
| 	<div id="pro_on" class="hidden"> | 	<div id="pro_on" class="hidden"> | ||||||
| 		      <h4>Login</h4> | 	    <div class="grey-box"> | ||||||
| 		      <p>Enjoy benefits and unlock more feature such as remote access, geo-redundant backups etc. <br><br> | 		<div class="vpn-text" id="vpnBtn" > | ||||||
| 		      <a href="" class="details">Read details</a><br><br> | 		  <img src="/img/globe.png" data-src="/img/globe.png" data-hover="/img/globe.png" alt="VPN"/> | ||||||
|  | 		  <span>Remote access</span> | ||||||
|  | 		</div> | ||||||
|  | 		      <p>It allows you to connect your installed apps to a custom domain (your own or one registered through us), so you can securely log in from any browser, anywhere in the world. | ||||||
| 		      </p> | 		      </p> | ||||||
|  | 			<div class="vpn-item"> | ||||||
|  | <!-- | ||||||
|  | 			    <label class="switch"> | ||||||
|  | 			      <input type="checkbox" id="vpnToggle" onclick="return false"> | ||||||
|  | 			      <span class="slider-text"><span class="switch-label">OFF</span></span> | ||||||
|  | 			    </label> | ||||||
|  | --> | ||||||
|  | 				<span id="vpn_on" class="hidden"><img src="/img/on.png" alt="on" /></span> | ||||||
|  | 				<span id="vpn_off" class="hidden"><img src="/img/off.png" alt="off" /></span> | ||||||
| 			</div> | 			</div> | ||||||
| 	    </div> | 	    </div> | ||||||
| 	    <div class="yellow-corner"> |  | ||||||
| 		<img src="img/yellow_corner.png" alt=""/> |  | ||||||
| 	</div> | 	</div> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
|   <div class="main" > |   <div class="main" > | ||||||
|     <div id="myAppsContainer"> |     <div id="myAppsContainer"> | ||||||
| 	    Loading applications. Please wait... | 	    <div class="loading">Loading applications...</div> | ||||||
|     </div> |     </div> | ||||||
|     <div id="popup" class="popup hidden"> |     <div id="popup" class="popup hidden"> | ||||||
| 	<div class="popup-content"> | 	<div class="popup-content"> | ||||||
| @@ -746,6 +98,7 @@ | |||||||
|     const settingsBtn = document.getElementById('settingsBtn'); |     const settingsBtn = document.getElementById('settingsBtn'); | ||||||
|  |  | ||||||
|     const vpnBtn = document.getElementById('vpnBtn'); |     const vpnBtn = document.getElementById('vpnBtn'); | ||||||
|  |     const upgradeBtn = document.getElementById('upgradeBtn'); | ||||||
|  |  | ||||||
|     const myAppsContainer = document.getElementById('myAppsContainer'); |     const myAppsContainer = document.getElementById('myAppsContainer'); | ||||||
|     const popup = document.getElementById('popup'); |     const popup = document.getElementById('popup'); | ||||||
| @@ -829,16 +182,30 @@ | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     function renderMonitor() { | ||||||
|  |     	myAppsContainer.classList.remove('hidden'); | ||||||
|  |         popup.classList.add('hidden'); | ||||||
|  |  | ||||||
|  |         //TODO: itt kell a buttont editálni és így kell hozzáadni hozzá mindent | ||||||
|  |         myAppsContainer.innerHTML = ` | ||||||
|  | 	    <div class="main-header"> | ||||||
|  | 	      <h1>Monitor</h1> | ||||||
|  | 	      <button id="updatesBtn"><i class="fas fa-bell"></i> Notification</button> | ||||||
|  | 	    </div> | ||||||
|  |         	<img src="/img/monitor.jpg" alt="Under development..." width="1000" /> | ||||||
|  |         `; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     function renderVPN() { |     function renderVPN() { | ||||||
|     	myAppsContainer.classList.remove('hidden'); |     	myAppsContainer.classList.remove('hidden'); | ||||||
|         popup.classList.add('hidden'); |         popup.classList.add('hidden'); | ||||||
|  |  | ||||||
|         myAppsContainer.innerHTML = ` |         myAppsContainer.innerHTML = ` | ||||||
| 	    <div class="main-header"> | 	    <div class="main-header"> | ||||||
| 	      <h1>VPN</h1> | 	      <h1>VPN - enable proxy</h1> | ||||||
| 	    </div> | 	    </div> | ||||||
|             <div id="vpn" class="innerDiv"> |             <div id="vpn" class="innerDiv"> | ||||||
| 	    Loading... | 	    <div class="loading">Loading...</div> | ||||||
|             </div> |             </div> | ||||||
|         `; |         `; | ||||||
| 	get_proxy_html(); | 	get_proxy_html(); | ||||||
| @@ -850,7 +217,7 @@ | |||||||
| 	      <h1>Services</h1> | 	      <h1>Services</h1> | ||||||
| 	    </div> | 	    </div> | ||||||
|             <div id="services" class="innerDiv"> |             <div id="services" class="innerDiv"> | ||||||
| 	    Loading... | 	    <div class="loading">Loading...</div> | ||||||
|             </div> |             </div> | ||||||
|         `; |         `; | ||||||
| 	get_services(); | 	get_services(); | ||||||
| @@ -862,7 +229,7 @@ | |||||||
| 	      <h1>Updates</h1> | 	      <h1>Updates</h1> | ||||||
| 	    </div> | 	    </div> | ||||||
|             <div id="updates" class="innerDiv"> |             <div id="updates" class="innerDiv"> | ||||||
| 	    Looking for updates... Please wait... | 	    <div class="loading">Looking for updates...</div> | ||||||
|             </div> |             </div> | ||||||
|         `; |         `; | ||||||
| 	get_updates(); | 	get_updates(); | ||||||
| @@ -874,7 +241,7 @@ | |||||||
| 	      <h1>System services</h1> | 	      <h1>System services</h1> | ||||||
| 	    </div> | 	    </div> | ||||||
|             <div id="system" class="innerDiv"> |             <div id="system" class="innerDiv"> | ||||||
| 	    Loading... | 	    <div class="loading">Loading...</div> | ||||||
|             </div> |             </div> | ||||||
|         `; |         `; | ||||||
| 	get_system(); | 	get_system(); | ||||||
| @@ -946,7 +313,7 @@ | |||||||
| 	    <div class="main-header"> | 	    <div class="main-header"> | ||||||
| 	      <h1>Repositories</h1> | 	      <h1>Repositories</h1> | ||||||
| 	    </div> | 	    </div> | ||||||
| 		<div id="repositories" style="text-align:left">Loading...</div> | 		<div id="repositories" style="text-align:left">Loading repositories...</div> | ||||||
| 		<br> | 		<br> | ||||||
| 		<form class="form-install" action="#" method="post" id="add_repo"> | 		<form class="form-install" action="#" method="post" id="add_repo"> | ||||||
| 		<div class="input-row"> | 		<div class="input-row"> | ||||||
| @@ -989,13 +356,15 @@ | |||||||
| 	installAppsBtn.addEventListener('click', () => {renderApps(true); activate(installAppsBtn);}); | 	installAppsBtn.addEventListener('click', () => {renderApps(true); activate(installAppsBtn);}); | ||||||
| 	backupBtn.addEventListener('click', () => {renderText('Backup'); activate(backupBtn);}); | 	backupBtn.addEventListener('click', () => {renderText('Backup'); activate(backupBtn);}); | ||||||
| 	diskBtn.addEventListener('click', () => {renderText('Disk Management'); activate(diskBtn)}); | 	diskBtn.addEventListener('click', () => {renderText('Disk Management'); activate(diskBtn)}); | ||||||
| 	monitorBtn.addEventListener('click', () => {renderText('Monitor'); activate(monitorBtn)}); | 	monitorBtn.addEventListener('click', () => {renderMonitor(); activate(monitorBtn)}); | ||||||
|     	settingsBtn.addEventListener('click', () => {renderSettings(); activate(settingsBtn)}); |     	settingsBtn.addEventListener('click', () => {renderSettings(); activate(settingsBtn)}); | ||||||
|  |  | ||||||
| 	vpnBtn.addEventListener('click', () => renderVPN()); | 	vpnBtn.addEventListener('click', () => renderVPN()); | ||||||
|  | 	upgradeBtn.addEventListener('click', () => renderVPN()); | ||||||
|  |  | ||||||
| //	renderApps(true); | //	renderApps(true); | ||||||
|  |  | ||||||
|  | /* | ||||||
| 	const vpnToggle = document.getElementById("vpnToggle"); | 	const vpnToggle = document.getElementById("vpnToggle"); | ||||||
|   	const vpnLabel = document.querySelector(".switch-label"); |   	const vpnLabel = document.querySelector(".switch-label"); | ||||||
|  |  | ||||||
| @@ -1004,9 +373,13 @@ | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	vpnToggle.addEventListener("change", updateStatus); | 	vpnToggle.addEventListener("change", updateStatus); | ||||||
|  | 	vpnToggle.addEventListener('click', function (e) { | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
| 	// Alapállapot beállítása | 	// Alapállapot beállítása | ||||||
| 	updateStatus(); | 	updateStatus(); | ||||||
|  | */ | ||||||
|  |  | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
| @@ -1016,7 +389,6 @@ | |||||||
| <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | ||||||
| <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> | ||||||
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> | ||||||
| <script src="common.js?t=30"></script> | <script src="common.js?t=41"></script> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										216
									
								
								scan.html
									
									
									
									
									
								
							
							
						
						| @@ -1,35 +1,38 @@ | |||||||
| <!doctype html> | <!DOCTYPE html> | ||||||
| <html lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
| <!-- Required meta tags --> | <meta charset="UTF-8" /> | ||||||
| <meta charset="utf-8"> | <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||||
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> | ||||||
| <title>INSTALLER TOOL</title> | <meta http-equiv="Pragma" content="no-cache" /> | ||||||
| <!-- Bootstrap CSS --> | <meta http-equiv="Expires" content="0" /> | ||||||
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> | <title>Safebox - INSTALLER TOOL</title> | ||||||
| <!-- Custom styles for this template --> | <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Switzer:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap"/> | ||||||
| <link href="installer.css?t=1" rel="stylesheet"> | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/> | ||||||
|  | <link rel="stylesheet" href="style.css?t=4" /> | ||||||
| </head> | </head> | ||||||
| <body id="scan" class="text-center"> | <body id="scan" class="text-center"> | ||||||
| <div class="container-fluid"> |   <div class="main"> | ||||||
| <div class="col-md-12"> |     <div id="myAppsContainer"> | ||||||
| 	<h1>Scanning your device for any previous installed versions</h1> | 	<div class="logo" style="margin:100px 0px 20px 0px;"> | ||||||
| 	<div class="row d-flex justify-content-center mt-100"> | 		<img src="/img/logo.svg" alt="Safebox"/> | ||||||
| 	       <div class="progress blue" data-value="100"> | 		<span>Safebox</span> | ||||||
| 		 <span class="progress-left"> | 	</div> | ||||||
| 		   <span class="progress-bar"></span> | 	<div class="progress-box"> | ||||||
| 		 </span> | 		<div class="progress-title">Scanning your device</div> | ||||||
| 		 <span class="progress-right"> | 		<div class="progress-description" id="info">Looking for any previously installed version</div> | ||||||
| 		   <span class="progress-bar"></span> | 		<div class="progress-container-shadow"> | ||||||
| 		 </span> | 		</div> | ||||||
| 		 <div class="progress-value"></div> | 		<div class="progress-container"> | ||||||
|  | 			<div class="progress-bar" id="progressBar"></div> | ||||||
|  | 			<div class="progress-text" id="progressText">0%</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div><a href="install.html" class="stop">STOP AND START INSTALL</a></div> | <!-- | ||||||
| 	<br> | 	<div class="controls"> | ||||||
| 	<br> |         	<button onclick="document.location='install.html'" class="save-button">STOP AND START INSTALL</button> | ||||||
| 	<div id="redis"></div> | 	</div> | ||||||
| 	<div id="previous"></div> | --> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| <!-- Optional JavaScript --> | <!-- Optional JavaScript --> | ||||||
| @@ -37,162 +40,19 @@ | |||||||
| <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | ||||||
| <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> | ||||||
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> | <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> | ||||||
|  | <script src="install.js?t=7"></script> | ||||||
| <script> | <script> | ||||||
| $(function() { | const progressBar = document.getElementById('progressBar'); | ||||||
|  | const progressText = document.getElementById('progressText'); | ||||||
|  | let currentProgress = 0; | ||||||
|  | let progressInterval; | ||||||
|  | let install = 0; // scan | ||||||
|  |  | ||||||
| function redirectToInstall() { | // Initialize | ||||||
|     window.location.href = 'install.html'; | updateProgress(0); | ||||||
| } | startProgress(30000);// 30 seconds | ||||||
|  |  | ||||||
| function redirectToManage() { |  | ||||||
|     window.location.href = 'manage.html'; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function start_system() { |  | ||||||
|   var url  = 'scan.php?op=system'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('start_system: '+data); |  | ||||||
|     if (data=='OK') { |  | ||||||
|       $("#previous").html('Scanning for previous install. Please wait...'); |  | ||||||
|       check_system(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       $("#previous").html('Scanning for previous install has aborted...'); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_system() { |  | ||||||
|   var url  = 'scan.php?op=check_system'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_system: '+data); |  | ||||||
|     if (data=='NEW') { |  | ||||||
|       $("#previous").html('No previous install has found...'); |  | ||||||
|       setTimeout(redirectToInstall, 3000); |  | ||||||
|     } |  | ||||||
|     else if (data=='EXISTS') { |  | ||||||
|       $("#previous").html('Previous install has found...'); |  | ||||||
|       setTimeout(redirectToManage, 3000); |  | ||||||
|     } |  | ||||||
|     else if (data=='WAIT') { |  | ||||||
|       setTimeout(check_system, 1000); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
| 	    // UNEXPECTED ERROR |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_redis() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=redis'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_redis: '+data); |  | ||||||
|     if (data=='OK') { |  | ||||||
|       $("#redis").html('Redis server - OK'); |  | ||||||
|       start_system(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       $("#redis").html('Redis server is not available...'); |  | ||||||
|       setTimeout(check_redis, 1000); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_directory() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=directory'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_directory: '+data); |  | ||||||
|     if (data=='OK') { |  | ||||||
|       $("#redis").html('Connection is ready - OK'); |  | ||||||
|       start_system(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       $("#redis").html('Shared directory is not available...'); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function check_interface() { |  | ||||||
|  |  | ||||||
|   var url  = 'scan.php?op=get_interface'; |  | ||||||
|   $.get(url, function(data){ |  | ||||||
|     console.log('check_interface: '+data); |  | ||||||
|     if (data=='redis') { |  | ||||||
|   	check_redis(); |  | ||||||
|     } |  | ||||||
|     else if (data=='directory') { |  | ||||||
|   	check_directory(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
| 	$("#redis").html('Invalid interface definition...'); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| check_interface(); | check_interface(); | ||||||
|  |  | ||||||
|   //setTimeout(redirectToManage, 10000); |  | ||||||
|  |  | ||||||
|   $(".progress").each(function() { |  | ||||||
|  |  | ||||||
|     var value = $(this).attr('data-value'); |  | ||||||
|     var left = $(this).find('.progress-left .progress-bar'); |  | ||||||
|     var right = $(this).find('.progress-right .progress-bar'); |  | ||||||
|  |  | ||||||
|     if (value > 0) { |  | ||||||
| /* |  | ||||||
| 	angle1 = getRotationDegrees(right); |  | ||||||
| 	angle2 = getRotationDegrees(left); |  | ||||||
| 		console.log(angle1); |  | ||||||
| 		console.log(angle2); |  | ||||||
| 	idx=1 |  | ||||||
| 	while (idx < 50) { |  | ||||||
| 		angle1 = getRotationDegrees(right); |  | ||||||
| 		angle2 = getRotationDegrees(left); |  | ||||||
| 		console.log(angle1); |  | ||||||
| 		console.log(angle2); |  | ||||||
| 		$('div.progress-value').html(angle2); |  | ||||||
| 		idx++; |  | ||||||
| 	} |  | ||||||
| */ |  | ||||||
| /* |  | ||||||
|       if (value <= 50) { |  | ||||||
|         right.css('transform', 'rotate(' + percentageToDegrees(value) + 'deg)') |  | ||||||
|       } else { |  | ||||||
|         right.css('transform', 'rotate(180deg)') |  | ||||||
|         left.css('transform', 'rotate(' + percentageToDegrees(value - 50) + 'deg)') |  | ||||||
|       } |  | ||||||
| */ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   function percentageToDegrees(percentage) { |  | ||||||
|     return percentage / 100 * 360 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Returns rotation in degrees when obtaining transform-styles using javascript |  | ||||||
| 	 * http://stackoverflow.com/questions/8270612/get-element-moz-transformrotate-value-in-jquery |  | ||||||
| 	 */ |  | ||||||
| 	function getRotationDegrees(obj) { |  | ||||||
| 	    var matrix = obj.css("-webkit-transform") || |  | ||||||
| 	    obj.css("-moz-transform")    || |  | ||||||
| 	    obj.css("-ms-transform")     || |  | ||||||
| 	    obj.css("-o-transform")      || |  | ||||||
| 	    obj.css("transform"); |  | ||||||
| 	    if(matrix !== 'none') { |  | ||||||
| 		var values = matrix.split('(')[1].split(')')[0].split(','); |  | ||||||
| 		var a = values[0]; |  | ||||||
| 		var b = values[1]; |  | ||||||
| 		var angle = Math.round(Math.atan2(b, a) * (180/Math.PI)); |  | ||||||
| 	    } else { var angle = 0; } |  | ||||||
| 	    return angle; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| }); |  | ||||||
| </script> | </script> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								scan.php
									
									
									
									
									
								
							
							
						
						| @@ -59,12 +59,12 @@ switch ($_GET["op"]) { | |||||||
| 		} | 		} | ||||||
| 		else echo "WAIT"; | 		else echo "WAIT"; | ||||||
| 	break; | 	break; | ||||||
| 	case "check_install": // called in install.php - check if install process has finished | 	case "check_install": // called in install.js - check if install process has finished | ||||||
| 		$arr = check_response($_GET["key"]); // TODO - replace key with "install", key can be "install*" | 		$arr = check_response("install"); | ||||||
| 		if (!empty($arr)) { | 		if (!empty($arr)) { | ||||||
| 			foreach ($arr as $key=>$data) { | 			foreach ($arr as $key=>$data) { | ||||||
| 				//echo $key."-".$_GET["key"]; | 				//echo $key."-".$_GET["key"]; | ||||||
| 				if ($key==$_GET["key"]) { // if install key moved to web_out | 				if ($key=="install") { // if install key moved to web_out | ||||||
| 					if ($data["INSTALL_STATUS"]>0) { | 					if ($data["INSTALL_STATUS"]>0) { | ||||||
| 						remove_response("$key"); | 						remove_response("$key"); | ||||||
| 						echo "INSTALLED"; | 						echo "INSTALLED"; | ||||||
| @@ -149,7 +149,7 @@ switch ($_GET["op"]) { | |||||||
| 								$subtitle = $content["subtitle"]; | 								$subtitle = $content["subtitle"]; | ||||||
| 								if (empty($subtitle) || $subtitle == "null") $subtitle = ""; | 								if (empty($subtitle) || $subtitle == "null") $subtitle = ""; | ||||||
| 								$icon = $content["icon"]; | 								$icon = $content["icon"]; | ||||||
| 								if (empty($icon) || $icon == "null") $icon = "img/default_logo.png"; // default icon image | 								if (empty($icon) || $icon == "null") $icon = "img/logo.svg"; // default icon image | ||||||
| 								if (array_key_exists($service_name,$data["INSTALLED_SERVICES"])) $installed = "true"; | 								if (array_key_exists($service_name,$data["INSTALLED_SERVICES"])) $installed = "true"; | ||||||
| 								else $installed = "false"; | 								else $installed = "false"; | ||||||
| 								if (!empty($deployments)) $deployments .= ", "; | 								if (!empty($deployments)) $deployments .= ", "; | ||||||
| @@ -182,6 +182,7 @@ switch ($_GET["op"]) { | |||||||
| 				if ($key=="deployment") { | 				if ($key=="deployment") { | ||||||
| 					if ($data["STATUS"]=="0") { // ask | 					if ($data["STATUS"]=="0") { // ask | ||||||
| 						$template = json_decode(base64_decode($data["TEMPLATE"])); | 						$template = json_decode(base64_decode($data["TEMPLATE"])); | ||||||
|  | 						$template->name = strtolower($template->name); | ||||||
|  |  | ||||||
| 						echo ' | 						echo ' | ||||||
| 						<div class="app-details"> | 						<div class="app-details"> | ||||||
| @@ -191,7 +192,7 @@ switch ($_GET["op"]) { | |||||||
| 								<img src="'.$template->icon.'"> | 								<img src="'.$template->icon.'"> | ||||||
| 							    </div> | 							    </div> | ||||||
| 							    <div class="text-content"> | 							    <div class="text-content"> | ||||||
| 							      <h1 class="title">'.$template->name.'</h1> | 							      <h1 class="title">'.$template->title.'</h1> | ||||||
| 							      <h2 class="subtitle">'.$template->subtitle.'</h2> | 							      <h2 class="subtitle">'.$template->subtitle.'</h2> | ||||||
| 							      <p class="description">'.$template->description.'</p> | 							      <p class="description">'.$template->description.'</p> | ||||||
| 							    </div> | 							    </div> | ||||||
| @@ -203,7 +204,7 @@ switch ($_GET["op"]) { | |||||||
| 							echo '<div id="letsencrypt">'; | 							echo '<div id="letsencrypt">'; | ||||||
| 							//var_dump($template); | 							//var_dump($template); | ||||||
|                                                         $letsencrypt = check_letsencrypt(); |                                                         $letsencrypt = check_letsencrypt(); | ||||||
| 							if (empty($letsencrypt)) echo "LETSENCRYPT file doesn't exists...<br><br>"; | 							if (empty($letsencrypt)) echo ""; //echo "LETSENCRYPT file doesn't exists...<br><br>"; | ||||||
| 							elseif ($letsencrypt=="ERROR") echo "LETSENCRYPT file: read JSON error...<br><br>"; | 							elseif ($letsencrypt=="ERROR") echo "LETSENCRYPT file: read JSON error...<br><br>"; | ||||||
| 							else { | 							else { | ||||||
| 								$domain = ""; | 								$domain = ""; | ||||||
| @@ -334,7 +335,7 @@ switch ($_GET["op"]) { | |||||||
| 	case "check_letsencrypt": | 	case "check_letsencrypt": | ||||||
| 		$domain = $_GET["domain"]; | 		$domain = $_GET["domain"]; | ||||||
| 		$letsencrypt = check_letsencrypt(); | 		$letsencrypt = check_letsencrypt(); | ||||||
| 		if (empty($letsencrypt)) echo "LETSENCRYPT file doesn't exists..."; | 		if (empty($letsencrypt)) echo ""; //echo "LETSENCRYPT file doesn't exists..."; | ||||||
| 		elseif ($letsencrypt=="ERROR") echo "LETSENCRYPT file: read JSON error..."; | 		elseif ($letsencrypt=="ERROR") echo "LETSENCRYPT file: read JSON error..."; | ||||||
| 		else { | 		else { | ||||||
| 			show_letsencrypt($letsencrypt, $domain); | 			show_letsencrypt($letsencrypt, $domain); | ||||||
| @@ -347,7 +348,7 @@ switch ($_GET["op"]) { | |||||||
| 			$text="A deployment ({$_GET["additional"]}) has already started.<br>Please wait and do not start a new one..."; | 			$text="A deployment ({$_GET["additional"]}) has already started.<br>Please wait and do not start a new one..."; | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			$text="Install in progress... Please wait..."; | 			$text="Install in progress..."; | ||||||
| 			$fields = $_GET; | 			$fields = $_GET; | ||||||
| 			unset($fields["op"]); | 			unset($fields["op"]); | ||||||
| 			unset($fields["additional"]); | 			unset($fields["additional"]); | ||||||
| @@ -492,6 +493,15 @@ switch ($_GET["op"]) { | |||||||
|                 } |                 } | ||||||
|                 echo $text; |                 echo $text; | ||||||
|         break; |         break; | ||||||
|  | 	case "version": | ||||||
|  | 		$arr = check_response("version"); | ||||||
|  | 		if (!empty($arr)) { | ||||||
|  | 			$data = $arr["version"]; | ||||||
|  | 			echo "Framework version: ".$data["VERSION"]."\n"; | ||||||
|  | 		} | ||||||
|  | 		else echo "Version not found"; | ||||||
|  | 		echo "Frontend version: 1.1.14"; | ||||||
|  | 	break; | ||||||
| 	case "repositories": | 	case "repositories": | ||||||
| 		$arr = array("STATUS" => 0); | 		$arr = array("STATUS" => 0); | ||||||
| 		$json = json_encode($arr, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT); | 		$json = json_encode($arr, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT); | ||||||
|   | |||||||
							
								
								
									
										770
									
								
								style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,770 @@ | |||||||
|  |     :root { | ||||||
|  |       --highlight-color: #FFB806; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     body { | ||||||
|  |       margin: 0; | ||||||
|  |       font-family: 'Switzer', sans-serif; | ||||||
|  |       font-weight: 500; | ||||||
|  |       font-size: 16px; | ||||||
|  |       background-color: #000; | ||||||
|  |       color: white; | ||||||
|  |       display: flex; | ||||||
|  |       height: 100vh; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     h4 { | ||||||
|  | 	font-size: 16px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	table {border: 1px solid var(--highlight-color); width:100%;} | ||||||
|  | 	table th {padding-left: 20px; text-align: left; color: var(--highlight-color); width: 25%;} | ||||||
|  | 	table td {padding-left: 20px; text-align:left; width: 25%;} | ||||||
|  |  | ||||||
|  | .progress-box { | ||||||
|  | 	max-width: 300px; | ||||||
|  | 	margin: auto; | ||||||
|  | 	text-align: center; | ||||||
|  | 	align-items: center; | ||||||
|  | 	border: 2px solid #41464f; | ||||||
|  | 	padding: 30px 30px 0px 30px; | ||||||
|  | 	border-radius: 20px; | ||||||
|  | } | ||||||
|  | .progress-container-shadow { | ||||||
|  |     width: 300px; | ||||||
|  |     height: 40px; | ||||||
|  |     background-color: var(--highlight-color); | ||||||
|  |     border-radius: 5px; | ||||||
|  |     overflow: hidden; | ||||||
|  |     position: relative; | ||||||
|  |     margin: 40px auto 0px auto; | ||||||
|  | } | ||||||
|  | .progress-container-shadow::after { | ||||||
|  |   content: ""; | ||||||
|  |   position: absolute; | ||||||
|  |   inset: 0; | ||||||
|  |   background-color: rgba(0, 0, 0, 0.5); | ||||||
|  |   pointer-events: none; | ||||||
|  | } | ||||||
|  | .progress-container { | ||||||
|  |     width: 300px; | ||||||
|  |     height: 40px; | ||||||
|  |     border-radius: 5px; | ||||||
|  |     overflow: hidden; | ||||||
|  |     position: relative; | ||||||
|  |     margin: 0px; | ||||||
|  |     top:-45px; | ||||||
|  |     left:5px; | ||||||
|  | } | ||||||
|  | .progress-bar { | ||||||
|  |     height: 100%; | ||||||
|  |     background-color: var(--highlight-color); | ||||||
|  |     width: 0%; | ||||||
|  |     border-radius: 5px; | ||||||
|  |     transition: width 0.3s ease; | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
|  | .progress-text { | ||||||
|  |     font-size: 20px; | ||||||
|  |     position: absolute; | ||||||
|  |     top: 50%; | ||||||
|  |     left: 50%; | ||||||
|  |     transform: translate(-50%, -50%); | ||||||
|  |     font-weight: bold; | ||||||
|  |     color: #000000; | ||||||
|  |     z-index: 10; | ||||||
|  | } | ||||||
|  | .progress-title { | ||||||
|  | 	text-align: left; | ||||||
|  | 	font-size: 18px; | ||||||
|  | 	font-weight: bold; | ||||||
|  | 	margin-bottom: 10px; | ||||||
|  | } | ||||||
|  | .progress-description { | ||||||
|  | 	text-align: left; | ||||||
|  | 	font-size: 16px; | ||||||
|  | 	margin-bottom: 10px; | ||||||
|  | 	color: #999; | ||||||
|  | 	min-height: 40px; | ||||||
|  | } | ||||||
|  | .controls { | ||||||
|  |     text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |     .sidebar { | ||||||
|  |       width: 250px; | ||||||
|  |       background-color: #101214; | ||||||
|  |       display: flex; | ||||||
|  |       flex-direction: column; | ||||||
|  |       /*height: 100vh;*/ | ||||||
|  |       justify-content: space-between; | ||||||
|  |       margin: 20px; | ||||||
|  |       border-radius: 20px; | ||||||
|  |       transition: width 0.3s; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | .sidebar-top { | ||||||
|  |       padding: 20px 0px 0px 0px; | ||||||
|  | 	overflow-y: auto; | ||||||
|  | 	flex: 1 1 auto; | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | 	justify-content: center; /* ez teszi középre függőlegesen a menüt */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  |     .logo { | ||||||
|  |       text-align: center; | ||||||
|  |       font-size: 24px; | ||||||
|  |       font-weight: bold; | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       justify-content: center; | ||||||
|  |       gap: 10px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .logo img { | ||||||
|  |       height: 30px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .loading { | ||||||
|  | 	    text-align:center; | ||||||
|  | 	    margin-top:300px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu { | ||||||
|  |       display: flex; | ||||||
|  |       flex-direction: column; | ||||||
|  |       justify-content: center; /* középre igazít függőlegesen */ | ||||||
|  |       flex-grow: 1; | ||||||
|  |       gap: 5px; | ||||||
|  |       padding: 0 10px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .vpn-item { | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       gap: 10px; | ||||||
|  |       color: white; | ||||||
|  |       transition: color 0.3s; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item { | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       gap: 10px; | ||||||
|  |       padding: 10px 20px; | ||||||
|  |       cursor: pointer; | ||||||
|  |       color: white; | ||||||
|  |       transition: color 0.3s; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item:hover { | ||||||
|  |       color: var(--highlight-color); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item i { | ||||||
|  |       font-size: 18px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item span { | ||||||
|  |       display: inline; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item img { | ||||||
|  |       width: 24px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item.active { | ||||||
|  |       background-color: var(--highlight-color); | ||||||
|  |       color: black; | ||||||
|  |       border-radius: 10px; | ||||||
|  |       font-weight: bold; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .menu-item.active:hover { | ||||||
|  |       color: black; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | .menu-item span.arrow { | ||||||
|  |   margin-left: auto; | ||||||
|  |   color: gray; | ||||||
|  |   font-size: 20px; | ||||||
|  |   transition: transform 0.3s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .menu-item.open .arrow { | ||||||
|  |   transform: rotate(180deg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .submenu { | ||||||
|  |   display: none; | ||||||
|  |   margin-left: 40px; | ||||||
|  |   flex-direction: column; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .submenu-item { | ||||||
|  |   padding: 5px 14px; | ||||||
|  |   font-size: 14px; | ||||||
|  |   color: #ffffff; | ||||||
|  |   cursor: pointer; | ||||||
|  |   border-radius: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .submenu-item:hover { | ||||||
|  |   color: #000000; | ||||||
|  |   background-color: var(--highlight-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Switch container */ | ||||||
|  | .switch { | ||||||
|  |   position: relative; | ||||||
|  |   display: inline-block; | ||||||
|  |   width: 60px; | ||||||
|  |   height: 26px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Hide native checkbox */ | ||||||
|  | .switch input { | ||||||
|  |   opacity: 0; | ||||||
|  |   width: 0; | ||||||
|  |   height: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Slider background */ | ||||||
|  | .slider-text { | ||||||
|  |   position: absolute; | ||||||
|  |   top: 0; | ||||||
|  |   left: 0; | ||||||
|  |   right: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   background-color: #ccc; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   transition: background-color 0.3s; | ||||||
|  |   display: flex !important; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: flex-end; /* default: OFF on the right */ | ||||||
|  |   padding: 0 8px; | ||||||
|  |   font-size: 12px; | ||||||
|  |   font-weight: bold; | ||||||
|  |   color: #000; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Circle */ | ||||||
|  | .slider-text::before { | ||||||
|  |   content: ""; | ||||||
|  |   position: absolute; | ||||||
|  |   height: 22px; | ||||||
|  |   width: 22px; | ||||||
|  |   left: 2px; | ||||||
|  |   top: 2px; | ||||||
|  |   background-color: white; | ||||||
|  |   border-radius: 50%; | ||||||
|  |   transition: transform 0.3s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Checked: move dot, change background and text alignment */ | ||||||
|  | .switch input:checked + .slider-text { | ||||||
|  |   background-color: var(--highlight-color); | ||||||
|  |   justify-content: flex-start; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Dot animation */ | ||||||
|  | .switch input:checked + .slider-text::before { | ||||||
|  |   transform: translateX(34px); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Status label */ | ||||||
|  | .status-label { | ||||||
|  |   font-size: 12px; | ||||||
|  |   color: #888; | ||||||
|  |   min-width: 28px; | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |     .details { | ||||||
|  |       color: white; | ||||||
|  |       text-decoration: none; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .yellow-row { | ||||||
|  | 	flex-shrink: 0; | ||||||
|  | 	max-width:250px; | ||||||
|  | 	display: flex; | ||||||
|  | 	align-items: flex-start; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  |         margin: 0px; | ||||||
|  | 	width: 100%; | ||||||
|  | 	padding: 0px 20px 20px 20px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .yellow-box { | ||||||
|  |       background-image: url('img/yellow-box.png'); | ||||||
|  |       background-repeat: no-repeat; | ||||||
|  |       /*background-color: var(--highlight-color); | ||||||
|  |       border-radius: 20px 20px 0px 20px;*/ | ||||||
|  |       color: black; | ||||||
|  |       text-align: left; | ||||||
|  |       margin: 0px; | ||||||
|  |       padding: 20px 18px; | ||||||
|  |       font-weight: bold; | ||||||
|  |       font-size: 12px; | ||||||
|  |       width: 156px; | ||||||
|  |       height: 176px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .yellow-corner { | ||||||
|  | 	padding:0px; | ||||||
|  | 	border: 0px; | ||||||
|  | 	display: flex; | ||||||
|  | 	margin: 0px; | ||||||
|  | 	margin-top: auto; | ||||||
|  | 	align-items: flex-end; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | .pro-text { | ||||||
|  | 	font-size: 16px; | ||||||
|  | 	color: black; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |     .grey-box { | ||||||
|  |       background-image: url('img/grey-box.png'); | ||||||
|  |       background-repeat: no-repeat; | ||||||
|  |  /*     border: 2px solid #41464f;  */ | ||||||
|  |       border-radius: 20px 20px 0px 20px; | ||||||
|  |       color: #999; | ||||||
|  |       text-align: left; | ||||||
|  |       margin: 0px; | ||||||
|  |       padding: 20px 18px; | ||||||
|  |       font-weight: bold; | ||||||
|  |       font-size: 12px; | ||||||
|  |       width: 158px; | ||||||
|  |       height: 178px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | .vpn-text { | ||||||
|  | 	display: flex; | ||||||
|  | 	align-items: center;  /* Ez igazítja középre függőlegesen a tartalmat */ | ||||||
|  | 	gap: 10px;            /* Távolság kép és szöveg között (opcionális) */ | ||||||
|  | 	font-size: 16px; | ||||||
|  | 	color: var(--highlight-color); | ||||||
|  | 	cursor: pointer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |     .main { | ||||||
|  |       flex: 1; | ||||||
|  |       padding: 30px; | ||||||
|  |       display: flex; | ||||||
|  |       flex-direction: column; | ||||||
|  |       overflow-y: auto; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	#appsContainer { | ||||||
|  | 	  display: flex; | ||||||
|  | 	  flex-wrap: wrap; | ||||||
|  | 	  gap: 16px; | ||||||
|  | 	  padding: 0px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app { | ||||||
|  | 	  border: 1px solid #41464f; | ||||||
|  | 	  border-radius: 15px; | ||||||
|  | 	  text-align: left; | ||||||
|  | 	  padding: 20px; | ||||||
|  | 	  width: 130px; | ||||||
|  | 	  min-height: 200px; | ||||||
|  | 	  text-align: left; | ||||||
|  | 	  display: flex; | ||||||
|  | 	  flex-direction: column; | ||||||
|  | 	  align-items: left; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app-img { | ||||||
|  | 	  padding: 0px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app img { | ||||||
|  | 	  border-radius: 15px; | ||||||
|  | 	  background-color: #101214; | ||||||
|  | 	  width: 70px; | ||||||
|  | 	  height: 70px; | ||||||
|  | 	  object-fit: contain; | ||||||
|  | 	  margin-bottom: 20px; | ||||||
|  | 	  padding: 30px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app-label { | ||||||
|  | 	  font-size: 10px; | ||||||
|  | 	  color: #cccccc; | ||||||
|  | 	  margin-bottom: 10px; | ||||||
|  | 	  align-items: left; | ||||||
|  | 	  text-align: left; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app-name { | ||||||
|  | 	  font-size: 16px; | ||||||
|  | 	  font-weight: bold; | ||||||
|  | 	  margin-bottom: 30px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.more-btn { | ||||||
|  | 	  background-color: inherit; | ||||||
|  | 	  color: #cccccc; | ||||||
|  | 	  border: 1px solid #cccccc; | ||||||
|  | 	  border-radius: 15px; | ||||||
|  | 	  padding: 18px; | ||||||
|  | 	  font-size: 16px; | ||||||
|  | 	  font-weight: 400; | ||||||
|  | 	  cursor: pointer; | ||||||
|  | 	  width: 100%; | ||||||
|  | 	  font-weight: bold; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.more-btn:hover { | ||||||
|  | 	  color: var(--highlight-color); | ||||||
|  | 	  border: 1px solid var(--highlight-color); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app-details { | ||||||
|  | 		padding: 0px 50px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app-fields { | ||||||
|  | 	  border: 1px solid #41464f; | ||||||
|  | 	  border-radius: 15px; | ||||||
|  | 	  text-align: left; | ||||||
|  | 	  padding: 20px; | ||||||
|  | 	  margin: 30px 0px 10px 0px; | ||||||
|  | 	  display: flex; | ||||||
|  | 	  flex-direction: column; | ||||||
|  | 	  align-items: left; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.app-fields .row { | ||||||
|  |             display: flex; | ||||||
|  | 	      justify-content: space-between; | ||||||
|  | 	      align-items: center; | ||||||
|  | 	      padding: 5px 20px; | ||||||
|  | 	      border-radius: 10px; | ||||||
|  | 	      gap: 10px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	#letsencrypt { | ||||||
|  | 		padding-top: 20px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | .header-block { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   padding: 20px 0px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .logo-and-text { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   gap: 16px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .applogo img { | ||||||
|  |   border-radius: 15px; | ||||||
|  |   background-color: #101214; | ||||||
|  |   width: 70px; | ||||||
|  |   height: 70px; | ||||||
|  |   object-fit: contain; | ||||||
|  |   padding: 40px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .text-content { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .title { | ||||||
|  |   font-size: 28px; | ||||||
|  |   font-weight: bold; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .subtitle { | ||||||
|  |   font-size: 18px; | ||||||
|  |   margin: 4px 0; | ||||||
|  |   color: #999; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .description { | ||||||
|  |   font-size: 16px; | ||||||
|  |   margin: 20px 0 0; | ||||||
|  |   color: #999; | ||||||
|  |   line-height: 1.5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .notification-btn { | ||||||
|  |       background-color: var(--highlight-color); | ||||||
|  |       color: black; | ||||||
|  |       border: none; | ||||||
|  |       padding: 10px 20px; | ||||||
|  |       border-radius: 10px; | ||||||
|  |       cursor: pointer; | ||||||
|  |       font-weight: bold; | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       gap: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |     .main-header { | ||||||
|  |       display: flex; | ||||||
|  |       justify-content: space-between; | ||||||
|  |       align-items: center; | ||||||
|  |       margin-bottom: 30px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .main-header h1 { | ||||||
|  |       margin: 0; | ||||||
|  |       font-size: 28px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .main-header button { | ||||||
|  |       background-color: var(--highlight-color); | ||||||
|  |       color: black; | ||||||
|  |       border: none; | ||||||
|  |       padding: 10px 20px; | ||||||
|  |       border-radius: 10px; | ||||||
|  |       cursor: pointer; | ||||||
|  |       font-weight: bold; | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       gap: 10px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .input-row, .input-group { | ||||||
|  |       display: flex; | ||||||
|  |       justify-content: space-between; | ||||||
|  |       align-items: center; | ||||||
|  |       border: 1px solid #41464f; | ||||||
|  |       padding: 15px 20px; | ||||||
|  |       margin-bottom: 15px; | ||||||
|  |       border-radius: 10px; | ||||||
|  |       gap: 10px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .input-container { | ||||||
|  |       display: flex; | ||||||
|  |       align-items: center; | ||||||
|  |       gap: 5px; | ||||||
|  |       flex: 1; | ||||||
|  |       justify-content: flex-end; | ||||||
|  |       position: relative; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .input-row input, | ||||||
|  |     .input-row select, | ||||||
|  |     .row input,  | ||||||
|  |     .row select { | ||||||
|  |       background: transparent; | ||||||
|  |       border: 1px solid #41464f; | ||||||
|  |       padding: 8px 30px 8px 8px; | ||||||
|  |       border-radius: 10px; | ||||||
|  |       color: white; | ||||||
|  |       transition: color 0.2s; | ||||||
|  |       max-width: 40%; | ||||||
|  |       box-sizing: border-box; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .row input,  | ||||||
|  |     .row select { | ||||||
|  |       padding: 12px 30px 12px 12px; | ||||||
|  |       font-size: 16px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .input-row input:focus, | ||||||
|  |     .input-row select:focus, | ||||||
|  |     .row input, | ||||||
|  |     .row select { | ||||||
|  |       outline: none; | ||||||
|  |       background-color: black; | ||||||
|  |       color: var(--highlight-color); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .input-row select, | ||||||
|  |     .row select { | ||||||
|  |       appearance: none; | ||||||
|  |       -webkit-appearance: none; | ||||||
|  |       -moz-appearance: none; | ||||||
|  |       background-image: url('data:image/svg+xml;utf8,<svg fill="white" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5-5 5 5zM7 14l5 5 5-5z"/></svg>'); | ||||||
|  |       background-repeat: no-repeat; | ||||||
|  |       background-position: right 8px center; | ||||||
|  |       background-size: 16px; | ||||||
|  |       padding-right: 32px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | 	.info-container { | ||||||
|  | 		position: relative; | ||||||
|  | 		left: -18px; | ||||||
|  | 		top: -22px; | ||||||
|  | 		display: inline-block; | ||||||
|  | 		font-family: Arial, sans-serif; | ||||||
|  | 		margin: 0px; | ||||||
|  | 		width: 0px; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |     .info-icon { | ||||||
|  |       background-color: var(--highlight-color); | ||||||
|  |       color: black; | ||||||
|  |       border-radius: 50%; | ||||||
|  |       padding: 1px 4px; | ||||||
|  |       cursor: pointer; | ||||||
|  |       font-weight: bold; | ||||||
|  |       font-size: 10px; | ||||||
|  |       text-align: center; | ||||||
|  |       line-height: 1; | ||||||
|  |       display: inline-block; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .tooltip { | ||||||
|  |       visibility: hidden; | ||||||
|  |       background-color: #333; | ||||||
|  |       border-radius: 5px; | ||||||
|  |       padding: 4px 8px; | ||||||
|  |       position: absolute; | ||||||
|  |       z-index: 1; | ||||||
|  |       bottom: 100%; /* above the icon */ | ||||||
|  |       left: 50%; | ||||||
|  |       transform: translateX(-78%); | ||||||
|  |       opacity: 0; | ||||||
|  |       transition: opacity 0.3s; | ||||||
|  |       /*white-space: nowrap;*/ | ||||||
|  |       text-align: right; | ||||||
|  |       width: 300px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .tooltip::after { | ||||||
|  |       content: ""; | ||||||
|  |       position: absolute; | ||||||
|  |       top: 100%; /* bottom of tooltip */ | ||||||
|  |       left: 80%; | ||||||
|  |       margin-left: -5px; | ||||||
|  |       border-width: 5px; | ||||||
|  |       border-style: solid; | ||||||
|  |       border-color: #333 transparent transparent transparent; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .info-container:hover .tooltip { | ||||||
|  |       visibility: visible; | ||||||
|  |       opacity: 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .clear-btn { | ||||||
|  |       position: absolute; | ||||||
|  |       right: 8px; | ||||||
|  |       background: transparent; | ||||||
|  |       border: none; | ||||||
|  |       color: white; | ||||||
|  |       cursor: pointer; | ||||||
|  |       font-size: 16px; | ||||||
|  |       padding: 0; | ||||||
|  |       width: 20px; | ||||||
|  |       height: 20px; | ||||||
|  |       line-height: 20px; | ||||||
|  |       text-align: center; | ||||||
|  |       user-select: none; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .save-button { | ||||||
|  |       background-color: var(--highlight-color); | ||||||
|  |       color: black; | ||||||
|  |       border: none; | ||||||
|  |       padding: 15px 30px; | ||||||
|  |       font-size: 16px; | ||||||
|  |       border-radius: 10px; | ||||||
|  |       font-weight: bold; | ||||||
|  |       cursor: pointer; | ||||||
|  |       margin-top: 30px; | ||||||
|  |       align-self: flex-start; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .save-button:hover { | ||||||
|  |       background-color: #f5c300; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .buttons .btn { | ||||||
|  |       background-color: black; | ||||||
|  |       border: 1px solid #999; | ||||||
|  |       color: #999; | ||||||
|  |       padding: 10px 15px; | ||||||
|  |       font-size: 14px; | ||||||
|  |       border-radius: 5px; | ||||||
|  |       font-weight: bold; | ||||||
|  |       cursor: pointer; | ||||||
|  |       margin-top: 10px; | ||||||
|  |       align-self: flex-start; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .buttons .btn:hover { | ||||||
|  |       border: 1px solid #f5c300; | ||||||
|  |       color: #f5c300; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |         .hidden { | ||||||
|  |             display: none; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .popup { | ||||||
|  | 	    width: 100%; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .popup-content { | ||||||
|  |             width: 100%; | ||||||
|  |             text-align: left; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         #popup .row { | ||||||
|  |             display: flex; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     @media (max-width: 768px) { | ||||||
|  |       .sidebar { | ||||||
|  |         width: 80px; | ||||||
|  |         padding: 20px 5px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .logo { | ||||||
|  |         font-size: 0; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .logo span { | ||||||
|  |         display: none; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .menu-item { | ||||||
|  |         justify-content: center; | ||||||
|  |         gap: 0; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .menu-item span { | ||||||
|  |         display: none; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .yellow-box { | ||||||
|  |         font-size: 0; | ||||||
|  |         padding: 10px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .input-row { | ||||||
|  |         flex-direction: column; | ||||||
|  |         align-items: flex-start; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .input-container { | ||||||
|  |         width: 100%; | ||||||
|  |         justify-content: flex-start; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .input-row input, | ||||||
|  |       .input-row select { | ||||||
|  |         max-width: 100%; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||