Files
web-installer/manage3.html
2025-07-07 22:16:18 +00:00

968 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="hu">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<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" />
<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: 10px;
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;
margin: 4px;
}
.menu-item.active:hover {
color: black;
}
/* 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: 110px;
height: 110px;
object-fit: contain;
margin-bottom: 20px;
padding: 10px;
}
.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: var(--highlight-color);
border: none;
border-radius: 15px;
padding: 20px;
font-size: 16px;
font-weight: 400;
cursor: pointer;
width: 100%;
}
.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: 20px;
font-weight: bold;
margin: 0;
}
.subtitle {
font-size: 14px;
margin: 4px 0;
color: #999;
}
.description {
font-size: 12px;
margin: 20px 0 0;
color: #999;
}
.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"/>
</head>
<body>
<div class="sidebar">
<div>
<div class="logo">
<img src="/img/logo.png" alt="Safebox"/>
<span>Safebox</span>
</div>
<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-hdd"></i><span>Disk Management</span></div>
<div class="menu-item"><i class="fas fa-chart-line"></i><span>Monitor</span></div>
<div class="menu-item active"><i class="fas fa-cog"></i><span>Settings</span></div>
-->
<div class="menu-item" id="installAppsBtn"><img src="/img/app.png" data-src="/img/app.png" data-hover="/img/app2.png" alt="Applications" /><span>Applications</span></div>
<div class="menu-item" id="backupBtn"><img src="/img/disk.png" data-src="/img/disk.png" data-hover="/img/disk2.png" alt="Backup" /><span>Backup</span></div>
<div class="menu-item" id="diskBtn"><img src="/img/disk.png" data-src="/img/disk.png" data-hover="/img/disk2.png" alt="Disk Management" /><span>Disk Management</span></div>
<div class="menu-item" id="monitorBtn"><img src="/img/monitor.png" data-src="/img/monitor.png" data-hover="/img/monitor2.png" alt="Monitor" /><span>Monitor</span></div>
<div class="menu-item" id="settingsBtn"><img src="/img/settings.png" data-src="/img/settings.png" data-hover="/img/settings2.png" alt="Settings" /><span>Settings</span></div>
</div>
</div>
<div class="yellow-row">
<div class="yellow-box">
<h4>Safebox Pro</h4>
<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>
<img src="/img/upgrade.png" alt="Upgrade now" width="100%"/>
</p>
</div>
<div class="yellow-corner">
<img src="img/yellow_corner.png" alt=""/>
</div>
</div>
</div>
<div class="main" >
<div id="myAppsContainer">
</div>
<div id="popup" class="popup hidden">
<div class="popup-content">
<div id="popupText" class="deployment"></div>
</div>
</div>
</div>
<script>
// apps array beállítása common.js-ben
const apps = []; // GLOBAL VARIABLE
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.menu-item.active').forEach(item => {
const img = item.querySelector('img');
img.src = img.dataset.hover;
/*
item.addEventListener('mouseenter', () => {
img.src = img.dataset.hover;
});
item.addEventListener('mouseleave', () => {
img.src = img.dataset.src;
});
*/
});
const myAppsBtn = document.getElementById('myAppsBtn');
const installAppsBtn = document.getElementById('installAppsBtn');
const backupBtn = document.getElementById('backupBtn');
const diskBtn = document.getElementById('diskBtn');
const monitorBtn = document.getElementById('monitorBtn');
const settingsBtn = document.getElementById('settingsBtn');
const vpnBtn = document.getElementById('vpnBtn');
const myAppsContainer = document.getElementById('myAppsContainer');
const popup = document.getElementById('popup');
const popupText = document.getElementById('popupText');
const closeBtn = document.querySelector('.close');
//Appok betöltése
function renderApps(all) {
myAppsContainer.classList.remove('hidden');
popup.classList.add('hidden');
myAppsContainer.innerHTML = '<div class="main-header"><h1>Applications</h1><button id="updatesBtn"><i class="fas fa-bell"></i> Notification</button></div><div id="appsContainer"></div>';
const appsContainer = document.getElementById('appsContainer');
const updatesBtn = document.getElementById('updatesBtn');
updatesBtn.addEventListener('click', () => renderUpdates());
apps.forEach(app => {
//if ((all==false && app.installed=='true') || (all==true && app.installed!='true')) {
const appDiv = document.createElement('div');
appDiv.className = 'app';
appDiv.innerHTML = `
<div class="app-img"><img src="${app.image}" alt="${app.name}" title="${app.orig_name} ${app.version}"></div>
<div class="app-label">${app.name} ${app.version}</div>
<div class="app-name">${app.orig_name}</div>
<button class="more-btn">More</button>
`;
appDiv.addEventListener('click', () => {
popupText.textContent = `You clicked on ${app.name} ${app.version}!`;
if (app.installed=='true') reinstall(app.name, 'popupText');
else load_template(app.name,'popupText');
popup.classList.remove('hidden');
myAppsContainer.classList.add('hidden');
});
appsContainer.appendChild(appDiv);
//}
});
}
//TODO: Ilyen függvényeket kell csinálni és a listenerekhez adni az egyes részeket
function renderText(title) {
//TODO: itt kell a buttont editálni és így kell hozzáadni hozzá mindent
myAppsContainer.innerHTML = `
<h1 style="text-align: center;">${title}</h1>
<div class="input-group">
<input type="text" placeholder="Írj be valamit..." id="textInput">
<button id="submitButton">Küldés</button>
<select id="myComboBox" class="custom-select">
<option value="">Válassz egy lehetőséget...</option>
<option value="1">Első opció</option>
<option value="2">Második opció</option>
<option value="3">Harmadik opció</option>
</select>
<label class="checkbox-container">
<input type="checkbox" id="myCheckbox">
<span class="checkmark"></span>
Elfogadom a feltételeket
</label>
</div>
`;
const submitButton = document.getElementById('submitButton');
const textInput = document.getElementById('textInput');
if (submitButton && textInput) {
submitButton.addEventListener('click', () => {
const value = textInput.value.trim();
if (value) {
alert(`Beírt szöveg: ${value}`);
textInput.value = '';
} else {
alert('Kérlek írj be valamit!');
}
});
}
}
function renderVPN() {
myAppsContainer.innerHTML = `
<div class="main-header">
<h1>VPN</h1>
</div>
<div id="vpn" class="innerDiv">
Loading...
</div>
`;
get_proxy_html();
}
function renderServices() {
myAppsContainer.innerHTML = `
<div class="main-header">
<h1>Services</h1>
</div>
<div id="services" class="innerDiv">
Loading...
</div>
`;
get_services();
}
function renderUpdates() {
myAppsContainer.innerHTML = `
<div class="main-header">
<h1>Updates</h1>
</div>
<div id="updates" class="innerDiv">
Looking for updates... Please wait...
</div>
`;
get_updates();
}
function renderSystemServices() {
myAppsContainer.innerHTML = `
<div class="main-header">
<h1>System services</h1>
</div>
<div id="system" class="innerDiv">
Loading...
</div>
`;
get_system();
}
function renderSettings() {
myAppsContainer.innerHTML = `
<div class="main-header">
<h1>Settings</h1>
<button id="updatesBtn"><i class="fas fa-bell"></i> Notification</button>
</div>
<div class="input-row">
<button id="servicesBtn" class="save-button">Services</button>
<button id="repositoriesBtn" class="save-button">Repositories</button>
<button id="systemservicesBtn" class="save-button">System services</button>
</div>
<div class="input-row">
<label>Docker registry name</label>
<div class="input-container">
<input type="text" placeholder="Enter name" />
<button class="clear-btn" onclick="this.previousElementSibling.value = ''">×</button>
</div>
</div>
<div class="input-row">
<label>Enable logging</label>
<div class="input-container">
<select>
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
<div class="input-row">
<label>Backup folder</label>
<div class="input-container">
<input type="text" placeholder="Path to backup" />
<button class="clear-btn" onclick="this.previousElementSibling.value = ''">×</button>
</div>
</div>
<div class="input-row">
<label>Send alerts</label>
<div class="input-container">
<select>
<option>Yes</option>
<option>No</option>
</select>
</div>
</div>
<button class="save-button">Save Settings</button>
`;
const servicesBtn = document.getElementById('servicesBtn');
const repositoriesBtn = document.getElementById('repositoriesBtn');
const systemservicesBtn = document.getElementById('systemservicesBtn');
const updatesBtn = document.getElementById('updatesBtn');
servicesBtn.addEventListener('click', () => renderServices());
repositoriesBtn.addEventListener('click', () => renderRepositories());
systemservicesBtn.addEventListener('click', () => renderSystemServices());
updatesBtn.addEventListener('click', () => renderUpdates());
}
function renderRepositories() {
myAppsContainer.innerHTML = `
<div class="main-header">
<h1>Repositories</h1>
</div>
<div id="repositories" style="text-align:left">Loading...</div>
<br>
<form class="form-install" action="#" method="post" id="add_repo">
<div class="input-row">
<label for="registry">Please add a new GIT repository URL: </label>
<div class="input-container">
<input type="registry" name="repository" id="repository" size="100" value="" required>
<button class="clear-btn" onclick="this.previousElementSibling.value = ''">×</button>
</div>
<!--<div class="invalid-feedback">
Please enter a valid repository url.
</div>-->
</div>
<div class="row">
<button class="save-button" type="submit" id="repo_add_btn"> Add </button>
</div>
</form>
`;
jQuery('#add_repo').submit(function() {
jQuery('#repositories').html('Loading...');
add_repository();
return false;
});
get_repositories();
}
function activate(btn) {
//myAppsBtn.classList.remove('active');
installAppsBtn.classList.remove('active');
backupBtn.classList.remove('active');
diskBtn.classList.remove('active');
monitorBtn.classList.remove('active');
settingsBtn.classList.remove('active');
btn.classList.add('active');
}
//myAppsBtn.addEventListener('click', () => {renderApps(false); activate(myAppsBtn);});
installAppsBtn.addEventListener('click', () => {renderApps(true); activate(installAppsBtn);});
backupBtn.addEventListener('click', () => {renderText('Backup'); activate(backupBtn);});
diskBtn.addEventListener('click', () => {renderText('Disk Management'); activate(diskBtn)});
monitorBtn.addEventListener('click', () => {renderText('Monitor'); activate(monitorBtn)});
settingsBtn.addEventListener('click', () => {renderSettings(); activate(settingsBtn)});
vpnBtn.addEventListener('click', () => renderVPN());
// renderApps(true);
const vpnToggle = document.getElementById("vpnToggle");
const vpnLabel = document.querySelector(".switch-label");
function updateStatus() {
vpnLabel.textContent = vpnToggle.checked ? "ON" : "OFF";
}
vpnToggle.addEventListener("change", updateStatus);
// Alapállapot beállítása
updateStatus();
});
</script>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<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/bootstrap@4.2.1/dist/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<script src="common.js?t=10"></script>
</body>
</html>