Skip to content

Commit

Permalink
#1 js
Browse files Browse the repository at this point in the history
  • Loading branch information
Scobiform committed Apr 17, 2024
1 parent fed50cd commit 178cd9d
Showing 1 changed file with 72 additions and 98 deletions.
170 changes: 72 additions & 98 deletions templates/graph.html
Original file line number Diff line number Diff line change
@@ -1,107 +1,81 @@
<div id="graph"></div>
<script>
document.addEventListener('DOMContentLoaded', async function() {
const apiBaseUrl = '{{ api_base_url }}';
const accessToken = sessionStorage.getItem('accessToken');
const userId = '{{ user.id }}';
const user = { id: userId, username: '{{ user.username }}', avatar: '{{ user.avatar }}' };

document.addEventListener('DOMContentLoaded', function() {
const apiBaseUrl = '{{ api_base_url }}';
const accessToken = sessionStorage.getItem('accessToken'); // Ensure this is stored securely
const userId = '{{ user.id }}';
const followers = await fetchAllItems(userId, 'followers');
const followings = await fetchAllItems(userId, 'following');
const graphData = generateGraphData(user, followers, followings);
initGraph(graphData);
});

Promise.all([
fetchAllItems(userId, 'followers'),
fetchAllItems(userId, 'following')
]).then(([followers, followings]) => {
const user = { id: userId, username: 'User' }; // Mock user data, replace with actual data as needed
const graphData = generateGraphData(user, followers, followings);
initGraph(graphData);
});
});
async function fetchAllItems(userId, endpoint) {
let items = [];
let maxId = null;
do {
const response = await fetch(`${apiBaseUrl}/${endpoint}/${userId}?limit=500&max_id=${maxId}`, {
headers: { 'Authorization': `Bearer ${accessToken}` }
});
const data = await response.json();
items = items.concat(data);
maxId = data.length > 0 ? data[data.length - 1].id : null;
} while (maxId != null);
return items;
}

async function fetchAllItems(userId, endpoint) {
let items = [];
let maxId = null;
do {
const response = await fetch(`${apiBaseUrl}/${endpoint}/${userId}?limit=500&max_id=${maxId}`, {
headers: { 'Authorization': `Bearer ${accessToken}` }
});
const data = await response.json();
items = items.concat(data);
maxId = data.length > 0 ? data[data.length - 1].id : null;
} while (maxId != null);
return items;
}
function generateGraphData(user, followers, followings) {
const nodes = [{ id: user.id, username: user.username, type: 'user', avatar: user.avatar }];
const followerNodes = followers.map(f => ({ id: f.id, username: f.username, type: 'follower', avatar: f.avatar }));
const followingNodes = followings.map(f => ({ id: f.id, username: f.username, type: 'following', avatar: f.avatar }));
nodes.push(...followerNodes, ...followingNodes);
const links = followerNodes.map(f => ({ source: user.id, target: f.id }))
.concat(followingNodes.map(f => ({ source: user.id, target: f.id })));
return { nodes, links };
}

function generateGraphData(user, followers, followings) {
const nodes = [{ id: user.id, username: user.username, type: 'user' }];
const followerNodes = followers.map(f => ({ id: f.id, username: f.username, type: 'follower' }));
const followingNodes = followings.map(f => ({ id: f.id, username: f.username, type: 'following' }));
nodes.push(...followerNodes, ...followingNodes);
const links = followerNodes.map(f => ({ source: user.id, target: f.id }))
.concat(followingNodes.map(f => ({ source: user.id, target: f.id })));
return { nodes, links };
}
function initGraph(graphData) {
const Graph = ForceGraph()(document.getElementById('graph'))
.backgroundColor('#F5F5FF')
.height(window.innerHeight - 60)
.graphData(graphData)
.nodeCanvasObject((node, ctx, globalScale) => {
const label = node.username;
const fontSize = 12 / globalScale;
const imgSize = 28;
ctx.font = `${fontSize}px Sans-Serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
if (node.avatar && node.img) {
ctx.drawImage(node.img, node.x - imgSize / 2, node.y - imgSize / 2, imgSize, imgSize);
} else if (node.avatar && !node.img) {
const img = new Image();
img.src = node.avatar;
img.onload = () => {
node.img = img;
ctx.drawImage(img, node.x - imgSize / 2, node.y - imgSize / 2, imgSize, imgSize);
};
}
ctx.fillStyle = (node.type === 'follower') ? 'red' : 'blue';
ctx.fillText(label, node.x, node.y + imgSize / 2 + 5);
})
.onNodeClick(node => console.log(node));

function initGraph(graphData) {
const Graph = ForceGraph()(document.getElementById('graph'))
.backgroundColor('#F5F5FF')
.height(window.innerHeight - 60)
.graphData(graphData)
.nodeCanvasObject((node, ctx, globalScale) => {
const label = node.username;
const fontSize = 12 / globalScale;
const imgSize = 28; // Adjust size as needed
ctx.font = `${fontSize}px Sans-Serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
Graph.d3Force('charge', d3.forceManyBody().strength(-120));
Graph.d3Force('link', d3.forceLink().distance(140));
}

// Draw avatar images
if (node.avatar && node.img) {
ctx.drawImage(node.img, node.x - imgSize / 2, node.y - imgSize / 2, imgSize, imgSize);
} else if (node.avatar && !node.img) {
const img = new Image();
img.src = node.avatar;
img.onload = () => {
node.img = img;
ctx.drawImage(img, node.x - imgSize / 2, node.y - imgSize / 2, imgSize, imgSize);
};
}

// Draw labels
ctx.fillStyle = (node.type === 'follower') ? 'red' : 'blue';
ctx.fillText(label, node.x, node.y + imgSize / 2 + 5);
})
.onNodeClick(node => console.log(node));

// Configuration for forces
Graph.d3Force('charge', d3.forceManyBody().strength(-120));
Graph.d3Force('link', d3.forceLink().distance(140));

elementResizeDetectorMaker().listenTo(
document.getElementById('graph'),
el => Graph.width(el.offsetWidth)
);
}

// Configuration for forces
Graph.d3Force('charge', d3.forceManyBody().strength(-120));
Graph.d3Force('link', d3.forceLink().distance(140));

elementResizeDetectorMaker().listenTo(
document.getElementById('graph'),
el => Graph.width(el.offsetWidth)
);

function filterNodes(filterType) {
const filteredData = {
nodes: graphData.nodes.filter(node => filterType === 'all' || node.type === filterType),
links: graphData.links.filter(link => {
const sourceVisible = filterType === 'all' || link.source.type === filterType;
const targetVisible = filterType === 'all' || link.target.type === filterType;
return sourceVisible && targetVisible;
})
};

// Update the graph with the filtered data
Graph.graphData(filteredData);
}

function filterNodes(filterType) {
const filteredData = {
nodes: graphData.nodes.filter(node => filterType === 'all' || node.type === filterType),
links: graphData.links.filter(link => {
const sourceVisible = filterType === 'all' || link.source.type === filterType;
const targetVisible = filterType === 'all' || link.target.type === filterType;
return sourceVisible && targetVisible;
})
};
Graph.graphData(filteredData); // Assuming 'Graph' is your ForceGraph instance
}
</script>

0 comments on commit 178cd9d

Please sign in to comment.