mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-22 12:42:49 +00:00
feat: contraband list with flagging and optional removal
Staff list contraband items on a new dashboard page (item search, reason, flag or flag and remove; contraband_manage to edit, reports_view to see). World servers check every inventory when a character loads and every item a player receives: each find is an economy flag of the new kind Contraband, shown with the other flags and in the character's related data. Items marked for removal are taken away, with a character snapshot kept first so they can be given back, an audit entry and a mail or chat message telling the player why. Staff are skipped unless contraband_ignore_staff is off. Worlds reload the list when it changes (RELOAD_CONTRABAND, added at the end of ePlayerAction). Fixes #1563 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
76
dDashboardServer/static/js/contraband.js
Normal file
76
dDashboardServer/static/js/contraband.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* The Contraband page: the list of items players shouldn't have, and (with contraband_manage) adding, changing and
|
||||
* removing entries. Running worlds reload the list after every change.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var canManage = false;
|
||||
var lotInput = document.getElementById('lotInput');
|
||||
|
||||
function row(i) {
|
||||
var action = i.action === 'remove' ? fmt.badge('Flag and remove', 'danger') : fmt.badge('Flag', 'warning');
|
||||
var buttons = canManage ? '<button type="button" class="btn btn-sm btn-outline-secondary me-1" data-edit="' + esc(i.lot) + '">Edit</button>' +
|
||||
'<button type="button" class="btn btn-sm btn-outline-danger" data-remove="' + esc(i.lot) + '">Remove</button>' : '';
|
||||
return '<tr><td><strong>' + esc(i.name) + '</strong> <span class="text-body-secondary small">' + esc(i.lot) + '</span></td>' +
|
||||
'<td>' + esc(i.reason) + '</td><td>' + action + '</td><td class="small">' + esc(i.added_by) + ', ' + esc(fmt.unix(i.added_at)) + '</td>' +
|
||||
'<td class="text-end text-nowrap">' + buttons + '</td></tr>';
|
||||
}
|
||||
|
||||
var items = [];
|
||||
function load() {
|
||||
api.get('/api/contraband').then(function (d) {
|
||||
if (!d.success) return;
|
||||
items = d.items;
|
||||
canManage = d.canManage;
|
||||
document.getElementById('addCard').classList.toggle('d-none', !canManage);
|
||||
document.getElementById('rows').innerHTML = items.map(row).join('') ||
|
||||
'<tr><td colspan="5" class="text-body-secondary">Nothing is contraband.</td></tr>';
|
||||
}).catch(function () {});
|
||||
}
|
||||
|
||||
var timer = null;
|
||||
lotInput.addEventListener('input', function () {
|
||||
clearTimeout(timer);
|
||||
var q = lotInput.value.trim();
|
||||
if (q.length < 2 || /^\d+$/.test(q)) return;
|
||||
timer = setTimeout(function () {
|
||||
api.get('/api/contraband/items?q=' + encodeURIComponent(q)).then(function (found) {
|
||||
document.getElementById('lotSuggestions').innerHTML = (Array.isArray(found) ? found : []).map(function (i) {
|
||||
return '<option value="' + esc(i.lot) + '">' + esc(i.name) + '</option>';
|
||||
}).join('');
|
||||
});
|
||||
}, 250);
|
||||
});
|
||||
|
||||
function done(d) {
|
||||
if (!d.success) { toast(d.error || 'Failed', 'danger'); return; }
|
||||
toast(d.message, 'success');
|
||||
load();
|
||||
}
|
||||
|
||||
document.getElementById('addForm').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var lot = parseInt(lotInput.value, 10);
|
||||
if (!(lot > 0)) { toast('Pick an item from the list or enter its LOT', 'warning'); return; }
|
||||
api.post('/api/contraband', { lot: lot, reason: document.getElementById('reasonInput').value, action: document.getElementById('actionInput').value })
|
||||
.then(function (d) { if (d.success) { lotInput.value = ''; document.getElementById('reasonInput').value = ''; } done(d); });
|
||||
});
|
||||
|
||||
document.getElementById('rows').addEventListener('click', function (e) {
|
||||
var edit = e.target.closest('[data-edit]'), remove = e.target.closest('[data-remove]');
|
||||
if (edit) {
|
||||
var item = items.filter(function (i) { return String(i.lot) === edit.dataset.edit; })[0];
|
||||
if (!item) return;
|
||||
lotInput.value = item.lot;
|
||||
document.getElementById('reasonInput').value = item.reason;
|
||||
document.getElementById('actionInput').value = item.action;
|
||||
lotInput.focus();
|
||||
} else if (remove) {
|
||||
if (!confirm('Take this item off the contraband list?')) return;
|
||||
api.post('/api/contraband/delete', { lot: parseInt(remove.dataset.remove, 10) }).then(done);
|
||||
}
|
||||
});
|
||||
|
||||
load();
|
||||
})();
|
||||
@@ -11,7 +11,7 @@
|
||||
// Names come from the server's enums (Labels); only the colours are kept here
|
||||
var METHOD_COLOURS = { 1: 'info', 2: 'secondary', 3: 'success', 4: 'light' };
|
||||
function methodBadge(value) { return fmt.badge(Labels.name('transferMethods', value) || '?', METHOD_COLOURS[value] || 'secondary'); }
|
||||
var FLAG_KIND_COLOURS = { 1: 'warning', 2: 'info', 3: 'danger' };
|
||||
var FLAG_KIND_COLOURS = { 1: 'warning', 2: 'info', 3: 'danger', 4: 'warning', 5: 'danger' };
|
||||
var FLAG_STATUS_COLOURS = { 0: 'danger', 1: 'secondary', 2: 'success' };
|
||||
function flagKindBadge(value) { return fmt.badge(Labels.name('flagKinds', value) || '?', FLAG_KIND_COLOURS[value] || 'secondary'); }
|
||||
function flagStatusBadge(value) { return fmt.badge(Labels.name('flagStatus', value) || '?', FLAG_STATUS_COLOURS[value] || 'secondary'); }
|
||||
|
||||
@@ -1588,7 +1588,7 @@
|
||||
|
||||
// ---- Flags ----
|
||||
|
||||
var FLAG_KIND_COLOURS = { 1: 'warning', 2: 'info', 3: 'danger', 4: 'warning' };
|
||||
var FLAG_KIND_COLOURS = { 1: 'warning', 2: 'info', 3: 'danger', 4: 'warning', 5: 'danger' };
|
||||
var FLAG_STATUS_COLOURS = { 0: 'danger', 1: 'secondary', 2: 'success' };
|
||||
function flagKindBadge(value) { return fmt.badge(Labels.name('flagKinds', value) || '?', FLAG_KIND_COLOURS[value] || 'secondary'); }
|
||||
function flagStatusBadge(value) { return fmt.badge(Labels.name('flagStatus', value) || '?', FLAG_STATUS_COLOURS[value] || 'secondary'); }
|
||||
|
||||
Reference in New Issue
Block a user