diff --git a/core/services/__pycache__/resolution.cpython-311.pyc b/core/services/__pycache__/resolution.cpython-311.pyc
index 7c7cad7..6ec4cfb 100644
Binary files a/core/services/__pycache__/resolution.cpython-311.pyc and b/core/services/__pycache__/resolution.cpython-311.pyc differ
diff --git a/core/services/resolution.py b/core/services/resolution.py
index fe7fa9f..4d44eb0 100644
--- a/core/services/resolution.py
+++ b/core/services/resolution.py
@@ -76,7 +76,8 @@ class NetworkDiscoveryService:
# Use first valid image found among search results if available
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'])
if images and not found_photo:
@@ -86,7 +87,7 @@ class NetworkDiscoveryService:
associate_val = meta['title'] or res['title']
if associate_val and associate_val.lower() != query.lower():
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(
source_entity=person, target_entity=associate,
@@ -103,4 +104,4 @@ class EntityResolutionService:
query = data.get('query')
if query:
return NetworkDiscoveryService.perform_osint_search(query)
- return None
\ No newline at end of file
+ return None
diff --git a/core/templates/core/dashboard.html b/core/templates/core/dashboard.html
index 7177835..47f4595 100644
--- a/core/templates/core/dashboard.html
+++ b/core/templates/core/dashboard.html
@@ -36,7 +36,7 @@
Network Visualization
-
+
@@ -82,14 +82,19 @@ function renderGraph(data) {
const width = 800;
const height = 600;
+ // Create SVG and enforce bounds
const svg = d3.select("#graphContainer")
.append("svg")
+ .attr("width", "100%")
+ .attr("height", "100%")
.attr("viewBox", [0, 0, width, height]);
const simulation = d3.forceSimulation(data.nodes)
.force("link", d3.forceLink(data.links).id(d => d.id).distance(100))
.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")
.selectAll("line")
@@ -108,35 +113,36 @@ function renderGraph(data) {
.on("drag", dragged)
.on("end", dragended));
+ // Reduce node sizes significantly
+ const radius = 12;
node.append("circle")
- .attr("r", 20)
+ .attr("r", radius)
.attr("class", "node-circle")
.attr("fill", d => d.type === 'PERSON' ? '#e74c3c' : '#3498db');
- // Add Image if available
+ // Add Image if available, scaled down
node.filter(d => d.photo)
.append("image")
.attr("xlink:href", d => d.photo)
- .attr("x", -15)
- .attr("y", -15)
- .attr("width", 30)
- .attr("height", 30)
- .attr("clip-path", "circle(15px)");
+ .attr("x", -radius)
+ .attr("y", -radius)
+ .attr("width", radius * 2)
+ .attr("height", radius * 2)
+ .attr("clip-path", `circle(${radius}px)`);
node.append("text")
- .attr("dy", 35)
+ .attr("dy", radius + 15)
.attr("text-anchor", "middle")
.attr("class", "node-text")
.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", () => {
+ // 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)
.attr("x2", d => d.target.x).attr("y2", d => d.target.y);
node.attr("transform", d => `translate(${d.x},${d.y})`);
@@ -160,4 +166,4 @@ function renderGraph(data) {
}
}
-{% endblock %}
\ No newline at end of file
+{% endblock %}