function getNavParams() {
const p = new URLSearchParams(location.search);
return {
level: p.get('level'),
node: p.get('node'),
side: p.get('side'),
group: p.get('group'),
mode: p.get('mode'),
dig: p.get('dig'),
};
}
function navSide() {
return window.CURRENT && window.viewSide ? window.viewSide : null;
}
function navViewState() {
return {
level: currentLevel() ?? null,
side: navSide(),
group: window.drillGroup || null,
mode: window.nodeSizeMode || null,
dig: window.dig || 0,
};
}
function navViewUrl(st) {
const p = new URLSearchParams();
if (st.level) p.set('level', st.level);
if (st.side) p.set('side', st.side);
if (st.group) p.set('group', st.group);
if (st.mode) p.set('mode', st.mode);
if (st.dig) p.set('dig', st.dig);
return p.toString() ? '?' + p : location.pathname;
}
window.navPushView = function() {
const st = navViewState();
history.pushState(st, '', navViewUrl(st));
};
window.navReplaceView = function() {
const st = navViewState();
history.replaceState(st, '', navViewUrl(st));
};
window.navPush = function(level, nodeId) {
const p = new URLSearchParams();
if (level) p.set('level', level);
const side = navSide();
if (side) p.set('side', side);
const grp = window.drillGroup || null;
if (grp) p.set('group', grp);
const mode = window.nodeSizeMode || null;
if (mode) p.set('mode', mode);
const dig = window.dig || 0;
if (dig) p.set('dig', dig);
if (nodeId) p.set('node', nodeId);
const url = p.toString() ? '?' + p : location.pathname;
history.pushState({ level: level ?? null, node: nodeId ?? null, side, group: grp, mode, dig }, '', url);
};
window.navSetSide = function() {
const st = { ...(history.state || {}), ...navViewState() };
history.replaceState(st, '', navViewUrl(st));
};
function currentLevel() {
return document.querySelector('.view.active')?.dataset.view ?? null;
}
function switchToLevel(target) {
document.querySelectorAll('.view').forEach(v => v.classList.toggle('active', v.dataset.view === target));
document.querySelectorAll('.report-switch a').forEach(l => l.classList.toggle('selected', l.dataset.view === target));
const sec = document.querySelector('.view.active');
if (sec && sec.dataset.rendered !== 'true' && window.gv) renderView(sec);
}
function openModalForNode(nodeId, level) {
const onSide = activeGraph(level).nodes.find(n => n.id === nodeId);
const nodeData = onSide ?? window.DIFF?.[level]?.nodes?.find(n => n.id === nodeId);
if (!nodeData) return false;
window._modalNode = { id: nodeId, level };
window.hideMetricTooltip?.();
const section = document.querySelector(`.view[data-view="${level}"]`);
const overlay = getModal();
if (onSide) {
const mc = buildModalContent(nodeData, level);
document.getElementById('node-modal-hdr-title').innerHTML = mc.hdr;
document.getElementById('node-modal-body').innerHTML = mc.body;
window.setModalDiagram(mc.diagram);
attachModalCheckbox(nodeData, level, section);
} else {
const side = viewModeSuffix().trim(); document.getElementById('node-modal-hdr-title').innerHTML =
`<span class="nm-title">${escHtml(nodeData.name || nodeId)}</span>`;
document.getElementById('node-modal-body').innerHTML =
`<div class="nm-absent">Not present in the ${escHtml(side.toLowerCase())} snapshot.</div>`;
window.setModalDiagram('');
}
overlay.style.display = 'flex';
document.body.style.overflow = 'hidden';
window.flyoutHeader?.mount(overlay, 'modal');
return true;
}