This commit is contained in:
Flatlogic Bot 2026-03-23 00:23:09 +00:00
parent 5fa2cf7ba7
commit 16879daf35
3 changed files with 28 additions and 21 deletions

View File

@ -76,7 +76,8 @@ class NetworkDiscoveryService:
# Use first valid image found among search results if available # Use first valid image found among search results if available
found_photo = None found_photo = None
for res in search_results[:3]: # Limit crawling to top 3 # Increase search limit to 6 and improve crawling logic
for res in search_results[:6]:
meta, images = crawler.fetch_url(res['url']) meta, images = crawler.fetch_url(res['url'])
if images and not found_photo: if images and not found_photo:
@ -86,7 +87,7 @@ class NetworkDiscoveryService:
associate_val = meta['title'] or res['title'] associate_val = meta['title'] or res['title']
if associate_val and associate_val.lower() != query.lower(): if associate_val and associate_val.lower() != query.lower():
associate, _ = Entity.objects.get_or_create( associate, _ = Entity.objects.get_or_create(
entity_type='PERSON', value=associate_val, source=source entity_type='PERSON', value=associate_val[:100], source=source
) )
Relationship.objects.get_or_create( Relationship.objects.get_or_create(
source_entity=person, target_entity=associate, source_entity=person, target_entity=associate,
@ -103,4 +104,4 @@ class EntityResolutionService:
query = data.get('query') query = data.get('query')
if query: if query:
return NetworkDiscoveryService.perform_osint_search(query) return NetworkDiscoveryService.perform_osint_search(query)
return None return None

View File

@ -36,7 +36,7 @@
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Network Visualization</h5> <h5 class="card-title">Network Visualization</h5>
<div id="graphContainer" style="width: 100%; height: 600px; background: #f8f9fa; border: 1px solid #ddd;"></div> <div id="graphContainer" style="width: 100%; height: 600px; background: #f8f9fa; border: 1px solid #ddd; overflow: hidden;"></div>
</div> </div>
</div> </div>
</div> </div>
@ -82,14 +82,19 @@ function renderGraph(data) {
const width = 800; const width = 800;
const height = 600; const height = 600;
// Create SVG and enforce bounds
const svg = d3.select("#graphContainer") const svg = d3.select("#graphContainer")
.append("svg") .append("svg")
.attr("width", "100%")
.attr("height", "100%")
.attr("viewBox", [0, 0, width, height]); .attr("viewBox", [0, 0, width, height]);
const simulation = d3.forceSimulation(data.nodes) const simulation = d3.forceSimulation(data.nodes)
.force("link", d3.forceLink(data.links).id(d => d.id).distance(100)) .force("link", d3.forceLink(data.links).id(d => d.id).distance(100))
.force("charge", d3.forceManyBody().strength(-300)) .force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2)); .force("center", d3.forceCenter(width / 2, height / 2))
.force("x", d3.forceX(width / 2).strength(0.05))
.force("y", d3.forceY(height / 2).strength(0.05));
const link = svg.append("g") const link = svg.append("g")
.selectAll("line") .selectAll("line")
@ -108,35 +113,36 @@ function renderGraph(data) {
.on("drag", dragged) .on("drag", dragged)
.on("end", dragended)); .on("end", dragended));
// Reduce node sizes significantly
const radius = 12;
node.append("circle") node.append("circle")
.attr("r", 20) .attr("r", radius)
.attr("class", "node-circle") .attr("class", "node-circle")
.attr("fill", d => d.type === 'PERSON' ? '#e74c3c' : '#3498db'); .attr("fill", d => d.type === 'PERSON' ? '#e74c3c' : '#3498db');
// Add Image if available // Add Image if available, scaled down
node.filter(d => d.photo) node.filter(d => d.photo)
.append("image") .append("image")
.attr("xlink:href", d => d.photo) .attr("xlink:href", d => d.photo)
.attr("x", -15) .attr("x", -radius)
.attr("y", -15) .attr("y", -radius)
.attr("width", 30) .attr("width", radius * 2)
.attr("height", 30) .attr("height", radius * 2)
.attr("clip-path", "circle(15px)"); .attr("clip-path", `circle(${radius}px)`);
node.append("text") node.append("text")
.attr("dy", 35) .attr("dy", radius + 15)
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("class", "node-text") .attr("class", "node-text")
.text(d => d.name); .text(d => d.name);
node.append("text")
.attr("dy", 48)
.attr("text-anchor", "middle")
.attr("class", "node-text")
.attr("fill", "#666")
.text(d => d.code || '');
simulation.on("tick", () => { simulation.on("tick", () => {
// Enforce boundary constraints
node.each(d => {
d.x = Math.max(radius, Math.min(width - radius, d.x));
d.y = Math.max(radius, Math.min(height - radius, d.y));
});
link.attr("x1", d => d.source.x).attr("y1", d => d.source.y) link.attr("x1", d => d.source.x).attr("y1", d => d.source.y)
.attr("x2", d => d.target.x).attr("y2", d => d.target.y); .attr("x2", d => d.target.x).attr("y2", d => d.target.y);
node.attr("transform", d => `translate(${d.x},${d.y})`); node.attr("transform", d => `translate(${d.x},${d.y})`);
@ -160,4 +166,4 @@ function renderGraph(data) {
} }
} }
</script> </script>
{% endblock %} {% endblock %}