Files
amneziavpnphp/templates/layout.twig
T
infosave2007 257edb8226 feat: Implement server and client metrics collection and monitoring
- Added a new PHP script for collecting server metrics every 30 seconds.
- Created a ServerMonitoring class to handle metrics collection for CPU, RAM, Disk, and Network.
- Introduced database tables for storing server and client metrics.
- Updated server view template to display real-time metrics using Chart.js.
- Added translations for monitoring UI elements.
- Created a new monitoring template for detailed server metrics visualization.
- Implemented client speed tracking and display in the monitoring UI.
2025-11-08 15:35:17 +03:00

179 lines
8.4 KiB
Twig

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{{ app_name }}{% endblock %}</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
{% block styles %}{% endblock %}
<style>
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.mobile-menu {
display: none;
}
.mobile-menu.active {
display: block;
}
.language-dropdown {
display: none;
}
.language-dropdown.active {
display: block;
}
</style>
</head>
<body class="bg-gray-50">
{% if user %}
<!-- Navigation -->
<nav class="gradient-bg shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex">
<div class="flex-shrink-0 flex items-center">
<i class="fas fa-shield-alt text-white text-2xl mr-2"></i>
<span class="text-white text-xl font-bold">{{ app_name }}</span>
</div>
<!-- Desktop Menu -->
<div class="hidden md:ml-6 md:flex md:space-x-8">
<a href="/dashboard" class="text-white hover:text-gray-200 inline-flex items-center px-1 pt-1 text-sm font-medium">
<i class="fas fa-tachometer-alt mr-2"></i>{{ t('menu.dashboard') }}
</a>
<a href="/servers" class="text-white hover:text-gray-200 inline-flex items-center px-1 pt-1 text-sm font-medium">
<i class="fas fa-server mr-2"></i>{{ t('menu.servers') }}
</a>
{% if user.role == 'admin' %}
<a href="/settings" class="text-white hover:text-gray-200 inline-flex items-center px-1 pt-1 text-sm font-medium">
<i class="fas fa-cog mr-2"></i>{{ t('menu.settings') }}
</a>
{% endif %}
</div>
</div>
<div class="flex items-center">
<!-- Language Selector -->
<div class="relative mr-4">
<button onclick="toggleLanguageDropdown()" class="text-white hover:text-gray-200 flex items-center focus:outline-none">
{% set currentLang = current_language %}
{% for lang in languages %}
{% if lang.code == currentLang %}
<span class="mr-2">{{ getFlag(lang.code) }}</span>
{% endif %}
{% endfor %}
<i class="fas fa-chevron-down ml-1 text-xs"></i>
</button>
<div id="languageDropdown" class="language-dropdown absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg z-50">
{% for lang in languages %}
<form method="POST" action="/language/change" class="block">
<input type="hidden" name="language" value="{{ lang.code }}">
<input type="hidden" name="redirect" value="{{ current_uri }}">
<button type="submit" class="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center
{% if lang.code == current_language %}bg-purple-50 font-medium{% endif %}">
<span class="mr-2">{{ getFlag(lang.code) }}</span>
<span>{{ lang.name }}</span>
{% if lang.code == current_language %}
<i class="fas fa-check text-purple-600 ml-auto"></i>
{% endif %}
</button>
</form>
{% endfor %}
</div>
</div>
<!-- User Menu (Desktop) -->
<div class="hidden md:flex items-center">
<span class="text-white mr-4">
<i class="fas fa-user mr-1"></i>{{ user.name }}
</span>
<a href="/logout" class="text-white hover:text-gray-200">
<i class="fas fa-sign-out-alt mr-1"></i>{{ t('menu.logout') }}
</a>
</div>
<!-- Mobile menu button -->
<div class="md:hidden flex items-center ml-4">
<button onclick="toggleMobileMenu()" type="button" class="text-white hover:text-gray-200 focus:outline-none">
<i class="fas fa-bars text-xl"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Mobile Menu -->
<div id="mobileMenu" class="mobile-menu md:hidden">
<div class="px-2 pt-2 pb-3 space-y-1">
<a href="/dashboard" class="text-white hover:bg-purple-700 block px-3 py-2 rounded-md text-base font-medium">
<i class="fas fa-tachometer-alt mr-2"></i>{{ t('menu.dashboard') }}
</a>
<a href="/servers" class="text-white hover:bg-purple-700 block px-3 py-2 rounded-md text-base font-medium">
<i class="fas fa-server mr-2"></i>{{ t('menu.servers') }}
</a>
{% if user.role == 'admin' %}
<a href="/settings" class="text-white hover:bg-purple-700 block px-3 py-2 rounded-md text-base font-medium">
<i class="fas fa-cog mr-2"></i>{{ t('menu.settings') }}
</a>
{% endif %}
<div class="border-t border-purple-500 my-2"></div>
<div class="text-white px-3 py-2">
<i class="fas fa-user mr-1"></i>{{ user.name }}
</div>
<a href="/logout" class="text-white hover:bg-purple-700 block px-3 py-2 rounded-md text-base font-medium">
<i class="fas fa-sign-out-alt mr-1"></i>{{ t('menu.logout') }}
</a>
</div>
</div>
</nav>
{% endif %}
<!-- Main Content -->
<main class="{% if user %}py-10{% endif %}">
{% block content %}{% endblock %}
</main>
<!-- Footer -->
<footer class="bg-white border-t border-gray-200 mt-auto">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<p class="text-center text-gray-500 text-sm">
{{ app_name }} &copy; 2025 | Open Source VPN Management Panel
</p>
</div>
</footer>
<script>
function toggleMobileMenu() {
const menu = document.getElementById('mobileMenu');
menu.classList.toggle('active');
}
function toggleLanguageDropdown() {
const dropdown = document.getElementById('languageDropdown');
dropdown.classList.toggle('active');
}
// Close dropdown when clicking outside
document.addEventListener('click', function(event) {
const languageButton = event.target.closest('button[onclick="toggleLanguageDropdown()"]');
const dropdown = document.getElementById('languageDropdown');
const isInsideDropdown = dropdown && dropdown.contains(event.target);
// Don't close if clicking the button or inside dropdown (except submit buttons)
if (!languageButton && !isInsideDropdown && dropdown) {
dropdown.classList.remove('active');
}
});
// Ensure dropdown stays open when form is being submitted
document.addEventListener('submit', function(event) {
if (event.target.closest('#languageDropdown')) {
// Form will submit normally, dropdown will close on page reload
}
});
</script>
{% block scripts %}{% endblock %}
</body>
</html>