mirror of
https://github.com/MrUnknownDE/utools.git
synced 2026-05-06 06:16:04 +02:00
rebase www template
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import { page as homePage } from './pages/home.js';
|
||||
import { page as subnetPage } from './pages/subnet.js';
|
||||
import { page as dnsPage } from './pages/dns.js';
|
||||
import { page as whoisPage } from './pages/whois.js';
|
||||
import { page as macPage } from './pages/mac.js';
|
||||
import { page as asnPage } from './pages/asn.js';
|
||||
|
||||
const routes = {
|
||||
'/': homePage,
|
||||
'/subnet': subnetPage,
|
||||
'/dns': dnsPage,
|
||||
'/whois': whoisPage,
|
||||
'/mac': macPage,
|
||||
'/asn': asnPage,
|
||||
};
|
||||
|
||||
const app = document.getElementById('app');
|
||||
let currentCleanup = null;
|
||||
|
||||
function setActiveNav(path) {
|
||||
document.querySelectorAll('nav a').forEach(a => {
|
||||
try {
|
||||
const p = new URL(a.href).pathname;
|
||||
a.classList.toggle('active-link', p === path);
|
||||
} catch {}
|
||||
});
|
||||
}
|
||||
|
||||
async function navigate(path, { push = true, search = '' } = {}) {
|
||||
const route = routes[path] ?? routes['/'];
|
||||
|
||||
// ── leave animation ──────────────────────────────────────────
|
||||
app.classList.add('page-leaving');
|
||||
if (currentCleanup) { try { currentCleanup(); } catch {} currentCleanup = null; }
|
||||
await new Promise(r => setTimeout(r, 200));
|
||||
|
||||
// ── swap content ─────────────────────────────────────────────
|
||||
app.innerHTML = route.template();
|
||||
document.title = route.title ? `${route.title} – uTools` : 'uTools – Network Suite';
|
||||
setActiveNav(path);
|
||||
|
||||
const fullUrl = path + (search ? (search.startsWith('?') ? search : '?' + search) : '');
|
||||
if (push) history.pushState({ path }, '', fullUrl);
|
||||
|
||||
// ── enter animation ──────────────────────────────────────────
|
||||
app.classList.remove('page-leaving');
|
||||
app.classList.add('page-entering');
|
||||
setTimeout(() => app.classList.remove('page-entering'), 300);
|
||||
|
||||
// ── init page ────────────────────────────────────────────────
|
||||
const cleanup = await route.init(search);
|
||||
currentCleanup = typeof cleanup === 'function' ? cleanup : null;
|
||||
}
|
||||
|
||||
// ── Intercept same-origin link clicks ───────────────────────────
|
||||
document.addEventListener('click', e => {
|
||||
const a = e.target.closest('a[href]');
|
||||
if (!a) return;
|
||||
let url;
|
||||
try { url = new URL(a.href); } catch { return; }
|
||||
if (url.origin !== location.origin) return;
|
||||
if (!(url.pathname in routes)) return;
|
||||
e.preventDefault();
|
||||
navigate(url.pathname, { push: true, search: url.search });
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', () => {
|
||||
navigate(location.pathname, { push: false, search: location.search });
|
||||
});
|
||||
|
||||
// ── Expose for programmatic navigation ──────────────────────────
|
||||
window._router = {
|
||||
navigate(path, searchObj = {}) {
|
||||
const s = new URLSearchParams(searchObj).toString();
|
||||
navigate(path, { push: true, search: s ? '?' + s : '' });
|
||||
}
|
||||
};
|
||||
|
||||
// ── Fetch version once ───────────────────────────────────────────
|
||||
fetch('/api/version')
|
||||
.then(r => r.json())
|
||||
.then(d => { const el = document.getElementById('commit-sha'); if (el) el.textContent = d.commitSha || 'unknown'; })
|
||||
.catch(() => { const el = document.getElementById('commit-sha'); if (el) el.textContent = 'error'; });
|
||||
|
||||
// ── Initial render ───────────────────────────────────────────────
|
||||
navigate(location.pathname, { push: false, search: location.search });
|
||||
Reference in New Issue
Block a user