mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-30 10:34:21 +00:00
WIP
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Account #{{ account.id }} - {{ account.name }}</h2>
|
||||
<h2>Account #{{ account.id }} - <span class="account-name">{{ account.name }}</span></h2>
|
||||
<p class="text-muted">View account details and manage settings</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
<div class="detail-item">
|
||||
<div class="detail-label">Username</div>
|
||||
<div class="detail-value">{{ account.name }}</div>
|
||||
<div class="detail-value"><span class="account-name">{{ account.name }}</span></div>
|
||||
</div>
|
||||
|
||||
<div class="detail-item">
|
||||
@@ -35,9 +35,9 @@
|
||||
<div class="detail-label">GM Level</div>
|
||||
<div class="detail-value">
|
||||
{% if account.gm_level > 0 %}
|
||||
<span class="badge badge-gm">GM {{ account.gm_level }}</span>
|
||||
<span class="account-gm-level badge badge-gm">GM {{ account.gm_level }}</span>
|
||||
{% else %}
|
||||
<span class="badge badge-inactive">User</span>
|
||||
<span class="account-gm-level badge badge-inactive">User</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,9 +46,9 @@
|
||||
<div class="detail-label">Ban Status</div>
|
||||
<div class="detail-value">
|
||||
{% if account.banned %}
|
||||
<span class="badge badge-banned">BANNED</span>
|
||||
<span class="account-banned badge badge-banned">BANNED</span>
|
||||
{% else %}
|
||||
<span class="badge badge-active">Active</span>
|
||||
<span class="account-banned badge badge-active">Active</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,9 +57,9 @@
|
||||
<div class="detail-label">Lock Status</div>
|
||||
<div class="detail-value">
|
||||
{% if account.locked %}
|
||||
<span class="badge badge-locked">LOCKED</span>
|
||||
<span class="account-locked badge badge-locked">LOCKED</span>
|
||||
{% else %}
|
||||
<span class="badge badge-active">Unlocked</span>
|
||||
<span class="account-locked badge badge-active">Unlocked</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -67,11 +67,13 @@
|
||||
<div class="detail-item">
|
||||
<div class="detail-label">Mute Expires</div>
|
||||
<div class="detail-value">
|
||||
{% if account.mute_expire > 0 %}
|
||||
<span>{{ account.mute_expire }}</span>
|
||||
{% else %}
|
||||
<span class="text-muted">Not muted</span>
|
||||
{% endif %}
|
||||
<span class="account-mute-expire">
|
||||
{% if account.mute_expire > 0 %}
|
||||
Muted until {{ account.mute_expire }}
|
||||
{% else %}
|
||||
Not muted
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,7 +102,18 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/realtime.js"></script>
|
||||
<script>
|
||||
// Set current account for real-time detail panel updates
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
realtimeManager.SetCurrentEntity('account', {{ account.id }});
|
||||
|
||||
// Clean up when leaving the page
|
||||
window.addEventListener('beforeunload', () => {
|
||||
realtimeManager.ClearCurrentEntity();
|
||||
});
|
||||
});
|
||||
|
||||
function EditAccount() {
|
||||
alert("Edit functionality coming soon");
|
||||
// TODO: Open edit modal
|
||||
@@ -110,6 +123,7 @@
|
||||
if (confirm("Are you sure you want to ban this account?")) {
|
||||
alert("Ban functionality coming soon");
|
||||
// TODO: Call ban API endpoint
|
||||
// After successful ban, call: BroadcastAccountUpdate({{ account.id }})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +131,7 @@
|
||||
if (confirm("Are you sure you want to unban this account?")) {
|
||||
alert("Unban functionality coming soon");
|
||||
// TODO: Call unban API endpoint
|
||||
// After successful unban, call: BroadcastAccountUpdate({{ account.id }})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +139,7 @@
|
||||
if (confirm("Are you sure you want to lock this account?")) {
|
||||
alert("Lock functionality coming soon");
|
||||
// TODO: Call lock API endpoint
|
||||
// After successful lock, call: BroadcastAccountUpdate({{ account.id }})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +147,7 @@
|
||||
if (confirm("Are you sure you want to unlock this account?")) {
|
||||
alert("Unlock functionality coming soon");
|
||||
// TODO: Call unlock API endpoint
|
||||
// After successful unlock, call: BroadcastAccountUpdate({{ account.id }})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
{% block content %}
|
||||
<div class="accounts-container">
|
||||
<div class="container-fluid">
|
||||
<div class="table-card">
|
||||
<div class="table-header">
|
||||
<h2 class="mb-0">Accounts</h2>
|
||||
<p class="text-muted">View and manage user accounts</p>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Accounts</h2>
|
||||
<p class="text-muted">View and manage user accounts - <span class="account-count">0</span> total</p>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table id="accountsTable" class="table table-dark table-hover mb-0">
|
||||
<thead>
|
||||
@@ -39,10 +39,11 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/realtime.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable with server-side processing
|
||||
$('#accountsTable').DataTable({
|
||||
const table = $('#accountsTable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
pageLength: 25,
|
||||
@@ -119,6 +120,25 @@
|
||||
order: [[0, 'asc']],
|
||||
stateSave: false
|
||||
});
|
||||
|
||||
// Register table for real-time updates
|
||||
realtimeManager.RegisterTable('account', table);
|
||||
|
||||
// Update account count when DataTable loads
|
||||
table.on('draw.dt', function() {
|
||||
const info = table.page.info();
|
||||
const countEl = document.querySelector('.account-count');
|
||||
if (countEl && info) {
|
||||
countEl.textContent = info.recordsTotal;
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize real-time listener when WebSocket is ready
|
||||
const waitForWS = setInterval(() => {
|
||||
if (typeof realtimeManager !== 'undefined' && wsConnectionReady) {
|
||||
clearInterval(waitForWS);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function viewAccount(id) {
|
||||
|
||||
@@ -28,6 +28,40 @@
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.0/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.datatables.net/v/bs5/jq-3.7.0/dt-2.3.7/b-3.2.6/fh-4.0.6/sc-2.4.3/datatables.min.js" integrity="sha384-BPUXtS4tH3onFfu5m+dPbFfpLOXQwSWGwrsNWxOAAwqqJx6tJHhFkGF6uitrmEui" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
// Global logout function (available on all pages)
|
||||
function deleteCookie(name) {
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Strict`;
|
||||
}
|
||||
|
||||
function logout() {
|
||||
deleteCookie('dashboardToken');
|
||||
deleteCookie('gmLevel');
|
||||
localStorage.removeItem('dashboardToken');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
|
||||
// Setup logout button
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const logoutBtn = document.getElementById('logoutBtn');
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
logout();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Load dashboard.js only on dashboard pages (not on login) -->
|
||||
<script>
|
||||
const isLoginPage = document.querySelector('.login-container') !== null;
|
||||
if (!isLoginPage) {
|
||||
const script = document.createElement('script');
|
||||
script.src = '/js/dashboard.js';
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
</script>
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="bug-reports-container">
|
||||
<div class="table-card">
|
||||
<div class="table-header">
|
||||
<h2 class="mb-0">Bug Reports</h2>
|
||||
<p class="text-muted">View and manage bug reports from players</p>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Bug Reports <span class="bug_report-count">0</span></h2>
|
||||
<p class="text-muted">View and manage bug reports from players</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="bugReportsTable" class="table table-dark table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -27,16 +28,18 @@
|
||||
<!-- Data populated by DataTables -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/realtime.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable with server-side processing
|
||||
$('#bugReportsTable').DataTable({
|
||||
const table = $('#bugReportsTable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
pageLength: 25,
|
||||
@@ -80,6 +83,25 @@
|
||||
order: [[0, 'desc']],
|
||||
stateSave: false
|
||||
});
|
||||
|
||||
// Register table for real-time updates
|
||||
realtimeManager.RegisterTable('bug_report', table);
|
||||
|
||||
// Update bug report count on table draw
|
||||
table.on('draw.dt', function() {
|
||||
const info = table.page.info();
|
||||
const countEl = document.querySelector('.bug_report-count');
|
||||
if (countEl && info) {
|
||||
countEl.textContent = info.recordsTotal;
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize real-time listener when WebSocket is ready
|
||||
const waitForWS = setInterval(() => {
|
||||
if (typeof realtimeManager !== 'undefined' && wsConnectionReady) {
|
||||
clearInterval(waitForWS);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function viewReport(id) {
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="characters-container">
|
||||
<div class="table-card">
|
||||
<div class="table-header">
|
||||
<h2 class="mb-0">Characters</h2>
|
||||
<p class="text-muted">View and manage player characters</p>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Characters</h2>
|
||||
<p class="text-muted">View and manage player characters - <span class="character-count">0</span> total</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="charactersTable" class="table table-dark table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -26,16 +27,18 @@
|
||||
<!-- Data populated by DataTables -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/realtime.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable with server-side processing
|
||||
$('#charactersTable').DataTable({
|
||||
const table = $('#charactersTable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
pageLength: 25,
|
||||
@@ -75,6 +78,25 @@
|
||||
order: [[0, 'asc']],
|
||||
stateSave: false
|
||||
});
|
||||
|
||||
// Register table for real-time updates
|
||||
realtimeManager.RegisterTable('character', table);
|
||||
|
||||
// Update character count when DataTable loads
|
||||
table.on('draw.dt', function() {
|
||||
const info = table.page.info();
|
||||
const countEl = document.querySelector('.character-count');
|
||||
if (countEl && info) {
|
||||
countEl.textContent = info.recordsTotal;
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize WebSocket realtime updates
|
||||
const waitForWS = setInterval(() => {
|
||||
if (typeof realtimeManager !== 'undefined' && wsConnectionReady) {
|
||||
clearInterval(waitForWS);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function viewCharacter(id) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{# Navigation #}
|
||||
<nav class="navbar navbar-dark bg-dark flex-column" style="width: 280px; height: 100vh; position: fixed; left: 0; top: 0; overflow-y: auto;">
|
||||
<nav class="navbar navbar-dark bg-dark flex-column">
|
||||
<div class="p-3">
|
||||
<a class="navbar-brand fw-bold" href="/">🎮 DarkflameServer</a>
|
||||
</div>
|
||||
|
||||
@@ -3,33 +3,33 @@
|
||||
{% block title %}Dashboard - DarkflameServer{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Main Content -->
|
||||
<main style="margin-left: 280px;">
|
||||
<div class="container-fluid p-3 p-md-4">
|
||||
|
||||
<div class="row g-3">
|
||||
{% include "server_status.jinja2" %}
|
||||
{% include "statistics.jinja2" %}
|
||||
</div>
|
||||
|
||||
{% include "world_instances.jinja2" %}
|
||||
<div class="container-fluid py-5 px-4">
|
||||
<div class="dashboard-header mb-4">
|
||||
<div>
|
||||
<h1>Welcome to DarkflameServer Dashboard</h1>
|
||||
<p class="text-muted">Real-time server monitoring and administration</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
{% include "server_status.jinja2" %}
|
||||
{% include "statistics.jinja2" %}
|
||||
</div>
|
||||
|
||||
{% include "world_instances.jinja2" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/dashboard.js"></script>
|
||||
<script>
|
||||
// Check authentication and initialize dashboard
|
||||
// Initialize dashboard when dashboard.js is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// checkAuthentication is now async and calls connectWebSocket when ready
|
||||
checkAuthentication();
|
||||
|
||||
// Setup logout button
|
||||
document.getElementById('logoutBtn').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
logout();
|
||||
});
|
||||
// Wait a bit for dashboard.js to load
|
||||
setTimeout(() => {
|
||||
if (typeof checkAuthentication === 'function') {
|
||||
checkAuthentication();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -2,50 +2,62 @@
|
||||
|
||||
{% block title %}Dashboard Login - DarkflameServer{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="/css/login.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="min-vh-100 d-flex align-items-center justify-content-center">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-5">
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<h1 class="text-center mb-4">🎮 DarkflameServer</h1>
|
||||
|
||||
<div id="alert" class="alert" role="alert" style="display: none;"></div>
|
||||
|
||||
<form id="loginForm">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required autofocus>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required maxlength="40">
|
||||
</div>
|
||||
|
||||
<div class="mb-3 form-check">
|
||||
<input type="checkbox" class="form-check-input" id="rememberMe" name="rememberMe">
|
||||
<label class="form-check-label" for="rememberMe">
|
||||
Remember me for 30 days
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100" id="loginBtn">
|
||||
<span id="loading" class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true" style="display: none;"></span>
|
||||
<span>Login</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="login-container">
|
||||
<div class="login-wrapper">
|
||||
<div class="login-left">
|
||||
<div class="login-branding">
|
||||
<div class="logo">⚙️</div>
|
||||
<h1>DarkflameServer</h1>
|
||||
<p>Administration Dashboard</p>
|
||||
</div>
|
||||
<div class="login-info">
|
||||
<h3>Welcome Back</h3>
|
||||
<p>Manage your DarkflameServer infrastructure with ease. Secure access to server administration tools.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="login-right">
|
||||
<div class="login-form-wrapper">
|
||||
<h2>Sign In</h2>
|
||||
|
||||
<div id="alert" class="alert-box" role="alert" style="display: none;"></div>
|
||||
|
||||
<form id="loginForm" class="login-form">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" required autofocus placeholder="Enter your username">
|
||||
<div class="form-focus"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required maxlength="40" placeholder="Enter your password">
|
||||
<div class="form-focus"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-checkbox">
|
||||
<input type="checkbox" id="rememberMe" name="rememberMe">
|
||||
<label for="rememberMe">Remember me for 30 days</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-login" id="loginBtn">
|
||||
<span id="loading" class="spinner" style="display: none;"></span>
|
||||
<span class="btn-text">Sign In</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="login-footer">
|
||||
<p>Contact your administrator if you don't have access</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="play-keys-container">
|
||||
<div class="table-card">
|
||||
<div class="table-header">
|
||||
<h2 class="mb-0">Play Keys</h2>
|
||||
<p class="text-muted">View and manage play keys</p>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Play Keys <span class="play_key-count">0</span></h2>
|
||||
<p class="text-muted">View and manage play keys</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="playKeysTable" class="table table-dark table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -27,16 +28,18 @@
|
||||
<!-- Data populated by DataTables -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/realtime.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable with server-side processing
|
||||
$('#playKeysTable').DataTable({
|
||||
const table = $('#playKeysTable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
pageLength: 25,
|
||||
@@ -80,6 +83,25 @@
|
||||
order: [[0, 'asc']],
|
||||
stateSave: false
|
||||
});
|
||||
|
||||
// Register table for real-time updates
|
||||
realtimeManager.RegisterTable('play_key', table);
|
||||
|
||||
// Update play key count on table draw
|
||||
table.on('draw.dt', function() {
|
||||
const info = table.page.info();
|
||||
const countEl = document.querySelector('.play_key-count');
|
||||
if (countEl && info) {
|
||||
countEl.textContent = info.recordsTotal;
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize real-time listener when WebSocket is ready
|
||||
const waitForWS = setInterval(() => {
|
||||
if (typeof realtimeManager !== 'undefined' && wsConnectionReady) {
|
||||
clearInterval(waitForWS);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function viewKey(id) {
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="properties-container">
|
||||
<div class="table-card">
|
||||
<div class="table-header">
|
||||
<h2 class="mb-0">Properties</h2>
|
||||
<p class="text-muted">View and manage player properties</p>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>Properties <span class="property-count">0</span></h2>
|
||||
<p class="text-muted">View and manage player properties</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="propertiesTable" class="table table-dark table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -28,16 +29,18 @@
|
||||
<!-- Data populated by DataTables -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/js/realtime.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable with server-side processing
|
||||
$('#propertiesTable').DataTable({
|
||||
const table = $('#propertiesTable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
pageLength: 25,
|
||||
@@ -77,6 +80,25 @@
|
||||
order: [[0, 'asc']],
|
||||
stateSave: false
|
||||
});
|
||||
|
||||
// Register table for real-time updates
|
||||
realtimeManager.RegisterTable('property', table);
|
||||
|
||||
// Update property count on table draw
|
||||
table.on('draw.dt', function() {
|
||||
const info = table.page.info();
|
||||
const countEl = document.querySelector('.property-count');
|
||||
if (countEl && info) {
|
||||
countEl.textContent = info.recordsTotal;
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize real-time listener when WebSocket is ready
|
||||
const waitForWS = setInterval(() => {
|
||||
if (typeof realtimeManager !== 'undefined' && wsConnectionReady) {
|
||||
clearInterval(waitForWS);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function viewProperty(id) {
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-light">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Server Status</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span>Auth Server</span>
|
||||
{% if auth.online %}
|
||||
<span class="badge bg-success" id="auth-status">Online</span>
|
||||
<span class="badge badge-active" id="auth-status">Online</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger" id="auth-status">Offline</span>
|
||||
<span class="badge badge-banned" id="auth-status">Offline</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span>Chat Server</span>
|
||||
{% if chat.online %}
|
||||
<span class="badge bg-success" id="chat-status">Online</span>
|
||||
<span class="badge badge-active" id="chat-status">Online</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger" id="chat-status">Offline</span>
|
||||
<span class="badge badge-banned" id="chat-status">Offline</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>Active Worlds</span>
|
||||
<span class="badge bg-primary" id="world-count">{{ length(worlds) }}</span>
|
||||
<span class="badge badge-primary" id="world-count">{{ length(worlds) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-light">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Statistics</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span>Online Players</span>
|
||||
<span class="badge bg-info" id="online-players">{{ stats.onlinePlayers }}</span>
|
||||
<span class="badge badge-primary" id="online-players">{{ stats.onlinePlayers }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span>Total Accounts</span>
|
||||
<span class="badge bg-info" id="total-accounts">{{ stats.totalAccounts }}</span>
|
||||
<span class="badge badge-primary" id="total-accounts">{{ stats.totalAccounts }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>Total Characters</span>
|
||||
<span class="badge bg-info" id="total-characters">{{ stats.totalCharacters }}</span>
|
||||
<span class="badge badge-primary" id="total-characters">{{ stats.totalCharacters }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="card border-0 shadow-sm mt-4">
|
||||
<div class="card-header bg-light">
|
||||
<h5 class="mb-0">Active World Instances</h5>
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h2>Active World Instances</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="world-list">
|
||||
@@ -8,8 +8,8 @@
|
||||
<p class="text-muted text-center mb-0">No active world instances</p>
|
||||
{% else %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm mb-0">
|
||||
<thead class="table-light">
|
||||
<table class="table table-dark table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Zone</th>
|
||||
<th>Instance</th>
|
||||
@@ -24,8 +24,8 @@
|
||||
<td>{{ world.mapID }}</td>
|
||||
<td>{{ world.instanceID }}</td>
|
||||
<td>{{ world.cloneID }}</td>
|
||||
<td><span class="badge bg-secondary">{{ world.players }}</span></td>
|
||||
<td>{% if world.isPrivate %}<span class="badge bg-warning">Private</span>{% else %}<span class="badge bg-primary">Public</span>{% endif %}</td>
|
||||
<td><span class="badge badge-primary">{{ world.players }}</span></td>
|
||||
<td>{% if world.isPrivate %}<span class="badge badge-warning">Private</span>{% else %}<span class="badge badge-success">Public</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user