| <!DOCTYPE html> |
| <html lang="fr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Ground Truth Graph</title> |
| <script src="https://cdn.jsdelivr.net/npm/vis-network@9.1.2/dist/vis-network.min.js"></script> |
| <style> |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| } |
| |
| body { |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| overflow: hidden; |
| } |
| |
| #mynetwork { |
| width: 100%; |
| height: 100vh; |
| background: white; |
| box-shadow: 0 4px 20px rgba(0,0,0,0.1); |
| } |
| |
| .header { |
| position: absolute; |
| top: 20px; |
| left: 20px; |
| z-index: 1000; |
| background: rgba(255, 255, 255, 0.95); |
| padding: 15px 25px; |
| border-radius: 12px; |
| box-shadow: 0 4px 15px rgba(0,0,0,0.2); |
| backdrop-filter: blur(10px); |
| } |
| |
| .header h1 { |
| color: #667eea; |
| font-size: 1.2em; |
| margin: 0; |
| font-weight: 600; |
| } |
| |
| .badge { |
| background: #10b981; |
| color: white; |
| padding: 4px 12px; |
| border-radius: 20px; |
| font-size: 0.75em; |
| font-weight: 600; |
| margin-left: 10px; |
| } |
| |
| .loading { |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| transform: translate(-50%, -50%); |
| text-align: center; |
| color: white; |
| font-size: 1.5em; |
| } |
| |
| .spinner { |
| border: 4px solid rgba(255,255,255,0.3); |
| border-radius: 50%; |
| border-top: 4px solid white; |
| width: 50px; |
| height: 50px; |
| animation: spin 1s linear infinite; |
| margin: 20px auto; |
| } |
| |
| @keyframes spin { |
| 0% { transform: rotate(0deg); } |
| 100% { transform: rotate(360deg); } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="header"> |
| <h1>📘 Ground Truth<span class="badge">GT</span></h1> |
| </div> |
|
|
| <div id="loading" class="loading"> |
| <div class="spinner"></div> |
| <div>Chargement du Ground Truth...</div> |
| </div> |
|
|
| <div id="mynetwork"></div> |
|
|
| <script> |
| console.log('🔍 Script GT chargé'); |
| |
| |
| const urlParams = new URLSearchParams(window.location.search); |
| const docName = urlParams.get('doc'); |
| |
| console.log('📄 Document demandé:', docName); |
| console.log('🌐 URL actuelle:', window.location.href); |
| |
| if (!docName) { |
| document.getElementById('loading').innerHTML = '<div style="color: #e74c3c; font-size: 1.2em;">❌ Aucun document spécifié dans l\'URL</div>'; |
| } else { |
| |
| const gtPath = `GT/${docName}.json`; |
| |
| console.log('📂 Chemin GT:', gtPath); |
| console.log('🔗 Tentative de chargement...'); |
| |
| fetch(gtPath) |
| .then(response => { |
| console.log('📡 Réponse reçue:', response.status, response.statusText); |
| |
| if (!response.ok) { |
| throw new Error(`Fichier non trouvé (${response.status})`); |
| } |
| return response.json(); |
| }) |
| .then(data => { |
| console.log('✅ Données GT chargées:', data); |
| console.log(' - Nœuds:', data.nodes?.length || 0); |
| console.log(' - Arêtes:', data.edges?.length || 0); |
| |
| document.getElementById('loading').style.display = 'none'; |
| displayGraph(data); |
| }) |
| .catch(error => { |
| console.error('❌ Erreur de chargement:', error); |
| document.getElementById('loading').innerHTML = |
| `<div style="color: #e74c3c;"> |
| <h2>❌ Erreur</h2> |
| <p style="font-size: 1em; margin-top: 10px;">${error.message}</p> |
| <p style="font-size: 0.9em; margin-top: 10px; color: #95a5a6;"> |
| Chemin tenté : <code style="background: rgba(255,255,255,0.2); padding: 4px 8px; border-radius: 4px;">${gtPath}</code> |
| </p> |
| <p style="font-size: 0.85em; margin-top: 10px;"> |
| 💡 Vérifiez la console du navigateur (F12) pour plus de détails |
| </p> |
| </div>`; |
| }); |
| } |
| |
| function displayGraph(data) { |
| console.log('🎨 Affichage du graphe...'); |
| |
| if (!data.nodes || !data.edges) { |
| console.error('❌ Format de données invalide:', data); |
| document.getElementById('loading').innerHTML = |
| '<div style="color: #e74c3c;">❌ Format de données invalide</div>'; |
| return; |
| } |
| |
| try { |
| |
| const nodes = data.nodes.map(node => ({ |
| id: node.id, |
| label: node.label, |
| shape: 'box', |
| color: { |
| background: '#10b981', |
| border: '#059669', |
| highlight: { |
| background: '#34d399', |
| border: '#059669' |
| } |
| }, |
| font: { |
| color: 'white', |
| size: 14, |
| face: 'Segoe UI', |
| bold: true |
| }, |
| margin: 10, |
| borderWidth: 2, |
| shadow: { |
| enabled: true, |
| color: 'rgba(0,0,0,0.2)', |
| size: 10, |
| x: 2, |
| y: 2 |
| } |
| })); |
| |
| |
| const edges = data.edges.map(edge => ({ |
| from: edge.source, |
| to: edge.target, |
| arrows: { |
| to: { |
| enabled: true, |
| scaleFactor: 0.8 |
| } |
| }, |
| color: { |
| color: '#10b981', |
| highlight: '#059669' |
| }, |
| width: 2, |
| smooth: { |
| type: 'cubicBezier', |
| roundness: 0.5 |
| } |
| })); |
| |
| console.log('✅ Nœuds préparés:', nodes.length); |
| console.log('✅ Arêtes préparées:', edges.length); |
| |
| |
| const container = document.getElementById('mynetwork'); |
| const graphData = { |
| nodes: new vis.DataSet(nodes), |
| edges: new vis.DataSet(edges) |
| }; |
| |
| const options = { |
| layout: { |
| hierarchical: { |
| enabled: true, |
| direction: 'UD', |
| sortMethod: 'directed', |
| nodeSpacing: 150, |
| levelSeparation: 120 |
| } |
| }, |
| physics: { |
| enabled: false |
| }, |
| interaction: { |
| hover: true, |
| tooltipDelay: 100, |
| navigationButtons: true, |
| keyboard: true |
| } |
| }; |
| |
| const network = new vis.Network(container, graphData, options); |
| |
| network.on('stabilizationIterationsDone', function() { |
| console.log('✅ Graphe stabilisé'); |
| }); |
| |
| console.log('✅ Graphe créé avec succès'); |
| |
| } catch (error) { |
| console.error('❌ Erreur lors de la création du graphe:', error); |
| document.getElementById('loading').innerHTML = |
| `<div style="color: #e74c3c;">❌ Erreur d'affichage : ${error.message}</div>`; |
| } |
| } |
| </script> |
| </body> |
| </html> |