asdsad
This commit is contained in:
@@ -2,6 +2,13 @@
|
|||||||
const page = document.querySelector('[data-pihole-page]');
|
const page = document.querySelector('[data-pihole-page]');
|
||||||
if (!page) return;
|
if (!page) return;
|
||||||
|
|
||||||
|
const pageType = page.dataset.piholePage || 'dashboard';
|
||||||
|
const configuredRefreshSeconds = Number(page.dataset.refreshSeconds || 0);
|
||||||
|
const defaultRefreshSeconds = pageType === 'dashboard' ? 1 : 5;
|
||||||
|
const refreshSeconds = Number.isFinite(configuredRefreshSeconds) && configuredRefreshSeconds >= 0
|
||||||
|
? configuredRefreshSeconds
|
||||||
|
: defaultRefreshSeconds;
|
||||||
|
|
||||||
const fmt = new Intl.NumberFormat('de-DE');
|
const fmt = new Intl.NumberFormat('de-DE');
|
||||||
const fmtDate = (ts) => {
|
const fmtDate = (ts) => {
|
||||||
if (!ts) return '–';
|
if (!ts) return '–';
|
||||||
@@ -11,7 +18,6 @@
|
|||||||
|
|
||||||
let refreshTimer = null;
|
let refreshTimer = null;
|
||||||
let loadInFlight = false;
|
let loadInFlight = false;
|
||||||
let loadErrorShown = false;
|
|
||||||
|
|
||||||
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)}`,
|
||||||
@@ -265,7 +271,6 @@
|
|||||||
renderList(document.querySelector('[data-top-queries]'), data.aggregate?.top_queries, 'Keine Daten');
|
renderList(document.querySelector('[data-top-queries]'), data.aggregate?.top_queries, 'Keine Daten');
|
||||||
renderList(document.querySelector('[data-top-clients]'), data.aggregate?.query_sources, 'Keine Daten');
|
renderList(document.querySelector('[data-top-clients]'), data.aggregate?.query_sources, 'Keine Daten');
|
||||||
renderBlocked(document.querySelector('[data-recent-blocked]'), data.aggregate?.recent_blocked);
|
renderBlocked(document.querySelector('[data-recent-blocked]'), data.aggregate?.recent_blocked);
|
||||||
loadErrorShown = false;
|
|
||||||
const existing = page.querySelector('[data-pihole-load-error]');
|
const existing = page.querySelector('[data-pihole-load-error]');
|
||||||
if (existing) existing.remove();
|
if (existing) existing.remove();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -278,19 +283,37 @@
|
|||||||
page.appendChild(message);
|
page.appendChild(message);
|
||||||
}
|
}
|
||||||
message.textContent = `Fehler beim Laden der Pi-hole Daten: ${err.message}`;
|
message.textContent = `Fehler beim Laden der Pi-hole Daten: ${err.message}`;
|
||||||
loadErrorShown = true;
|
|
||||||
} finally {
|
} finally {
|
||||||
loadInFlight = false;
|
loadInFlight = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const stopAutoRefresh = () => {
|
||||||
|
if (refreshTimer !== null) {
|
||||||
|
window.clearInterval(refreshTimer);
|
||||||
|
refreshTimer = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const startAutoRefresh = () => {
|
||||||
|
stopAutoRefresh();
|
||||||
|
if (refreshSeconds <= 0 || document.visibilityState !== 'visible') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refreshTimer = window.setInterval(loadDashboard, refreshSeconds * 1000);
|
||||||
|
};
|
||||||
|
|
||||||
bindActionButtons();
|
bindActionButtons();
|
||||||
bindForms();
|
bindForms();
|
||||||
loadDashboard();
|
loadDashboard();
|
||||||
refreshTimer = window.setInterval(loadDashboard, 1000);
|
startAutoRefresh();
|
||||||
window.addEventListener('beforeunload', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
if (refreshTimer !== null) {
|
if (document.visibilityState === 'visible') {
|
||||||
window.clearInterval(refreshTimer);
|
loadDashboard();
|
||||||
|
startAutoRefresh();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
stopAutoRefresh();
|
||||||
});
|
});
|
||||||
|
window.addEventListener('beforeunload', stopAutoRefresh);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -2,5 +2,29 @@
|
|||||||
"title": "Pi-hole",
|
"title": "Pi-hole",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Pi-hole Monitoring, Listen und Steuerung fuer mehrere Instanzen.",
|
"description": "Pi-hole Monitoring, Listen und Steuerung fuer mehrere Instanzen.",
|
||||||
"setup": { "fields": [] }
|
"setup": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "dashboard_refresh_sec",
|
||||||
|
"label": "Refresh Dashboard (Sekunden)",
|
||||||
|
"type": "number",
|
||||||
|
"help": "Automatische Aktualisierung fuer das Dashboard. Standard: 1 Sekunde. 0 deaktiviert den Auto-Refresh.",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lists_refresh_sec",
|
||||||
|
"label": "Refresh Listen (Sekunden)",
|
||||||
|
"type": "number",
|
||||||
|
"help": "Automatische Aktualisierung fuer die Listen-Seite. Standard: 5 Sekunden. 0 deaktiviert den Auto-Refresh.",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "queries_refresh_sec",
|
||||||
|
"label": "Refresh Queries (Sekunden)",
|
||||||
|
"type": "number",
|
||||||
|
"help": "Automatische Aktualisierung fuer die Queries-Seite. Standard: 5 Sekunden. 0 deaktiviert den Auto-Refresh.",
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,10 +209,18 @@ $detectApi = function (array $instance) use ($v6Auth, $v6RequestAny, $v5Request)
|
|||||||
$authRes = $v6Auth($instance);
|
$authRes = $v6Auth($instance);
|
||||||
if (($authRes['ok'] ?? false) && !empty($authRes['sid'])) {
|
if (($authRes['ok'] ?? false) && !empty($authRes['sid'])) {
|
||||||
$sid = (string)$authRes['sid'];
|
$sid = (string)$authRes['sid'];
|
||||||
|
|
||||||
|
$probe = $v6RequestAny($instance, ['dns/blocking', 'stats/summary', 'summary'], 'GET', [], $sid);
|
||||||
|
return ['version' => 6, 'sid' => $sid, 'probe' => $probe, 'auth' => $authRes];
|
||||||
|
}
|
||||||
|
|
||||||
|
$httpCode = (int)($authRes['http_code'] ?? 0);
|
||||||
|
if (in_array($httpCode, [401, 403], true)) {
|
||||||
|
return ['version' => 6, 'sid' => '', 'probe' => $authRes, 'auth' => $authRes];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$probe = $v6RequestAny($instance, ['stats/summary', 'summary'], 'GET', [], $sid);
|
$probe = $v6RequestAny($instance, ['dns/blocking', 'stats/summary', 'summary'], 'GET', [], $sid);
|
||||||
if ($probe['ok'] || in_array((int)($probe['http_code'] ?? 0), [401, 403], true)) {
|
if ($probe['ok'] || in_array((int)($probe['http_code'] ?? 0), [401, 403], true)) {
|
||||||
return ['version' => 6, 'sid' => $sid, 'probe' => $probe, 'auth' => $authRes];
|
return ['version' => 6, 'sid' => $sid, 'probe' => $probe, 'auth' => $authRes];
|
||||||
}
|
}
|
||||||
@@ -222,7 +230,7 @@ $detectApi = function (array $instance) use ($v6Auth, $v6RequestAny, $v5Request)
|
|||||||
return ['version' => 5, 'sid' => '', 'probe' => $legacy];
|
return ['version' => 5, 'sid' => '', 'probe' => $legacy];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['version' => 0, 'sid' => '', 'probe' => $probe, 'legacy' => $legacy];
|
return ['version' => 0, 'sid' => '', 'probe' => $probe, 'legacy' => $legacy, 'auth' => $authRes];
|
||||||
};
|
};
|
||||||
|
|
||||||
$debugResult = static function (string $label, string $instanceId, array $instance, array $result) use ($debugPush): void {
|
$debugResult = static function (string $label, string $instanceId, array $instance, array $result) use ($debugPush): void {
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ $assets = app()->assets();
|
|||||||
$assets->addStyle('/module/pihole/asset?file=pihole.css');
|
$assets->addStyle('/module/pihole/asset?file=pihole.css');
|
||||||
$assets->addScript('/module/pihole/asset?file=pihole.js', 'footer', true);
|
$assets->addScript('/module/pihole/asset?file=pihole.js', 'footer', true);
|
||||||
|
|
||||||
|
$settings = modules()->settings('pihole');
|
||||||
$instances = module_fn('pihole', 'instances');
|
$instances = module_fn('pihole', 'instances');
|
||||||
$hasConfig = !empty($instances);
|
$hasConfig = !empty($instances);
|
||||||
|
$refreshSeconds = (int)($settings['dashboard_refresh_sec'] ?? 1);
|
||||||
|
if ($refreshSeconds < 0) {
|
||||||
|
$refreshSeconds = 1;
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<?= module_shell_header('pihole', [
|
<?= module_shell_header('pihole', [
|
||||||
'title' => 'Pi-hole Dashboard',
|
'title' => 'Pi-hole Dashboard',
|
||||||
'description' => 'Status, Blockings, Usage und Steuerung fuer beide Instanzen.',
|
'description' => 'Status, Blockings, Usage und Steuerung fuer beide Instanzen.',
|
||||||
]) ?>
|
]) ?>
|
||||||
<div class="module-flow pihole-page" data-pihole-page="dashboard">
|
<div class="module-flow pihole-page" data-pihole-page="dashboard" data-refresh-seconds="<?= e((string)$refreshSeconds) ?>">
|
||||||
|
|
||||||
<section class="module-box">
|
<section class="module-box">
|
||||||
<div class="pihole-section-header">
|
<div class="pihole-section-header">
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ $assets = app()->assets();
|
|||||||
$assets->addStyle('/module/pihole/asset?file=pihole.css');
|
$assets->addStyle('/module/pihole/asset?file=pihole.css');
|
||||||
$assets->addScript('/module/pihole/asset?file=pihole.js', 'footer', true);
|
$assets->addScript('/module/pihole/asset?file=pihole.js', 'footer', true);
|
||||||
|
|
||||||
|
$settings = modules()->settings('pihole');
|
||||||
$instances = module_fn('pihole', 'instances');
|
$instances = module_fn('pihole', 'instances');
|
||||||
$hasConfig = !empty($instances);
|
$hasConfig = !empty($instances);
|
||||||
|
$refreshSeconds = (int)($settings['lists_refresh_sec'] ?? 5);
|
||||||
|
if ($refreshSeconds < 0) {
|
||||||
|
$refreshSeconds = 5;
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<?= module_shell_header('pihole', [
|
<?= module_shell_header('pihole', [
|
||||||
'title' => 'Listen & Domains',
|
'title' => 'Listen & Domains',
|
||||||
'description' => 'Top-Domains, Listen-Updates und neue Eintraege auf der Primaer-Instanz.',
|
'description' => 'Top-Domains, Listen-Updates und neue Eintraege auf der Primaer-Instanz.',
|
||||||
]) ?>
|
]) ?>
|
||||||
<div class="module-flow pihole-page" data-pihole-page="lists">
|
<div class="module-flow pihole-page" data-pihole-page="lists" data-refresh-seconds="<?= e((string)$refreshSeconds) ?>">
|
||||||
<?php if (!$hasConfig): ?>
|
<?php if (!$hasConfig): ?>
|
||||||
<div class="module-box">
|
<div class="module-box">
|
||||||
<strong>Keine Instanzen konfiguriert</strong>
|
<strong>Keine Instanzen konfiguriert</strong>
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ $assets = app()->assets();
|
|||||||
$assets->addStyle('/module/pihole/asset?file=pihole.css');
|
$assets->addStyle('/module/pihole/asset?file=pihole.css');
|
||||||
$assets->addScript('/module/pihole/asset?file=pihole.js', 'footer', true);
|
$assets->addScript('/module/pihole/asset?file=pihole.js', 'footer', true);
|
||||||
|
|
||||||
|
$settings = modules()->settings('pihole');
|
||||||
$instances = module_fn('pihole', 'instances');
|
$instances = module_fn('pihole', 'instances');
|
||||||
$hasConfig = !empty($instances);
|
$hasConfig = !empty($instances);
|
||||||
|
$refreshSeconds = (int)($settings['queries_refresh_sec'] ?? 5);
|
||||||
|
if ($refreshSeconds < 0) {
|
||||||
|
$refreshSeconds = 5;
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<?= module_shell_header('pihole', [
|
<?= module_shell_header('pihole', [
|
||||||
'title' => 'Zugriffe & Blockings',
|
'title' => 'Zugriffe & Blockings',
|
||||||
'description' => 'Aktuelle Blockings, Top Clients und Status pro Instanz.',
|
'description' => 'Aktuelle Blockings, Top Clients und Status pro Instanz.',
|
||||||
]) ?>
|
]) ?>
|
||||||
<div class="module-flow pihole-page" data-pihole-page="queries">
|
<div class="module-flow pihole-page" data-pihole-page="queries" data-refresh-seconds="<?= e((string)$refreshSeconds) ?>">
|
||||||
<?php if (!$hasConfig): ?>
|
<?php if (!$hasConfig): ?>
|
||||||
<div class="module-box">
|
<div class="module-box">
|
||||||
<strong>Keine Instanzen konfiguriert</strong>
|
<strong>Keine Instanzen konfiguriert</strong>
|
||||||
|
|||||||
Reference in New Issue
Block a user