mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-05-13 02:45:04 +00:00
Add dashboard audit log and configuration management
- Implemented dashboard audit logging with InsertAuditLog, GetRecentAuditLogs, GetAuditLogsByIP, and CleanupOldAuditLogs methods. - Created dashboard configuration management with GetDashboardConfig and SetDashboardConfig methods. - Added new tables for dashboard_audit_log and dashboard_config in both MySQL and SQLite migrations. - Updated CMakeLists to include Crow and ASIO for dashboard server functionality. - Enhanced existing database classes to support new dashboard features, including character, play key, and property management. - Added new methods for retrieving and managing play keys, properties, and pet names. - Updated TestSQLDatabase to include stubs for new dashboard-related methods. - Modified shared and dashboard configuration files for new settings.
This commit is contained in:
293
dDashboardServer/templates/index.html
Normal file
293
dDashboardServer/templates/index.html
Normal file
@@ -0,0 +1,293 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="mb-4">Dashboard</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#is_authenticated}}
|
||||
<div class="row">
|
||||
<!-- Account Info Card -->
|
||||
<div class="col-md-6 col-lg-3 mb-4">
|
||||
<div class="card stats-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="bi bi-person-circle text-primary"></i>
|
||||
Your Account
|
||||
</h5>
|
||||
<p class="card-text">
|
||||
<strong>Username:</strong> {{username}}<br>
|
||||
<strong>Account ID:</strong> {{account_id}}<br>
|
||||
<strong>GM Level:</strong> {{gm_level}} ({{gm_level_name}})
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#is_gm_3_plus}}
|
||||
<!-- Server Stats Card -->
|
||||
<div class="col-md-6 col-lg-3 mb-4">
|
||||
<div class="card stats-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="bi bi-server text-success"></i>
|
||||
Server Status
|
||||
</h5>
|
||||
<div id="server-stats">
|
||||
<p class="card-text">
|
||||
<strong>Master:</strong> <span id="master-status" class="badge bg-secondary">Loading...</span><br>
|
||||
<strong>Connected Clients:</strong> <span id="client-count">-</span><br>
|
||||
<strong>Packets Sent:</strong> <span id="packets-sent">-</span><br>
|
||||
<strong>Packets Received:</strong> <span id="packets-received">-</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Accounts Card -->
|
||||
<div class="col-md-6 col-lg-3 mb-4">
|
||||
<div class="card stats-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="bi bi-people text-info"></i>
|
||||
Accounts
|
||||
</h5>
|
||||
<p class="card-text">
|
||||
<strong>Total Accounts:</strong> <span id="total-accounts">-</span><br>
|
||||
<strong>Banned:</strong> <span id="banned-accounts">-</span><br>
|
||||
<strong>Locked:</strong> <span id="locked-accounts">-</span>
|
||||
</p>
|
||||
<a href="/accounts" class="btn btn-sm btn-primary">Manage Accounts</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Characters Card -->
|
||||
<div class="col-md-6 col-lg-3 mb-4">
|
||||
<div class="card stats-card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="bi bi-person-badge text-warning"></i>
|
||||
Characters
|
||||
</h5>
|
||||
<p class="card-text">
|
||||
<strong>Total Characters:</strong> <span id="total-characters">-</span><br>
|
||||
<strong>Pending Names:</strong> <span id="pending-names">-</span>
|
||||
</p>
|
||||
<a href="/characters" class="btn btn-sm btn-primary">Manage Characters</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/is_gm_3_plus}}
|
||||
</div>
|
||||
|
||||
{{#is_gm_3_plus}}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-activity"></i>
|
||||
Recent Activity
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="recent-activity-table" class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Character</th>
|
||||
<th>Activity</th>
|
||||
<th>Map</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Populated via API -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/is_gm_3_plus}}
|
||||
|
||||
<!-- Character Cards for All Authenticated Users -->
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<h3 class="mb-3">
|
||||
<i class="bi bi-person-badge"></i>
|
||||
Your Characters
|
||||
</h3>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" id="character-cards-container">
|
||||
<!-- Character cards will be populated via JavaScript -->
|
||||
<div class="col-12 text-center">
|
||||
<p class="text-muted">Loading characters...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/is_authenticated}}
|
||||
|
||||
{{^is_authenticated}}
|
||||
<div class="row">
|
||||
<div class="col-md-6 offset-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body text-center">
|
||||
<h3>Welcome to DarkflameServer Dashboard</h3>
|
||||
<p class="lead">Please log in to access the dashboard.</p>
|
||||
<a href="/login" class="btn btn-primary btn-lg">Login</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/is_authenticated}}
|
||||
|
||||
<script>
|
||||
{{#is_gm_3_plus}}
|
||||
// Load dashboard stats
|
||||
async function loadDashboardStats() {
|
||||
try {
|
||||
// Server stats
|
||||
const serverStats = await API.get('/api/stats/server');
|
||||
if (serverStats) {
|
||||
updateServerStats(serverStats);
|
||||
}
|
||||
|
||||
// Account stats
|
||||
const accountStats = await API.get('/api/stats/accounts');
|
||||
if (accountStats) {
|
||||
updateAccountStats(accountStats);
|
||||
}
|
||||
|
||||
// Character stats
|
||||
const characterStats = await API.get('/api/stats/characters');
|
||||
if (characterStats) {
|
||||
updateCharacterStats(characterStats);
|
||||
}
|
||||
|
||||
// Recent activity
|
||||
const activities = await API.get('/api/stats/recent-activity');
|
||||
if (activities && activities.data) {
|
||||
updateRecentActivity(activities.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading dashboard stats:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Update server stats on UI
|
||||
function updateServerStats(data) {
|
||||
document.getElementById('master-status').textContent = data.master_connected ? 'Connected' : 'Disconnected';
|
||||
document.getElementById('master-status').className = data.master_connected ? 'badge bg-success' : 'badge bg-danger';
|
||||
document.getElementById('client-count').textContent = data.connected_clients || 0;
|
||||
document.getElementById('packets-sent').textContent = data.packets_sent || 0;
|
||||
document.getElementById('packets-received').textContent = data.packets_received || 0;
|
||||
}
|
||||
|
||||
// Update account stats on UI
|
||||
function updateAccountStats(data) {
|
||||
document.getElementById('total-accounts').textContent = data.total || 0;
|
||||
document.getElementById('banned-accounts').textContent = data.banned || 0;
|
||||
document.getElementById('locked-accounts').textContent = data.locked || 0;
|
||||
}
|
||||
|
||||
// Update character stats on UI
|
||||
function updateCharacterStats(data) {
|
||||
document.getElementById('total-characters').textContent = data.total || 0;
|
||||
document.getElementById('pending-names').textContent = data.pending_names || 0;
|
||||
}
|
||||
|
||||
// Update recent activity table
|
||||
function updateRecentActivity(data) {
|
||||
// Avoid reinitialising the DataTable on repeated calls (e.g. interval refreshs).
|
||||
// If the table already exists, update its data and redraw. Otherwise initialize it.
|
||||
if ($.fn.DataTable.isDataTable('#recent-activity-table')) {
|
||||
const table = $('#recent-activity-table').DataTable();
|
||||
table.clear();
|
||||
table.rows.add(data);
|
||||
table.draw(false);
|
||||
} else {
|
||||
const table = $('#recent-activity-table').DataTable({
|
||||
data: data,
|
||||
columns: [
|
||||
{ data: 'timestamp' },
|
||||
{ data: 'character_name' },
|
||||
{ data: 'activity' },
|
||||
{ data: 'map_id' }
|
||||
],
|
||||
pageLength: 10,
|
||||
order: [[0, 'desc']]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initial load
|
||||
document.addEventListener('DOMContentLoaded', loadDashboardStats);
|
||||
|
||||
// Auto-refresh stats every 30 seconds
|
||||
setInterval(loadDashboardStats, 30000);
|
||||
{{/is_gm_3_plus}}
|
||||
|
||||
{{#is_authenticated}}
|
||||
// Load user's characters for character cards
|
||||
async function loadUserCharacters() {
|
||||
try {
|
||||
const res = await API.get('/api/user/characters');
|
||||
const characters = (res && Array.isArray(res.data)) ? res.data : (res || []);
|
||||
|
||||
const container = document.getElementById('character-cards-container');
|
||||
container.innerHTML = '';
|
||||
|
||||
if (characters.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="col-12 text-center">
|
||||
<p class="text-muted">You don't have any characters yet. Log in to the game to create one!</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
characters.forEach(char => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'col-md-6 col-lg-4 mb-4';
|
||||
card.innerHTML = `
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="bi bi-person-circle"></i>
|
||||
${char.name}
|
||||
</h5>
|
||||
<p class="card-text">
|
||||
<strong>Level:</strong> ${char.level || 0}<br>
|
||||
<strong>Universe Score:</strong> ${char.uscore || 0}<br>
|
||||
<strong>Current Zone:</strong> ${char.zone_id || 'Unknown'}<br>
|
||||
<strong>Last Login:</strong> ${char.last_login && char.last_login > 0 ? new Date(char.last_login * 1000).toLocaleString() : 'Never'}
|
||||
</p>
|
||||
${char.pending_name ? `<span class="badge bg-warning mb-2">Pending Name: ${char.pending_name}</span><br>` : ''}
|
||||
${char.needs_rename ? '<span class="badge bg-danger mb-2">Needs Rename</span><br>' : ''}
|
||||
<a href="/characters/view/${char.id}" class="btn btn-sm btn-primary mt-2">View Details</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(card);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error loading user characters:', error);
|
||||
const container = document.getElementById('character-cards-container');
|
||||
container.innerHTML = `
|
||||
<div class="col-12">
|
||||
<div class="alert alert-warning">
|
||||
Failed to load your characters. Please try refreshing the page.
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Load character cards on page load
|
||||
document.addEventListener('DOMContentLoaded', loadUserCharacters);
|
||||
{{/is_authenticated}}
|
||||
</script>
|
||||
Reference in New Issue
Block a user