Files
desktop/modules/pihole/assets/pihole-native.js
Lars Gebhardt-Kusche 80874e2e1d
All checks were successful
Deploy / deploy-staging (push) Successful in 24s
Deploy / deploy-production (push) Has been skipped
Pihole
2026-06-24 00:18:11 +02:00

122 lines
3.4 KiB
JavaScript

(function () {
'use strict';
function toPartialUrl(input, fallbackView) {
const url = new URL(input, window.location.origin);
if (!url.searchParams.has('view') && fallbackView) {
url.searchParams.set('view', fallbackView);
}
url.searchParams.set('partial', '1');
return url;
}
async function fetchHtml(url, options) {
const response = await fetch(url.toString(), {
credentials: 'same-origin',
headers: {
Accept: 'text/html',
'X-Requested-With': 'XMLHttpRequest'
},
...options
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.text();
}
function enhanceHost(host, state) {
host.querySelectorAll('a[href]').forEach((link) => {
const href = link.getAttribute('href') || '';
if (!href.startsWith('/apps/pihole')) {
return;
}
link.addEventListener('click', (event) => {
event.preventDefault();
state.load(href);
});
});
host.querySelectorAll('form').forEach((form) => {
form.addEventListener('submit', async (event) => {
event.preventDefault();
const method = String(form.getAttribute('method') || 'get').toUpperCase();
const action = form.getAttribute('action') || state.currentUrl.toString();
const formData = new FormData(form);
const url = toPartialUrl(action, state.defaultView);
try {
if (method === 'GET') {
const next = new URL(url.toString());
next.search = '';
next.searchParams.set('partial', '1');
for (const [key, value] of formData.entries()) {
next.searchParams.append(key, String(value));
}
await state.load(next.toString());
return;
}
const html = await fetchHtml(url, {
method,
body: formData
});
state.render(html, url);
} catch (error) {
state.renderError(error);
}
});
});
}
function initContent(host) {
if (typeof window.initPiholeModule === 'function') {
window.initPiholeModule(host);
}
if (typeof window.initPiholeInstancesModule === 'function') {
window.initPiholeInstancesModule(host);
}
}
window.initPiholeApp = function initPiholeApp(host, options) {
if (!(host instanceof HTMLElement)) {
return;
}
const entryRoute = String(options?.entryRoute || '/apps/pihole/index.php');
const defaultView = String(options?.defaultView || 'dashboard');
const state = {
defaultView,
currentUrl: toPartialUrl(entryRoute, defaultView),
async load(targetUrl) {
const url = toPartialUrl(targetUrl, defaultView);
this.currentUrl = url;
host.innerHTML = '<div class="window-app-loading"><p>Pi-hole wird geladen...</p></div>';
try {
const html = await fetchHtml(url);
this.render(html, url);
} catch (error) {
this.renderError(error);
}
},
render(html, url) {
this.currentUrl = url;
host.innerHTML = html;
enhanceHost(host, this);
initContent(host);
},
renderError(error) {
const message = error instanceof Error ? error.message : 'Pi-hole konnte nicht geladen werden.';
host.innerHTML = `<div class="window-app-error-state"><p>${message}</p></div>`;
}
};
state.load(entryRoute);
};
})();