Files
2026-09-17 08:52:02 +02:00

120 lines
5.6 KiB
JavaScript

const VIEW_ROUTES = Object.freeze({
dashboard: '/dashboard',
devices: '/devices',
zones: '/zones',
groups: '/groups',
schedules: '/schedules',
automations: '/automations',
flows: '/flows',
simulation: '/simulation',
night: '/night-mode',
homeassistant: '/home-assistant',
settings: '/settings',
logs: '/events',
});
const ROUTE_VIEWS = Object.freeze(Object.fromEntries(Object.entries(VIEW_ROUTES).map(([view, path]) => [path, view])));
const HISTORY_TABS = Object.freeze(['overview', 'zones', 'devices', 'energy', 'network', 'sensors', 'custom']);
let routerInitialized = false;
function currentHistoryPath() {
const tab = HISTORY_TABS.includes(app.historyTab) ? app.historyTab : 'overview';
const params = new URLSearchParams();
const hours = $('#historyHours')?.value || new URLSearchParams(location.search).get('hours') || '24';
if (hours !== '24') params.set('hours', hours);
if (tab === 'zones' && app.historyZone !== 'all') params.set('zone', app.historyZone);
if (tab === 'devices' && app.historyDevice !== 'all') params.set('device', app.historyDevice);
if (tab === 'energy' && app.historyEnergyTargets?.length) params.set('targets', app.historyEnergyTargets.join(','));
if (tab === 'energy' && app.historyEnergyInterval !== 'daily') params.set('interval', app.historyEnergyInterval);
if (tab === 'energy' && app.historyEnergyCompare !== 'none') params.set('compare', app.historyEnergyCompare);
if (tab === 'network' && app.historyNetworkTarget !== 'all') params.set('target', app.historyNetworkTarget);
if (tab === 'sensors' && app.historySensor !== 'all') params.set('sensor', app.historySensor);
if (tab === 'custom' && app.customChartSeries.length) params.set('chart', encodeChartSpec(app.customChartSeries));
const query = params.toString();
return `/history/${tab}${query ? `?${query}` : ''}`;
}
function pathForView(name) {
return name === 'history' ? currentHistoryPath() : (VIEW_ROUTES[name] || VIEW_ROUTES.dashboard);
}
function appRelativePath(pathname = location.pathname) {
if (!APP_BASE) return pathname || '/';
if (pathname === APP_BASE) return '/';
if (pathname.startsWith(`${APP_BASE}/`)) return pathname.slice(APP_BASE.length) || '/';
return pathname || '/';
}
function updateBrowserUrl(path, replace = false) {
const normalized = path.startsWith('/') ? path : `/${path}`;
const target = `${APP_BASE}${normalized}` || normalized;
const current = `${location.pathname}${location.search}`;
if (current === target) return;
history[replace ? 'replaceState' : 'pushState']({}, '', target);
}
function restoreCurrentRoute(previousView) {
updateBrowserUrl(previousView === 'history' ? currentHistoryPath() : pathForView(previousView), true);
}
function applyRouteFromLocation() {
const routePath = appRelativePath();
const parts = routePath.split('/').filter(Boolean);
const first = parts[0] || 'dashboard';
const params = new URLSearchParams(location.search);
const previousView = app.currentView;
app.standaloneSimulation = first === 'simulation' && params.get('standalone') === '1';
document.body.classList.toggle('simulation-standalone', app.standaloneSimulation);
if (first === 'simulation') {
app.simulationScope = ['units', 'groups'].includes(params.get('scope')) ? params.get('scope') : 'units';
app.simulationTarget = params.get('target') || 'all';
}
if (first === 'history') {
app.historyTab = HISTORY_TABS.includes(parts[1]) ? parts[1] : 'overview';
app.historyZone = params.get('zone') || 'all';
app.historyDevice = params.get('device') || 'all';
if (app.historyTab === 'energy') {
const targetParam = params.get('targets') || params.get('device') || '';
app.historyEnergyTargets = targetParam ? targetParam.split(',').filter(Boolean).slice(0, 8) : (app.historyEnergyTargets || []);
app.historyEnergyDevice = app.historyEnergyTargets[0] || '';
if (['hourly', 'daily', 'weekly', 'monthly'].includes(params.get('interval'))) app.historyEnergyInterval = params.get('interval');
if (['none', 'previous_day', 'previous_period', 'previous_year'].includes(params.get('compare'))) app.historyEnergyCompare = params.get('compare');
}
app.historyNetworkTarget = params.get('target') || 'all';
app.historySensor = params.get('sensor') || 'all';
const hours = params.get('hours');
const validHours = hours && ['6', '24', '168', '720', '2160', '8760'].includes(hours) ? hours : null;
if (app.historyTab === 'energy') {
app.historyEnergyHours = validHours || app.historyEnergyHours || '720';
if ($('#historyHours')) $('#historyHours').value = app.historyEnergyHours;
} else if (validHours && $('#historyHours')) {
$('#historyHours').value = validHours;
}
if (app.historyTab === 'custom' && params.get('chart')) app.customChartSeries = decodeChartSpec(params.get('chart'));
if (!showView('history', { push: false, scroll: false })) restoreCurrentRoute(previousView);
return;
}
const view = first === 'index.html' ? 'dashboard' : ROUTE_VIEWS[`/${first}`];
if (!showView(view || 'dashboard', { push: false, scroll: false })) {
restoreCurrentRoute(previousView);
return;
}
if (first === 'flows') {
if (parts[1]) requestAnimationFrame(() => openFlowEditor(parts[1] === 'new' ? '' : parts[1], { push: false }));
else if (!$('#flowEditor')?.hidden) closeFlowEditor({ push: false, force: true });
}
if (!parts.length || first === 'index.html') updateBrowserUrl(VIEW_ROUTES.dashboard, true);
}
function initRouter() {
if (!routerInitialized) {
window.addEventListener('popstate', applyRouteFromLocation);
routerInitialized = true;
}
applyRouteFromLocation();
}