mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-05-14 03:15:05 +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:
151
dDashboardServer/templates/bugreports/index.html
Normal file
151
dDashboardServer/templates/bugreports/index.html
Normal file
@@ -0,0 +1,151 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="mb-4"><i class="bi bi-bug"></i> Bug Reports</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4">
|
||||
<div class="list-group" id="report-filter">
|
||||
<button class="list-group-item list-group-item-action active" data-status="all">All</button>
|
||||
<button class="list-group-item list-group-item-action" data-status="unresolved">Unresolved</button>
|
||||
<button class="list-group-item list-group-item-action" data-status="resolved">Resolved</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">Reports</div>
|
||||
<div class="card-body">
|
||||
<table id="bugreports-table" class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Character</th>
|
||||
<th>Submitted</th>
|
||||
<th>Resolved</th>
|
||||
<th>Summary</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal for resolving -->
|
||||
<div class="modal" tabindex="-1" id="resolveModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Resolve Bug Report</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Resolution Message</label>
|
||||
<textarea id="resolution-text" class="form-control" rows="4"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="resolve-confirm">Resolve</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentStatus = 'all';
|
||||
let currentResolveId = 0;
|
||||
|
||||
function loadTable() {
|
||||
API.get('/api/bugreports', { status: currentStatus }).then(res => {
|
||||
const data = Array.isArray(res.data) ? res.data : (res || []);
|
||||
|
||||
if ($.fn.DataTable.isDataTable('#bugreports-table')) {
|
||||
const table = $('#bugreports-table').DataTable();
|
||||
table.clear();
|
||||
table.rows.add(data);
|
||||
table.draw(false);
|
||||
} else {
|
||||
$('#bugreports-table').DataTable({
|
||||
data: data,
|
||||
destroy: true,
|
||||
columns: [
|
||||
{ data: 'id' },
|
||||
{ data: 'character_name' },
|
||||
{ data: 'submitted', render: d => d ? new Date(d * 1000).toLocaleString() : '-' },
|
||||
{ data: 'resolved_time', render: d => d && d>0 ? new Date(d * 1000).toLocaleString() : '-' },
|
||||
{ data: 'body', render: d => d ? d.substring(0,120) : '-' },
|
||||
{ data: null, orderable: false, render: function(data, type, row) {
|
||||
let actions = '';
|
||||
if (!row.resolved_time || row.resolved_time == 0) {
|
||||
actions += `<button class="btn btn-sm btn-success" onclick="openResolve(${row.id})">Resolve</button>`;
|
||||
}
|
||||
actions += ` <button class="btn btn-sm btn-info" onclick="viewReport(${row.id})">View</button>`;
|
||||
return actions;
|
||||
} }
|
||||
],
|
||||
order: [[0, 'desc']],
|
||||
pageLength: 25
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
alert(err && err.message ? err.message : 'Failed to load bug reports');
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize when libraries are ready
|
||||
safeInit(function($) {
|
||||
loadTable();
|
||||
|
||||
// Filter clicks
|
||||
$('#report-filter button').on('click', function() {
|
||||
$('#report-filter button').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
currentStatus = $(this).data('status');
|
||||
loadTable();
|
||||
});
|
||||
|
||||
// Resolve confirm
|
||||
$('#resolve-confirm').on('click', async function() {
|
||||
const resolution = $('#resolution-text').val().trim();
|
||||
if (!resolution) { alert('Resolution message required'); return; }
|
||||
try {
|
||||
const res = await API.post(`/api/bugreports/${currentResolveId}/resolve`, { resolution: resolution });
|
||||
if (res && res.success) {
|
||||
$('#resolveModal').modal('hide');
|
||||
loadTable();
|
||||
alert('Bug report resolved');
|
||||
} else {
|
||||
alert(res.error || 'Failed to resolve');
|
||||
}
|
||||
} catch (err) {
|
||||
alert(err.message);
|
||||
}
|
||||
});
|
||||
}, { requireApi: true, timeout: 8000 });
|
||||
|
||||
function openResolve(id) {
|
||||
currentResolveId = id;
|
||||
$('#resolution-text').val('');
|
||||
var modal = new bootstrap.Modal(document.getElementById('resolveModal'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
async function viewReport(id) {
|
||||
try {
|
||||
const res = await API.get(`/api/bugreports/${id}`);
|
||||
if (res && res.success) {
|
||||
const text = `ID: ${res.id}\nCharacter: ${res.character_name}\nSubmitted: ${res.submitted?new Date(res.submitted*1000).toLocaleString():''}\n\n${res.body}`;
|
||||
alert(text);
|
||||
} else {
|
||||
alert(res.error || 'Failed to get report');
|
||||
}
|
||||
} catch (err) {
|
||||
alert(err.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user