Files
server-manager/views/layouts/main.php

184 lines
8.7 KiB
PHP
Executable File

<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?? '' ?>">
<title><?= htmlspecialchars($title ?? 'ServerManager') ?></title>
<link rel="icon" type="image/svg+xml" href="/assets/img/server.svg">
<link rel="stylesheet" href="/assets/css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head>
<body>
<div class="app-container">
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<a href="/dashboard" class="sidebar-logo">
<i class="fas fa-server"></i>
<span class="logo-text">ServerManager</span>
</a>
<button class="sidebar-toggle" id="sidebarToggle" title="Toggle sidebar">
<i class="fas fa-bars"></i>
</button>
</div>
<nav class="sidebar-nav">
<ul class="nav-list">
<li class="nav-item">
<a href="/dashboard" class="nav-link <?= str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/dashboard') ? 'active' : '' ?>">
<i class="fas fa-tachometer-alt"></i>
<span>Dashboard</span>
</a>
</li>
<li class="nav-item nav-item-accordion <?= str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/servers') ? 'active' : '' ?>">
<a href="#" class="nav-link" onclick="toggleServerList(event)">
<i class="fas fa-hdd"></i>
<span>Servers</span>
<i class="fas fa-chevron-right nav-chevron"></i>
</a>
<div class="nav-submenu" id="serverList">
<div class="nav-submenu-loading"><i class="fas fa-spinner fa-spin"></i></div>
</div>
</li>
<?php if (in_array($_SESSION['user_role'] ?? '', ['super_admin', 'admin'])): ?>
<li class="nav-divider"></li>
<li class="nav-section">Administration</li>
<li class="nav-item">
<a href="/teams" class="nav-link <?= str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/teams') ? 'active' : '' ?>">
<i class="fas fa-users-cog"></i>
<span>Teams</span>
</a>
</li>
<li class="nav-item">
<a href="/admin/users" class="nav-link <?= str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/admin/users') ? 'active' : '' ?>">
<i class="fas fa-users"></i>
<span>Users</span>
</a>
</li>
<li class="nav-item">
<a href="/admin/audit" class="nav-link <?= str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/admin/audit') ? 'active' : '' ?>">
<i class="fas fa-history"></i>
<span>Audit Logs</span>
</a>
</li>
<?php if ($_SESSION['user_role'] ?? '' === 'super_admin'): ?>
<li class="nav-item">
<a href="/admin/security" class="nav-link <?= str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/admin/security') ? 'active' : '' ?>">
<i class="fas fa-shield-alt"></i>
<span>Security</span>
</a>
</li>
<?php endif; ?>
<?php endif; ?>
</ul>
</nav>
<div class="sidebar-footer">
<div class="user-info">
<div class="user-avatar">
<?= strtoupper(substr($_SESSION['username'] ?? '?', 0, 2)) ?>
</div>
<div class="user-details">
<span class="user-name"><?= htmlspecialchars($_SESSION['username'] ?? 'Guest') ?></span>
<span class="user-role"><?= htmlspecialchars(ucfirst(str_replace('_', ' ', $_SESSION['user_role'] ?? 'guest'))) ?></span>
</div>
<div class="user-menu">
<a href="/profile" title="Profile"><i class="fas fa-user-cog"></i></a>
<a href="/logout" title="Logout"><i class="fas fa-sign-out-alt"></i></a>
</div>
</div>
</div>
</aside>
<main class="main-content">
<header class="top-bar">
<div class="top-bar-left">
<button class="mobile-toggle" id="mobileToggle">
<i class="fas fa-bars"></i>
</button>
<div class="breadcrumb">
<?= htmlspecialchars($title ?? 'ServerManager') ?>
</div>
</div>
<div class="top-bar-right">
<div class="top-bar-actions">
<button class="btn-icon" id="refreshBtn" title="Refresh">
<i class="fas fa-sync-alt"></i>
</button>
<button class="btn-icon" id="themeToggle" title="Toggle theme">
<i class="fas fa-moon"></i>
</button>
</div>
</div>
</header>
<div class="content-area">
<?php if ($flash = \ServerManager\Core\Session::getAllFlashes()): ?>
<?php foreach ($flash as $type => $messages): ?>
<?php foreach ($messages as $message): ?>
<div class="toast toast-<?= htmlspecialchars($type) ?>" data-autohide="true">
<div class="toast-body">
<i class="fas fa-<?= $type === 'success' ? 'check-circle' : ($type === 'error' ? 'times-circle' : 'info-circle') ?>"></i>
<?= htmlspecialchars($message) ?>
</div>
<button class="toast-close">&times;</button>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
<?php endif; ?>
<?= $content ?? '' ?>
</div>
</main>
</div>
<div id="toastContainer" class="toast-container"></div>
<script src="/assets/js/app.js"></script>
<?php if (isset($scripts)): ?>
<?php foreach ($scripts as $script): ?>
<script src="<?= htmlspecialchars($script) ?>"></script>
<?php endforeach; ?>
<?php endif; ?>
<script>
let serverListLoaded = false;
function toggleServerList(e) {
e.preventDefault();
const item = e.currentTarget.closest('.nav-item-accordion');
const sub = document.getElementById('serverList');
const chevron = item.querySelector('.nav-chevron');
if (item.classList.contains('expanded')) {
item.classList.remove('expanded');
sub.style.maxHeight = '0';
return;
}
item.classList.add('expanded');
if (!serverListLoaded) {
serverListLoaded = true;
fetch('/sidebar/servers')
.then(r => r.json())
.then(d => {
if (d.success && d.data) {
let html = '<a href="/servers" class="nav-sub-item"><i class="fas fa-list"></i> All Servers</a>';
d.data.forEach(s => {
const status = s.current_status === 'online' ? 'success' : s.current_status === 'offline' ? 'danger' : 'muted';
html += '<a href="/servers/' + s.id + '" class="nav-sub-item">'
+ '<span class="status-dot-sm status-' + status + '"></span> '
+ s.name + '</a>';
});
sub.innerHTML = html;
} else {
sub.innerHTML = '<div class="nav-sub-item" style="color:var(--text-muted)">No servers</div>';
}
sub.style.maxHeight = sub.scrollHeight + 'px';
})
.catch(() => {
sub.innerHTML = '<div class="nav-sub-item" style="color:var(--danger)">Failed to load</div>';
sub.style.maxHeight = sub.scrollHeight + 'px';
});
} else {
sub.style.maxHeight = sub.scrollHeight + 'px';
}
}
</script>
</body>
</html>