Skip to content

Instantly share code, notes, and snippets.

@Windowsfreak
Last active May 12, 2026 13:25
Show Gist options
  • Select an option

  • Save Windowsfreak/3945740389f8cbcbd735c64a092d5671 to your computer and use it in GitHub Desktop.

Select an option

Save Windowsfreak/3945740389f8cbcbd735c64a092d5671 to your computer and use it in GitHub Desktop.
(async () => {
// 1. Configuration & Selectors
const CONTAINER_SELECTOR = 'div.@container/main.flex.flex-1.flex-col.gap-2.w-full'.replace(/([@/])/g, '\\$1');
const targetElement = document.querySelector(CONTAINER_SELECTOR);
if (!targetElement) {
console.error("Target container not found:", CONTAINER_SELECTOR);
return;
}
// 2. Load Dependencies (vis-network)
if (typeof vis === 'undefined') {
const script = document.createElement('script');
script.src = "https://unpkg.com/vis-network/standalone/umd/vis-network.min.js";
document.head.appendChild(script);
await new Promise(resolve => script.onload = resolve);
}
// 3. Inject Scoped Styles & Prepare Container
targetElement.innerHTML = `
<style>
#aurum-tree-wrapper {
width: 100%;
height: 800px;
background: radial-gradient(circle at top right, #1e293b 0%, #0f172a 100%);
border-radius: 12px;
position: relative;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.1);
}
#aurum-tree-network { width: 100%; height: 100%; }
.tree-overlay {
position: absolute; top: 20px; left: 20px; z-index: 5;
background: rgba(30, 41, 59, 0.7); backdrop-filter: blur(8px);
padding: 15px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.1);
pointer-events: none;
}
.tree-error {
padding: 40px; color: #f87171; text-align: center; font-family: sans-serif;
background: rgba(0,0,0,0.2); height: 100%; display: flex; align-items: center; justify-content: center;
}
</style>
<div id="aurum-tree-wrapper">
<div class="tree-overlay">
<h3 style="margin:0; color:#38bdf8; font-size:1.1rem;">Network Tree</h3>
<p style="margin:5px 0 0 0; color:#94a3b8; font-size:0.8rem;">Hierarchical Balance Analysis</p>
</div>
<div id="aurum-tree-network"></div>
</div>
`;
// 4. Authentication Check
const rawToken = localStorage.getItem('ib_portal_auth_token');
if (!rawToken) {
targetElement.innerHTML = `<div class="tree-error">Error: No 'ib_portal_auth_token' found in localStorage. Please log in first.</div>`;
return;
}
const token = rawToken.replace(/^"|"$/g, '');
const headers = {
'Accept': 'application/json, text/plain, */*',
'Authorization': `Bearer ${token}`
};
// 5. Fetch & Process Data
const API_URL = 'https://api.ibportal.io/api/Backoffice/v1.0/Tree/tag/UnilevelTree?minLevel=1&maxLevel=10&includeSelf=true';
try {
const response = await fetch(API_URL, { headers });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
const nodes = [];
const edges = [];
const dataMap = new Map();
// Pass 1: Map for lookups
data.forEach(item => dataMap.set(item.distributorId, { ...item, children: [] }));
// Pass 2: Build hierarchy
data.forEach(item => {
const parent = dataMap.get(item.enrollerId);
if (parent) parent.children.push(item.distributorId);
});
// Pass 3: Compute Net Balances & Build Vis Nodes
data.forEach(item => {
const distributor = dataMap.get(item.distributorId);
const childrenSum = distributor.children.reduce((s, cid) => s + (dataMap.get(cid)?.activeTotalBalance || 0), 0);
const netBalance = item.activeTotalBalance - childrenSum;
const x = Math.max(512, netBalance);
const margin = Math.round((Math.log2(x) - 8) * 4);
const hue = (item.level * 36) % 360;
nodes.push({
id: item.distributorId,
label: `<b>${item.fullName}</b>\n${netBalance.toFixed(2)}`,
color: {
background: `hsla(${hue}, 70%, 25%, 0.9)`,
border: `hsla(${hue}, 80%, 50%, 1)`,
highlight: { background: `hsla(${hue}, 80%, 40%, 1)`, border: '#fff' }
},
shape: 'box',
shapeProperties: {
borderDashes: !item.isQualified ? [5, 5] : false
},
margin: margin,
level: item.level,
font: { color: '#fff', size: 13, multi: 'html', align: 'center' },
borderWidth: 2,
shadow: { enabled: true, color: 'rgba(0,0,0,0.3)', size: 5 }
});
if (dataMap.has(item.enrollerId)) {
edges.push({
from: item.enrollerId, to: item.distributorId,
arrows: 'to', color: { color: 'rgba(255,255,255,0.15)' },
width: 1, smooth: { type: 'cubicBezier', forceDirection: 'vertical', roundness: 0.4 }
});
}
});
// 6. Initialize Network
const container = document.getElementById('aurum-tree-network');
new vis.Network(container, { nodes: new vis.DataSet(nodes), edges: new vis.DataSet(edges) }, {
layout: { hierarchical: { direction: 'UD', sortMethod: 'directed', levelSeparation: 120, nodeSpacing: 200 } },
physics: { enabled: false },
interaction: { hover: true, dragNodes: false }
});
} catch (e) {
console.error("Tree Rendering Error:", e);
targetElement.innerHTML = `<div class="tree-error">Failed to load tree data: ${e.message}</div>`;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment