75 lines
3.5 KiB
JavaScript
75 lines
3.5 KiB
JavaScript
// SvxPortal — web front-end for SvxReflector
|
|
// Copyright (C) 2026 SA7AUX (Björn)
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it under
|
|
// the terms of the GNU Affero General Public License as published by the Free
|
|
// Software Foundation, either version 3 of the License, or (at your option) any
|
|
// later version. See the LICENSE file for details.
|
|
|
|
'use strict';
|
|
// Global Bans — callsign-only, styled like the DMR site's bans page.
|
|
var $ = function(id) { return document.getElementById(id); };
|
|
var bansCanWrite = false;
|
|
function bansEsc(s) { var d=document.createElement('div'); d.textContent=s==null?'':s; return d.innerHTML; }
|
|
function bansSetMsg(txt, err) {
|
|
var el = $('banMsg'); if (!el) return;
|
|
if (!txt) { el.style.display='none'; return; }
|
|
el.style.display='block'; el.textContent=txt; el.style.color=err?'#ff8080':'#00ff80';
|
|
}
|
|
async function bapi(body) {
|
|
var r = await fetch('/auth/admin_bans_api.php', { method:'POST', credentials:'same-origin', headers:{'Content-Type':'application/json','X-CSRF-Token':window._csrfToken||''}, body:JSON.stringify(body) });
|
|
return r.json().catch(function(){ return null; });
|
|
}
|
|
|
|
function bansRenderList(items) {
|
|
var ul = $('banCsList'); if (!ul) return;
|
|
ul.innerHTML = '';
|
|
if (!items || items.length === 0) { ul.innerHTML = '<li class="text-secondary">— none —</li>'; return; }
|
|
items.forEach(function(v) {
|
|
var li = document.createElement('li');
|
|
li.className = 'd-flex justify-content-between align-items-center mb-1';
|
|
li.innerHTML = '<span>' + bansEsc(v) + '</span>'
|
|
+ (bansCanWrite
|
|
? '<button class="btn btn-outline-secondary btn-sm" data-ban-rm-val="' + bansEsc(v) + '" style="font-size:10px;padding:1px 6px;">unban</button>'
|
|
: '');
|
|
ul.appendChild(li);
|
|
});
|
|
}
|
|
|
|
async function bansLoad() {
|
|
var j = await bapi({action:'list'});
|
|
if (!j || !j.ok) return;
|
|
bansCanWrite = !!j.can_write;
|
|
var ro = $('banReadonlyBadge'); if (ro) ro.style.display = bansCanWrite ? 'none' : '';
|
|
document.querySelectorAll('.ban-add-row').forEach(function(el){ el.style.display = bansCanWrite ? 'flex' : 'none'; });
|
|
bansRenderList(j.callsigns || []);
|
|
}
|
|
|
|
async function bansAdd() {
|
|
var v = ($('banCsAdd').value || '').trim();
|
|
if (!v) return;
|
|
var res = await bapi({action:'add', kind:'callsign', value:v});
|
|
if (res && res.ok) { $('banCsAdd').value=''; bansSetMsg('Banned callsign: ' + v.toUpperCase(), false); await bansLoad(); }
|
|
else bansSetMsg((res && res.error) || 'Failed', true);
|
|
}
|
|
|
|
async function bansRemove(v) {
|
|
if (!confirm('Unban callsign ' + v + '?')) return;
|
|
var res = await bapi({action:'remove', kind:'callsign', value:v});
|
|
if (res && res.ok) { bansSetMsg('Removed.', false); await bansLoad(); }
|
|
else bansSetMsg((res && res.error) || 'Failed', true);
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
fetch('/auth/me.php',{credentials:'same-origin'}).then(function(r){return r.json();}).then(function(j){if(j&&j.csrf_token)window._csrfToken=j.csrf_token;}).catch(function(){});
|
|
$('btnBansRefresh').addEventListener('click', bansLoad);
|
|
document.querySelectorAll('button[data-ban-add]').forEach(function(b){ b.addEventListener('click', bansAdd); });
|
|
$('banCsAdd').addEventListener('keydown', function(e){ if (e.key==='Enter') bansAdd(); });
|
|
$('banCsList').addEventListener('click', function(e){
|
|
var btn = e.target.closest('button[data-ban-rm-val]');
|
|
if (btn) bansRemove(btn.getAttribute('data-ban-rm-val'));
|
|
});
|
|
bansLoad();
|
|
});
|