⌕
Categories
85
Objects
—
Dependencies
ZOOM
📄 Node Documentation
Click any node to view its
config files and Splunk docs
presetBtn.addEventListener('mouseover', () => { presetBtn.style.background = 'rgba(127,255,107,0.15)'; presetBtn.style.boxShadow = '0 0 30px rgba(127,255,107,0.3)'; }); presetBtn.addEventListener('mouseout', () => { presetBtn.style.background = 'rgba(15,22,32,0.9)'; presetBtn.style.boxShadow = '0 0 20px rgba(127,255,107,0.15)'; }); // Multi-path highlight — show ALL paths from Origin System to Analyst Queue function showPresetFlow() { // Exit other modes if (blastMode) { blastMode = false; blastBtn.classList.remove('active'); blastBanner.style.display = 'none'; clearBlast(); blastPanel.style.display = 'none'; } if (pathMode) { pathMode = false; pathBtn.classList.remove('active'); pathBanner.style.display = 'none'; clearPath(); pathPanel.style.display = 'none'; } const SOURCE = 'Origin System'; const TARGET = 'Analyst Queue'; // BFS to find ALL nodes and links on ANY path from source to target // Step 1: forward reachability from SOURCE const fwdAdj = new Map(); links.forEach(l => { const s = typeof l.source === 'object' ? l.source.id : l.source; const t = typeof l.target === 'object' ? l.target.id : l.target; if (!fwdAdj.has(s)) fwdAdj.set(s, []); fwdAdj.get(s).push(t); }); // Step 2: backward reachability from TARGET const bwdAdj = new Map(); links.forEach(l => { const s = typeof l.source === 'object' ? l.source.id : l.source; const t = typeof l.target === 'object' ? l.target.id : l.target; if (!bwdAdj.has(t)) bwdAdj.set(t, []); bwdAdj.get(t).push(s); }); function bfsReach(start, adj) { const visited = new Set([start]); const queue = [start]; while (queue.length) { const curr = queue.shift(); for (const next of (adj.get(curr) || [])) { if (!visited.has(next)) { visited.add(next); queue.push(next); } } } return visited; } const fwdReach = bfsReach(SOURCE, fwdAdj); // all nodes reachable FROM source const bwdReach = bfsReach(TARGET, bwdAdj); // all nodes that can REACH target // Nodes on a valid path = intersection const onPath = new Set([...fwdReach].filter(n => bwdReach.has(n))); // Links on a valid path const onPathLinks = new Set(); links.forEach((l, i) => { const s = typeof l.source === 'object' ? l.source.id : l.source; const t = typeof l.target === 'object' ? l.target.id : l.target; if (onPath.has(s) && onPath.has(t)) onPathLinks.add(i); }); // Assign hop depths from SOURCE for colour grading const hopDepth = new Map(); const q = [[SOURCE, 0]]; const vis = new Set([SOURCE]); while (q.length) { const [curr, d] = q.shift(); hopDepth.set(curr, d); for (const next of (fwdAdj.get(curr) || [])) { if (!vis.has(next) && onPath.has(next)) { vis.add(next); q.push([next, d+1]); } } } const maxHop = Math.max(...hopDepth.values()); // Colour nodes by hop depth along a green→cyan→yellow→orange→red gradient function hopColor(hop) { const t = hop / Math.max(maxHop, 1); if (t < 0.25) return '#7fff6b'; if (t < 0.5) return '#00d4ff'; if (t < 0.75) return '#ffd700'; return '#e63946'; } // Apply styles nodeGroup.classed('path-source path-target path-node path-dim path-pending highlighted dimmed blast-source blast-hop1 blast-hop2 blast-hop3 blast-safe', false); nodeGroup.each(function(d) { const el = d3.select(this); if (!onPath.has(d.id)) { el.classed('path-dim', true); return; } const col = d.id === SOURCE ? '#7fff6b' : d.id === TARGET ? '#e63946' : hopColor(hopDepth.get(d.id) || 0); el.select('circle:first-of-type') .attr('stroke', col) .attr('stroke-width', d.id === SOURCE || d.id === TARGET ? 4 : 2.5) .style('filter', `drop-shadow(0 0 12px ${col})`); el.select('circle + circle').attr('fill', col); }); link .classed('path-active', (l, i) => onPathLinks.has(i)) .classed('path-dim', (l, i) => !onPathLinks.has(i)); // Show info panel pathPanel.style.display = 'block'; const hops = maxHop; const nodeCount = onPath.size; document.getElementById('path-content').innerHTML = `
Full pipeline from Origin System to Analyst Queue
${nodeCount}
nodes
${hops}
max hops
${onPathLinks.size}
edges
Colour = pipeline depth
${[...hopDepth.entries()].sort((a,b) => a[1]-b[1]).map(([id, hop]) => { const col = id === SOURCE ? '#7fff6b' : id === TARGET ? '#e63946' : hopColor(hop); return `
${id} hop ${hop}
`; }).join('')}
`; pathBanner.style.display = 'block'; pathBanner.innerHTML = `⇢ FLOW — Origin System → Analyst Queue  |  ${nodeCount} nodes · ${hops} max hops`; } function clearPresetFlow() { nodeGroup.classed('path-dim', false); nodeGroup.each(function(d) { const col = categories[d.category]?.color || '#5a7a99'; d3.select(this).select('circle:first-of-type') .attr('stroke', col).attr('stroke-width', 2).style('filter', null); d3.select(this).select('circle + circle').attr('fill', col); }); link.classed('path-active path-dim', false); pathPanel.style.display = 'none'; pathBanner.style.display = 'none'; } presetBtn.addEventListener('click', showPresetFlow);