Added options page

This commit is contained in:
2025-10-23 00:54:43 +01:00
parent 0a5637f12a
commit 26b9785ba3
8 changed files with 576 additions and 0 deletions

183
src/js/options.js Normal file
View File

@@ -0,0 +1,183 @@
document.addEventListener('page-loaded', e => {
if (e.detail.page !== 'options') return;
// ---- STATUS WIDGET ----
const wifi = document.getElementById('statusWifi');
const uptime = document.getElementById('statusUptime');
const load = document.getElementById('statusLoad');
const mem = document.getElementById('statusMem');
const services = document.getElementById('statusServices');
const btnRefresh = document.getElementById('btnRefreshStatus');
async function updateStatus() {
try {
const res = await fetch('includes/api/system.php', {
method: 'POST',
body: new URLSearchParams({ action: 'system-info' })
});
const j = await res.json();
if (j.error) throw new Error(j.error);
wifi.textContent = j.wifi || '';
uptime.textContent = j.uptime || '';
load.textContent = j.load || '';
mem.textContent = j.memory || '';
const svcList = CONFIG.options_status_services;
const results = [];
for (const svc of svcList) {
const r = await fetch('includes/api/system.php', {
method: 'POST',
body: new URLSearchParams({ action: 'service-status', service: svc })
});
const text = await r.text();
results.push(`${svc}: ${text.includes('running') ? '🟢' : '🔴'}`);
}
services.textContent = results.join(' ');
} catch (err) {
wifi.textContent = uptime.textContent = load.textContent = mem.textContent = 'Error';
services.textContent = err.message;
}
}
btnRefresh?.addEventListener('click', updateStatus);
updateStatus();
setInterval(updateStatus, CONFIG.options_status_interval);
// ---- CONFIG EDITOR ----
const editor = document.getElementById('configEditor');
const msg = document.getElementById('configMessage');
const btnLoadConfig = document.getElementById('btnLoadConfig');
const btnSaveConfig = document.getElementById('btnSaveConfig');
if (!btnSaveConfig.dataset.bound) {
btnSaveConfig.dataset.bound = 'true';
btnLoadConfig?.addEventListener('click', async () => {
msg.textContent = 'Loading...';
try {
const res = await fetch('includes/api/config.php', {
method: 'POST',
body: new URLSearchParams({ action: 'load' })
});
const j = await res.json();
if (j.error) msg.textContent = j.error;
else {
editor.value = j.content || '';
msg.textContent = 'Config loaded.';
}
} catch (err) {
msg.textContent = 'Error loading config: ' + err.message;
}
});
btnSaveConfig?.addEventListener('click', async () => {
msg.textContent = 'Checking changes...';
try {
const data = editor.value;
// Preview changes & syntax check
const previewRes = await fetch('includes/api/config.php', {
method: 'POST',
body: new URLSearchParams({ action: 'preview-save', data })
});
const preview = await previewRes.json();
if (preview.error) {
msg.textContent = preview.error;
return;
}
if (preview.message) {
msg.textContent = preview.message;
return;
}
const confirmMsg = `⚙️ Changes detected (${preview.diff.split('\n\n').length} lines):\n\n` +
preview.diff.slice(0, 1000) +
(preview.diff.length > 1000 ? '\n\n...preview truncated...' : '') +
`\n\nSave these changes?`;
if (!confirm(confirmMsg)) {
msg.textContent = 'Save canceled.';
return;
}
msg.textContent = 'Saving...';
const resSave = await fetch('includes/api/config.php', {
method: 'POST',
body: new URLSearchParams({ action: 'save', data })
});
const jSave = await resSave.json();
msg.textContent = jSave.message || jSave.error || 'Saved successfully.';
if (jSave.message && jSave.message.includes('successfully')) {
editor.value = '';
msg.textContent = '';
}
} catch (err) {
msg.textContent = 'Error: ' + err.message;
}
});
}
// ---- CACHE ----
const cacheBtn = document.getElementById('btnClearCache');
cacheBtn?.addEventListener('click', async () => {
if (!confirm('Clear cache folder?')) return;
const res = await fetch('includes/api/cache.php', { method: 'POST' });
const j = await res.json();
alert(j.message || j.error);
});
// ---- LOGS ----
const logsBtn = document.getElementById('btnViewLogs');
const logsBox = document.getElementById('logsBox');
logsBtn?.addEventListener('click', async () => {
const res = await fetch('includes/api/logs.php');
const j = await res.json();
logsBox.textContent = j.content || j.error;
});
// ---- WIFI / LAN ----
const wifiBtn = document.getElementById('btnWifiToggle');
const lanBtn = document.getElementById('btnLanRestart');
wifiBtn?.addEventListener('click', async () => {
await fetch('includes/api/system.php', {
method: 'POST',
body: new URLSearchParams({ action: 'wifi-toggle' })
});
updateStatus();
});
lanBtn?.addEventListener('click', async () => {
await fetch('includes/api/system.php', {
method: 'POST',
body: new URLSearchParams({ action: 'service-restart', service: 'network' })
});
updateStatus();
});
// ---- PASSWORD CHANGE ----
const oldPass = document.getElementById('oldPass');
const newPass = document.getElementById('newPass');
const confirmPass = document.getElementById('confirmPass');
const passBtn = document.getElementById('btnChangePass');
passBtn?.addEventListener('click', async () => {
if (newPass.value !== confirmPass.value) {
alert('New passwords do not match');
return;
}
const res = await fetch('includes/api/admin.php', {
method: 'POST',
body: new URLSearchParams({
action: 'change_pass',
oldPass: oldPass.value,
newPass: newPass.value
})
});
const j = await res.json();
alert(j.message || j.error);
});
});