sdsad
This commit is contained in:
@@ -198,6 +198,47 @@
|
|||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pihole-console-modal {
|
||||||
|
width: min(720px, 96vw);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pihole-console-body {
|
||||||
|
margin-top: 16px;
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
max-height: 48vh;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pihole-console-line {
|
||||||
|
display: grid;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
background: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pihole-console-line span {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pihole-console-line strong {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pihole-console-line.is-success {
|
||||||
|
border-color: rgba(0, 179, 164, 0.22);
|
||||||
|
background: rgba(0, 179, 164, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pihole-console-line.is-error {
|
||||||
|
border-color: rgba(255, 90, 61, 0.24);
|
||||||
|
background: rgba(255, 90, 61, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
.pihole-instance-card {
|
.pihole-instance-card {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: var(--panel-2);
|
background: var(--panel-2);
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
let refreshTimer = null;
|
let refreshTimer = null;
|
||||||
let loadInFlight = false;
|
let loadInFlight = false;
|
||||||
let actionInFlight = false;
|
let actionInFlight = false;
|
||||||
|
let actionConsoleApi = null;
|
||||||
|
let actionConsoleBody = null;
|
||||||
|
let actionConsoleClose = null;
|
||||||
|
|
||||||
const apiCall = async (action, payload = {}) => {
|
const apiCall = async (action, payload = {}) => {
|
||||||
const res = await fetch(`/module/pihole/api?action=${encodeURIComponent(action)}`,
|
const res = await fetch(`/module/pihole/api?action=${encodeURIComponent(action)}`,
|
||||||
@@ -47,9 +50,82 @@
|
|||||||
el.textContent = value;
|
el.textContent = value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ensureActionConsole = () => {
|
||||||
|
if (actionConsoleApi && actionConsoleBody && actionConsoleClose) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = document.createElement('div');
|
||||||
|
root.className = 'modal';
|
||||||
|
root.dataset.piholeConsoleModal = '1';
|
||||||
|
root.setAttribute('aria-hidden', 'true');
|
||||||
|
root.innerHTML = `
|
||||||
|
<div class="modal-card pihole-console-modal" role="dialog" aria-modal="true" aria-labelledby="pihole-console-title">
|
||||||
|
<div class="modal-header">
|
||||||
|
<div>
|
||||||
|
<strong id="pihole-console-title">Pi-hole Aktion</strong>
|
||||||
|
<div class="muted">Status und Rueckmeldungen zur laufenden Aktion.</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-actions">
|
||||||
|
<button class="module-button module-button--secondary module-button--small" type="button" data-pihole-console-clear>Leeren</button>
|
||||||
|
<button class="icon-button" type="button" data-pihole-console-close aria-label="Konsole schliessen">×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pihole-console-body" data-pihole-console-body></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(root);
|
||||||
|
|
||||||
|
actionConsoleBody = root.querySelector('[data-pihole-console-body]');
|
||||||
|
actionConsoleClose = root.querySelector('[data-pihole-console-close]');
|
||||||
|
const clearBtn = root.querySelector('[data-pihole-console-clear]');
|
||||||
|
|
||||||
|
actionConsoleApi = window.NexusModal && typeof window.NexusModal.create === 'function'
|
||||||
|
? window.NexusModal.create(root, { initialFocus: '[data-pihole-console-close]' })
|
||||||
|
: {
|
||||||
|
open() {
|
||||||
|
root.classList.add('is-open');
|
||||||
|
root.setAttribute('aria-hidden', 'false');
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
root.classList.remove('is-open');
|
||||||
|
root.setAttribute('aria-hidden', 'true');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (actionConsoleClose) {
|
||||||
|
actionConsoleClose.addEventListener('click', () => {
|
||||||
|
if (!actionInFlight) {
|
||||||
|
actionConsoleApi.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clearBtn) {
|
||||||
|
clearBtn.addEventListener('click', () => {
|
||||||
|
if (actionConsoleBody) {
|
||||||
|
actionConsoleBody.innerHTML = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const appendActionLog = (message, tone = 'info') => {
|
||||||
|
ensureActionConsole();
|
||||||
|
if (!actionConsoleBody) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const row = document.createElement('div');
|
||||||
|
row.className = `pihole-console-line is-${tone}`;
|
||||||
|
row.innerHTML = `<span>${new Date().toLocaleTimeString('de-DE')}</span><strong>${message}</strong>`;
|
||||||
|
actionConsoleBody.appendChild(row);
|
||||||
|
actionConsoleBody.scrollTop = actionConsoleBody.scrollHeight;
|
||||||
|
};
|
||||||
|
|
||||||
const setActionLock = (locked, message = 'Bitte warten ...') => {
|
const setActionLock = (locked, message = 'Bitte warten ...') => {
|
||||||
actionInFlight = locked;
|
actionInFlight = locked;
|
||||||
page.classList.toggle('is-busy', locked);
|
page.classList.toggle('is-busy', locked);
|
||||||
|
ensureActionConsole();
|
||||||
|
|
||||||
let overlay = page.querySelector('[data-pihole-busy-overlay]');
|
let overlay = page.querySelector('[data-pihole-busy-overlay]');
|
||||||
if (!overlay) {
|
if (!overlay) {
|
||||||
@@ -67,6 +143,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
overlay.hidden = !locked;
|
overlay.hidden = !locked;
|
||||||
|
if (actionConsoleClose) {
|
||||||
|
actionConsoleClose.disabled = locked;
|
||||||
|
}
|
||||||
|
|
||||||
page.querySelectorAll('button, input, select, textarea').forEach((el) => {
|
page.querySelectorAll('button, input, select, textarea').forEach((el) => {
|
||||||
const formControl = el;
|
const formControl = el;
|
||||||
@@ -229,26 +308,38 @@
|
|||||||
: action === 'gravity'
|
: action === 'gravity'
|
||||||
? 'Listen werden aktualisiert ...'
|
? 'Listen werden aktualisiert ...'
|
||||||
: 'Aktion wird ausgefuehrt ...';
|
: 'Aktion wird ausgefuehrt ...';
|
||||||
|
ensureActionConsole();
|
||||||
|
if (actionConsoleBody) {
|
||||||
|
actionConsoleBody.innerHTML = '';
|
||||||
|
}
|
||||||
|
actionConsoleApi.open();
|
||||||
|
appendActionLog(actionLabel, 'info');
|
||||||
setActionLock(true, actionLabel);
|
setActionLock(true, actionLabel);
|
||||||
|
|
||||||
if (action === 'enable') {
|
if (action === 'enable') {
|
||||||
|
appendActionLog(`Aktiviere ${instance === 'all' ? 'alle Instanzen' : `Instanz ${instance}`}.`, 'info');
|
||||||
await apiCall('enable', payload);
|
await apiCall('enable', payload);
|
||||||
} else if (action === 'disable' || action === 'disable-custom') {
|
} else if (action === 'disable' || action === 'disable-custom') {
|
||||||
if (!payload.minutes || payload.minutes <= 0) {
|
if (!payload.minutes || payload.minutes <= 0) {
|
||||||
alert('Bitte Minuten angeben.');
|
appendActionLog('Fehler: Bitte Minuten angeben.', 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
appendActionLog(`Deaktiviere ${instance === 'all' ? 'alle Instanzen' : `Instanz ${instance}`} fuer ${payload.minutes} Minuten.`, 'info');
|
||||||
await apiCall('disable', payload);
|
await apiCall('disable', payload);
|
||||||
} else if (action === 'gravity') {
|
} else if (action === 'gravity') {
|
||||||
|
appendActionLog(`Starte Listen-Update fuer ${instance === 'all' ? 'alle Instanzen' : `Instanz ${instance}`}.`, 'info');
|
||||||
await apiCall('gravity', payload);
|
await apiCall('gravity', payload);
|
||||||
const status = document.querySelector('[data-list-update-status]');
|
const status = document.querySelector('[data-list-update-status]');
|
||||||
if (status) status.textContent = 'Listen-Update gestartet.';
|
if (status) status.textContent = 'Listen-Update gestartet.';
|
||||||
} else if (action === 'update') {
|
} else if (action === 'update') {
|
||||||
|
appendActionLog(`Starte Pi-hole-Update fuer ${instance === 'all' ? 'alle Instanzen' : `Instanz ${instance}`}.`, 'info');
|
||||||
await apiCall('update', payload);
|
await apiCall('update', payload);
|
||||||
}
|
}
|
||||||
|
appendActionLog('Aktion abgeschlossen. Dashboard wird aktualisiert.', 'success');
|
||||||
await loadDashboard();
|
await loadDashboard();
|
||||||
|
appendActionLog('Anzeige erfolgreich aktualisiert.', 'success');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(`Aktion fehlgeschlagen: ${err.message}`);
|
appendActionLog(`Aktion fehlgeschlagen: ${err.message}`, 'error');
|
||||||
} finally {
|
} finally {
|
||||||
setActionLock(false);
|
setActionLock(false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user