init commit
This commit is contained in:
198
UI/index.php
Normal file
198
UI/index.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
require_once 'config.php';
|
||||
|
||||
// Wrapper variables for compatibility with existing template logic
|
||||
$api_url = $api_config['stats_url'];
|
||||
$refresh_interval = $api_config['refresh_interval'];
|
||||
|
||||
$timezone_abbr = date('T');
|
||||
$timezone_offset = date('P');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>OpenVPN Client Statistics</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
|
||||
<link href="css/style.css?v=<?php echo time(); ?>" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="js/utils.js?v=<?php echo time(); ?>"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="main-content-wrapper">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="d-flex justify-content-between align-items-start flex-wrap">
|
||||
<div class="mb-3 mb-md-0">
|
||||
<h1 class="h3 mb-1">OpenVPN Monitor</h1>
|
||||
<p class="text-muted mb-0">Real-time traffic & connection statistics</p>
|
||||
</div>
|
||||
<div class="d-flex align-items-center flex-wrap gap-2">
|
||||
<a href="index.php" class="btn-nav active">
|
||||
<i class="fas fa-list me-2"></i>Clients
|
||||
</a>
|
||||
<a href="certificates.php" class="btn-nav">
|
||||
<i class="fas fa-certificate me-2"></i>Certificates
|
||||
</a>
|
||||
<a href="dashboard.php" class="btn-nav">
|
||||
<i class="fas fa-chart-pie me-2"></i>Analytics
|
||||
</a>
|
||||
<span class="header-badge" id="clientCount">0 clients</span>
|
||||
<span class="header-timezone">
|
||||
<i class="fas fa-globe me-1 text-muted"></i><?php echo $timezone_abbr; ?>
|
||||
</span>
|
||||
<button class="btn-header" onclick="toggleTheme()" title="Toggle Theme">
|
||||
<i class="fas fa-moon" id="themeIcon"></i>
|
||||
</button>
|
||||
<button class="btn-header" onclick="fetchData()" title="Refresh">
|
||||
<i class="fas fa-sync-alt" id="refreshIcon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-info" id="statsInfo">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value" id="totalReceived">0 B</div>
|
||||
<div class="stat-label">Total Received</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value" id="totalSent">0 B</div>
|
||||
<div class="stat-label">Total Sent</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value" id="activeClients">0</div>
|
||||
<div class="stat-label">Active Clients</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-3">
|
||||
<div class="d-flex gap-3 align-items-center flex-wrap">
|
||||
<div class="sort-btn-group">
|
||||
<button class="sort-btn" onclick="changeSort('received')" id="sortRecv">Received</button>
|
||||
<button class="sort-btn active" onclick="changeSort('sent')" id="sortSent">Sent</button>
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm" style="width: 250px;">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" id="clientSearch" placeholder="Search client..."
|
||||
onkeyup="handleSearch(this.value)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="hideDisconnected"
|
||||
onchange="toggleDisconnected()">
|
||||
<label class="form-check-label user-select-none text-muted" for="hideDisconnected">Hide
|
||||
Disconnected</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-transparent border-bottom">
|
||||
<span><i class="fas fa-network-wired me-2"></i>Clients List</span>
|
||||
<small class="text-muted" id="lastUpdated">Updating...</small>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client Name</th>
|
||||
<th>Real Address</th>
|
||||
<th>Status</th>
|
||||
<th onclick="changeSort('received')" id="thRecv">Received</th>
|
||||
<th onclick="changeSort('sent')" id="thSent">Sent</th>
|
||||
<th>Max 30s DL</th>
|
||||
<th>Max 30s UL</th>
|
||||
<th>Last Activity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="statsTable">
|
||||
<tr>
|
||||
<td colspan="8" class="text-center py-4 text-muted">Loading...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="historyModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-chart-area me-2" style="color: var(--accent-color);"></i>
|
||||
<span id="modalClientName">Client Name</span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="chart-controls">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<label for="historyRange" class="text-muted"><i class="far fa-clock me-1"></i>
|
||||
Range:</label>
|
||||
<select id="historyRange" class="form-select form-select-sm"
|
||||
style="width: auto; min-width: 200px;" onchange="updateHistoryRange()">
|
||||
<option value="1h">Last 1 Hour (30s agg)</option>
|
||||
<option value="3h">Last 3 Hours (1m agg)</option>
|
||||
<option value="6h">Last 6 Hours (1m agg)</option>
|
||||
<option value="12h">Last 12 Hours (1m agg)</option>
|
||||
<option value="24h" selected>Last 24 Hours (1m agg)</option>
|
||||
<option disabled>──────────</option>
|
||||
<option value="24h">Last 1 Day (15m agg)</option>
|
||||
<option value="2d">Last 2 Days (15m agg)</option>
|
||||
<option value="3d">Last 3 Days (15m agg)</option>
|
||||
<option disabled>──────────</option>
|
||||
<option value="4d">Last 4 Days (1h agg)</option>
|
||||
<option value="5d">Last 5 Days (1h agg)</option>
|
||||
<option value="6d">Last 6 Days (1h agg)</option>
|
||||
<option value="7d">Last 7 Days (1h agg)</option>
|
||||
<option value="14d">Last 14 Days (1h agg)</option>
|
||||
<option value="30d">Last 1 Month (1h agg)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center gap-3 bg-white-custom px-3 py-1 border rounded">
|
||||
<span class="small fw-bold text-muted">Metric:</span>
|
||||
<div class="form-check form-switch mb-0">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="vizToggle"
|
||||
onchange="toggleVizMode()">
|
||||
<label class="form-check-label text-main" for="vizToggle" id="vizLabel">Data
|
||||
Volume</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-chart-container">
|
||||
<canvas id="trafficChart"></canvas>
|
||||
<div id="chartLoader" class="position-absolute top-50 start-50 translate-middle"
|
||||
style="display: none;">
|
||||
<div class="spinner-border text-primary" role="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/utils.js"></script>
|
||||
<script>
|
||||
// Pass PHP Configuration to JS
|
||||
window.AppConfig = {
|
||||
apiUrl: '<?php echo $api_url; ?>',
|
||||
refreshTime: <?php echo $refresh_interval; ?>
|
||||
};
|
||||
</script>
|
||||
<script src="js/pages/index.js?v=<?php echo time(); ?>"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user