feat: full de-Angularization with Bootstrap 5 migration
- Removed AngularJS 1.4.8 completely — no more framework dependency - Extracted core RCON logic into pure vanilla JS (js/rcon.js) - Added lightweight hash-based SPA router (js/router.js) - Rewrote all 6 pages as vanilla JS modules in js/pages/ - Migrated Bootstrap 3 → Bootstrap 5 (cards instead of panels, bootstrap-icons instead of glyphicons) - Removed jQuery dependency (Bootstrap 5 is vanilla JS) - Purged all Angular templates from html/ - Removed npm artifacts (package.json, node_modules) - Added nginx.example.conf for static hosting - Updated rcon.css dark theme for BS5 variables - Static file only — no Node.js backend required Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Connection page — connect form with localStorage persistence.
|
||||
*/
|
||||
function ConnectPage(params, container) {
|
||||
var html =
|
||||
'<div class="row">' +
|
||||
'<div class="offset-md-4 col-md-6" style="margin-top: 128px">' +
|
||||
'<div class="card p-4 mb-4">' +
|
||||
'<h2>Connect</h2>' +
|
||||
'<div class="alert alert-danger" id="connect-error" style="display:none"></div>' +
|
||||
'<p>Enter the address (including rcon port) and the rcon password below to connect.</p>' +
|
||||
'<form id="connect-form">' +
|
||||
'<div class="mb-3">' +
|
||||
'<label for="connection-address" class="form-label">Address</label>' +
|
||||
'<input required minlength="5" id="connection-address" class="form-control" placeholder="xxx.xxx.xxx.xxx:28016">' +
|
||||
'</div>' +
|
||||
'<div class="mb-3">' +
|
||||
'<label for="connection-password" class="form-label">Password</label>' +
|
||||
'<input required minlength="2" type="password" id="connection-password" class="form-control">' +
|
||||
'</div>' +
|
||||
'<div class="form-check float-end">' +
|
||||
'<input type="checkbox" class="form-check-input" id="connection-save" checked>' +
|
||||
'<label class="form-check-label" for="connection-save">Save Connection</label>' +
|
||||
'</div>' +
|
||||
'<button type="submit" class="btn btn-primary w-100">Connect</button>' +
|
||||
'</form>' +
|
||||
'</div>' +
|
||||
'<div class="card p-4">' +
|
||||
'<div id="saved-connections"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
container.innerHTML = html;
|
||||
|
||||
var addrInput = document.getElementById('connection-address');
|
||||
var passInput = document.getElementById('connection-password');
|
||||
var saveCheck = document.getElementById('connection-save');
|
||||
var errorDiv = document.getElementById('connect-error');
|
||||
var savedDiv = document.getElementById('saved-connections');
|
||||
var connectionsLimit = 5;
|
||||
|
||||
function loadConnections() {
|
||||
try { return JSON.parse(localStorage.previousConnections || '[]'); }
|
||||
catch (e) { return []; }
|
||||
}
|
||||
|
||||
function saveConnections(conns) {
|
||||
localStorage.previousConnections = JSON.stringify(conns);
|
||||
}
|
||||
|
||||
function showError(msg) {
|
||||
errorDiv.textContent = msg;
|
||||
errorDiv.style.display = 'block';
|
||||
}
|
||||
|
||||
function hideError() { errorDiv.style.display = 'none'; }
|
||||
|
||||
function addConnection(addr, pass) {
|
||||
var conns = loadConnections();
|
||||
conns = conns.filter(function (c) { return c.Address !== addr; });
|
||||
conns.push({ Address: addr, Password: pass, date: new Date().toISOString() });
|
||||
saveConnections(conns);
|
||||
}
|
||||
|
||||
function doConnect(addr, pass) {
|
||||
hideError();
|
||||
Rcon.connect(addr, pass);
|
||||
}
|
||||
|
||||
function renderSaved() {
|
||||
var conns = loadConnections();
|
||||
if (conns.length === 0) { savedDiv.innerHTML = ''; return; }
|
||||
var display = conns.slice().reverse();
|
||||
var shown = connectionsLimit || display.length;
|
||||
var h = '<h2>Saved Connections</h2><ul>';
|
||||
for (var i = 0; i < Math.min(shown, display.length); i++) {
|
||||
var c = display[i];
|
||||
h += '<li><a href="#" class="saved-conn" data-addr="' + c.Address + '" data-pass="' + c.Password + '">' + c.Address + '</a> — ' + new Date(c.date).toLocaleString() + '</li>';
|
||||
}
|
||||
h += '</ul>';
|
||||
if (conns.length > 5) {
|
||||
h += '<button type="button" class="btn btn-primary btn-block" id="toggle-conn-limit">Show ' + (connectionsLimit ? 'more' : 'less') + '</button>';
|
||||
}
|
||||
savedDiv.innerHTML = h;
|
||||
|
||||
var links = savedDiv.querySelectorAll('.saved-conn');
|
||||
for (var j = 0; j < links.length; j++) {
|
||||
links[j].addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
doConnect(this.dataset.addr, this.dataset.pass);
|
||||
});
|
||||
}
|
||||
var toggle = document.getElementById('toggle-conn-limit');
|
||||
if (toggle) {
|
||||
toggle.addEventListener('click', function () {
|
||||
connectionsLimit = connectionsLimit ? undefined : 5;
|
||||
renderSaved();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('connect-form').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var addr = addrInput.value.trim();
|
||||
var pass = passInput.value.trim();
|
||||
if (!addr || !pass) return;
|
||||
if (saveCheck.checked) addConnection(addr, pass);
|
||||
doConnect(addr, pass);
|
||||
});
|
||||
|
||||
function onConnected() {
|
||||
window.location.hash = '#/' + Rcon.getAddress() + '/info';
|
||||
}
|
||||
function onDisconnected(ev) {
|
||||
showError('Connection was closed — Error ' + (ev ? ev.code : 'unknown'));
|
||||
}
|
||||
|
||||
Rcon.on('connected', onConnected);
|
||||
Rcon.on('disconnected', onDisconnected);
|
||||
renderSaved();
|
||||
|
||||
// Auto-connect from URL — check hash for address and password
|
||||
var hash = window.location.hash;
|
||||
var pwMatch = hash.match(/[?&]password=([^&]+)/);
|
||||
if (pwMatch) {
|
||||
passInput.value = decodeURIComponent(pwMatch[1]);
|
||||
window.location.hash = hash.replace(/[?&]password=[^&]+/, '');
|
||||
}
|
||||
var addrMatch = hash.match(/^#\/([^/]+)\//);
|
||||
if (addrMatch) addrInput.value = addrMatch[1];
|
||||
|
||||
if (addrInput.value && passInput.value) {
|
||||
if (saveCheck.checked) addConnection(addrInput.value.trim(), passInput.value.trim());
|
||||
doConnect(addrInput.value.trim(), passInput.value.trim());
|
||||
}
|
||||
|
||||
return function cleanup() {
|
||||
Rcon.off('connected', onConnected);
|
||||
Rcon.off('disconnected', onDisconnected);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user