Added options page
This commit is contained in:
183
src/js/options.js
Normal file
183
src/js/options.js
Normal 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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user