GitHub Action
Sync from GitHub Actions (Clean Commit)
7f22d3c
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Node View - TUM Neural Net</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
</style>
</head>
<body class="bg-slate-50 text-slate-800 min-h-screen pb-20">
<!-- Navbar -->
<nav class="bg-white border-b border-slate-200 sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<a href="/" class="flex items-center gap-2 text-slate-500 hover:text-slate-900 transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
<span class="font-medium">Return to Network</span>
</a>
</div>
<div class="flex items-center">
<span class="text-sm font-mono text-slate-400" id="node-id-display">Node ID: Loading...</span>
</div>
</div>
</div>
</nav>
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Column: Content (2/3) -->
<div class="lg:col-span-2 space-y-8">
<!-- Header Card -->
<div class="bg-white p-8 rounded-2xl shadow-sm border border-slate-200">
<div class="flex items-center gap-2 mb-4">
<span
class="bg-blue-100 text-blue-800 text-xs font-bold px-2.5 py-0.5 rounded border border-blue-200">ACTIVE
NODE</span>
<span class="text-xs text-slate-400 font-mono" id="node-type">Type: WebPage</span>
</div>
<h1 class="text-3xl font-extrabold text-slate-900 mb-4 leading-tight" id="title">Loading Node
Data...</h1>
<div class="flex items-center gap-4 text-sm text-slate-500 border-t border-slate-100 pt-4">
<a href="#" id="external-link" target="_blank"
class="flex items-center gap-1 text-blue-600 hover:text-blue-800 font-medium transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14">
</path>
</svg>
Visit Source Origin
</a>
</div>
</div>
<!-- Content Card -->
<div class="bg-white p-8 rounded-2xl shadow-sm border border-slate-200">
<h2 class="text-lg font-bold text-slate-900 mb-4 flex items-center gap-2">
<svg class="w-5 h-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">
</path>
</svg>
Extracted Knowledge
</h2>
<div class="prose prose-slate max-w-none text-slate-600 leading-relaxed" id="content">
<!-- Content injected here -->
</div>
</div>
</div>
<!-- Right Column: Connections (1/3) -->
<div class="space-y-8">
<!-- Collaborative Filtering (Community Trails) -->
<div id="collab-section" class="hidden">
<div
class="bg-gradient-to-br from-orange-50 to-white p-6 rounded-2xl shadow-sm border border-orange-100">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold text-orange-900 flex items-center gap-2">
👣 Community Trails
</h2>
<div class="group relative flex justify-center">
<svg class="w-4 h-4 text-orange-400 cursor-help" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span
class="absolute bottom-6 scale-0 transition-all rounded bg-slate-800 p-2 text-xs text-white group-hover:scale-100 w-48 text-center z-50">
Paths frequently taken by other humans. These links have high "Transitive Trust".
</span>
</div>
</div>
<div class="space-y-3" id="collab-list">
<!-- Injected Items -->
</div>
</div>
</div>
<!-- Semantic Recommendations (Synapses) -->
<div class="bg-white p-6 rounded-2xl shadow-sm border border-slate-200">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold text-slate-900 flex items-center gap-2">
🧠 Semantic Synapses
</h2>
<div class="group relative flex justify-center">
<svg class="w-4 h-4 text-slate-400 cursor-help" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span
class="absolute bottom-6 scale-0 transition-all rounded bg-slate-800 p-2 text-xs text-white group-hover:scale-100 w-48 text-center z-50">
Concepts that are mathematically similar in the high-dimensional vector space.
</span>
</div>
</div>
<div class="space-y-3" id="related-list">
<!-- Injected Items -->
</div>
</div>
</div>
</div>
</main>
<script src="config.js"></script>
<script>
const itemId = window.location.pathname.split('/').pop();
let currentUrl = "";
async function loadItem() {
try {
const response = await fetch(API_CONFIG.getURL(`${API_CONFIG.endpoints.item}/${itemId}`));
const data = await response.json();
if (!response.ok) throw new Error(data.message || 'Failed to load');
const item = data.item;
const payload = item.payload;
currentUrl = payload.url;
// Render Main Content
document.title = `Node: ${payload.url} - TUM Neural Net`;
document.getElementById('title').textContent = payload.url;
document.getElementById('node-id-display').textContent = `ID: ${item.id.substring(0, 8)}...`;
document.getElementById('content').textContent = payload.content || payload.content_preview;
document.getElementById('external-link').href = payload.url;
// Render Semantic Synapses (Related)
const relatedList = document.getElementById('related-list');
relatedList.innerHTML = '';
data.related.forEach(rel => {
const card = document.createElement('a');
card.href = `/view/${rel.id}`;
card.className = 'block p-4 rounded-xl border border-slate-100 hover:border-blue-300 hover:bg-blue-50 transition-all group';
card.onclick = (e) => { recordTransition(rel.id); };
card.innerHTML = `
<div class="text-sm font-semibold text-slate-800 group-hover:text-blue-700 truncate mb-1">${rel.payload.url}</div>
<div class="text-xs text-slate-500 line-clamp-2 mb-2">${(rel.payload.content_preview || '').substring(0, 80)}...</div>
<div class="flex items-center gap-1 text-xs text-slate-400 font-mono">
<span class="w-1.5 h-1.5 bg-blue-400 rounded-full"></span>
Sim: ${rel.score.toFixed(4)}
</div>
`;
relatedList.appendChild(card);
});
// Render Community Trails (Collaborative)
const collabList = document.getElementById('collab-list');
if (data.collaborative && data.collaborative.length > 0) {
document.getElementById('collab-section').classList.remove('hidden');
collabList.innerHTML = '';
data.collaborative.forEach(col => {
const card = document.createElement('a');
card.href = `/view/${col.id}`;
card.className = 'block p-4 rounded-xl bg-white border border-orange-100 hover:border-orange-300 hover:shadow-sm transition-all group';
card.onclick = (e) => { recordTransition(col.id); };
card.innerHTML = `
<div class="flex items-center gap-2 mb-1">
<span class="text-orange-500">🔥</span>
<div class="text-sm font-bold text-slate-800 group-hover:text-orange-700 truncate flex-1">${col.payload.url}</div>
</div>
<div class="text-xs text-slate-500 line-clamp-2 mb-2">${(col.payload.content_preview || '').substring(0, 80)}...</div>
<div class="flex items-center gap-1 text-xs text-orange-600 font-bold bg-orange-50 inline-block px-2 py-1 rounded">
${col.count} Travelers
</div>
`;
collabList.appendChild(card);
});
} else {
document.getElementById('collab-section').classList.add('hidden');
}
} catch (e) {
document.body.innerHTML = `<div class="p-10 text-center text-red-600 font-bold">Error loading node: ${e.message}</div>`;
}
}
function recordTransition(targetId) {
const formData = new FormData();
formData.append('item_id', targetId);
formData.append('action', 'click');
formData.append('source_id', itemId); // itemId is UUID from URL
fetch(API_CONFIG.getURL(API_CONFIG.endpoints.feedback), {
method: 'POST',
body: formData,
keepalive: true
});
}
loadItem();
</script>
</body>
</html>