Skip to content

Commit f849057

Browse files
committed
Render occurrence data in sidebar
When a node is selected, render any occurrence data in the sidebar.
1 parent 0286bc0 commit f849057

2 files changed

Lines changed: 55 additions & 7 deletions

File tree

static/css/graph.css

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ main {
3535
font-size: 1rem;
3636
}
3737

38-
.sidebar pre {
38+
.sidebar #node-details {
3939
white-space: pre-wrap;
4040
word-break: break-word;
4141
background: #ffffff;
@@ -44,8 +44,28 @@ main {
4444
border-radius: 0.375rem;
4545
}
4646

47+
.sidebar #node-details section {
48+
margin-bottom: 1rem;
49+
}
50+
51+
.sidebar #node-details a {
52+
color: #2563eb;
53+
text-decoration: none;
54+
}
55+
56+
.sidebar #node-details a:hover {
57+
text-decoration: underline;
58+
}
59+
4760
.status {
4861
margin-top: 0.5rem;
4962
font-size: 0.9rem;
5063
color: #374151;
5164
}
65+
66+
.occurrence {
67+
background-color: #ffeb3b;
68+
padding: 0.2em 0.4em;
69+
border-radius: 4px;
70+
font-weight: bold;
71+
}

templates/graph.html

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,46 @@ <h1>Graph Viewer</h1>
1414
<main>
1515
<div id="graph"></div>
1616
<aside class="sidebar">
17-
<h2></h2>
18-
<pre id="node-details">No node selected.</pre>
17+
<h2 id="sidebar-title">No node selected</h2>
18+
<div id="node-details">Select a node to view details.</div>
1919
</aside>
2020
</main>
2121

2222
<script src="https://unpkg.com/cytoscape@3.4.0/dist/cytoscape.min.js"></script>
2323
<script>
2424
const status = document.querySelector('.status');
25+
const sidebarTitle = document.getElementById('sidebar-title');
2526
const details = document.getElementById('node-details');
2627

27-
function formatNodeData(node) {
28+
function escapeHtml(value) {
29+
return String(value || '')
30+
.replace(/&/g, '&amp;')
31+
.replace(/</g, '&lt;')
32+
.replace(/>/g, '&gt;')
33+
.replace(/"/g, '&quot;')
34+
.replace(/'/g, '&#39;');
35+
}
36+
37+
function renderNodeDetails(node) {
2838
const data = node.data();
29-
return JSON.stringify(data, null, 2);
39+
sidebarTitle.textContent = data.label || 'Selected node';
40+
41+
const occurrences = Array.isArray(data.occurrences) ? data.occurrences : [];
42+
if (!occurrences.length) {
43+
details.innerHTML = '<p>No occurrences available.</p>';
44+
return;
45+
}
46+
47+
details.innerHTML = occurrences.map(item => {
48+
const link = escapeHtml(item.link);
49+
const context = item.context;
50+
return `
51+
<section>
52+
<p><a href="${link}" target="_blank" rel="noopener noreferrer">View on GOV.UK</a></p>
53+
<p>${context}</p>
54+
</section>
55+
`;
56+
}).join('');
3057
}
3158

3259
async function loadGraph() {
@@ -104,12 +131,13 @@ <h2></h2>
104131
});
105132

106133
cy.on('tap', 'node', (event) => {
107-
details.textContent = formatNodeData(event.target);
134+
renderNodeDetails(event.target);
108135
});
109136

110137
cy.on('tap', (event) => {
111138
if (event.target === cy) {
112-
details.textContent = 'No node selected.';
139+
sidebarTitle.textContent = 'No node selected';
140+
details.innerHTML = '<p>Select a node to view details.</p>';
113141
}
114142
});
115143
} catch (error) {

0 commit comments

Comments
 (0)