Skip to content

Commit 8d02c9a

Browse files
committed
fix ui filter for namespace
1 parent af78266 commit 8d02c9a

File tree

2 files changed

+267
-1
lines changed

2 files changed

+267
-1
lines changed

docs/enhanced_index.html

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,20 @@ <h2>Code Statistics</h2>
483483
</div>
484484

485485
<div class="sidebar-section" id="filters-container">
486-
<h2>Filters</h2>
486+
<h2>Filters <button id="reset-filters" class="small-button"><i class="fas fa-undo"></i> Reset</button></h2>
487+
488+
<!-- Namespace filters (dynamically populated) -->
489+
<div class="filter-group">
490+
<h4>Namespaces</h4>
491+
<div id="namespace-filters" class="filter-group-content">
492+
<!-- Will be populated dynamically -->
493+
<div class="loading-placeholder">Loading namespaces...</div>
494+
</div>
495+
</div>
496+
497+
<!-- Node type filters -->
487498
<div class="filter-group">
499+
<h4>Node Types</h4>
488500
<label>
489501
<input type="checkbox" class="node-filter" value="namespace" checked>
490502
<span class="color-indicator" style="background-color: var(--namespace-color)"></span>

docs/enhanced_visualizer.js

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,9 @@ document.addEventListener('DOMContentLoaded', function() {
717717
const nodeTypes = Array.from(document.querySelectorAll('.node-filter:checked')).map(el => el.value);
718718
const linkTypes = Array.from(document.querySelectorAll('.link-filter:checked')).map(el => el.value);
719719

720+
// Get namespace filters
721+
const namespaceFilters = Array.from(document.querySelectorAll('.namespace-filter:checked')).map(el => el.value);
722+
720723
// Get usage filters (used/unused)
721724
const showUsed = document.getElementById('filter-used')?.checked ?? true;
722725
const showUnused = document.getElementById('filter-unused')?.checked ?? true;
@@ -728,10 +731,29 @@ document.addEventListener('DOMContentLoaded', function() {
728731
console.log("Active filters:", {
729732
nodeTypes,
730733
linkTypes,
734+
namespaces: namespaceFilters,
731735
usage: { showUsed, showUnused },
732736
origin: { showInternal, showExternal }
733737
});
734738

739+
// Helper function to check if a node belongs to a namespace
740+
const nodeInFilteredNamespace = (nodeId) => {
741+
// If no namespace filters are selected, show all nodes
742+
if (namespaceFilters.length === 0) return true;
743+
744+
// For namespace nodes, check direct match
745+
const node = graph.nodes.find(n => n.id === nodeId);
746+
if (node && node.group === 'namespace') {
747+
return namespaceFilters.some(ns => ns === nodeId);
748+
}
749+
750+
// For other nodes, check if they belong to any of the filtered namespaces
751+
return namespaceFilters.some(namespace => {
752+
// Check if the node ID starts with the namespace followed by a dot
753+
return nodeId === namespace || nodeId.startsWith(namespace + '.');
754+
});
755+
};
756+
735757
// Apply node filters
736758
gContainer.selectAll('.node').each(function(d) {
737759
const node = d3.select(this);
@@ -742,6 +764,11 @@ document.addEventListener('DOMContentLoaded', function() {
742764
visible = false;
743765
}
744766

767+
// Check namespace filter
768+
if (visible && !nodeInFilteredNamespace(d.id)) {
769+
visible = false;
770+
}
771+
745772
// Check usage filter
746773
if (visible) {
747774
if (d.used && !showUsed) visible = false;
@@ -1116,6 +1143,130 @@ document.addEventListener('DOMContentLoaded', function() {
11161143
d3.select(event.currentTarget).classed('hover', false);
11171144
}
11181145

1146+
// Initialize filters based on the graph data
1147+
function initializeFilters() {
1148+
console.log("Initializing filters...");
1149+
1150+
// Extract all namespaces from the graph
1151+
const namespaces = new Set();
1152+
1153+
// Extract namespace from node IDs
1154+
graph.nodes.forEach(node => {
1155+
if (node.group === 'namespace') {
1156+
namespaces.add(node.id);
1157+
} else {
1158+
// For non-namespace nodes, extract the namespace part
1159+
const parts = node.id.split('.');
1160+
if (parts.length > 1) {
1161+
// Find the namespace by looking at the first part(s) of the ID
1162+
// We consider everything before the last part as potentially part of the namespace
1163+
const potentialNamespace = parts.slice(0, -1).join('.');
1164+
1165+
// Check if this potential namespace exists as a node
1166+
const namespaceNode = graph.nodes.find(n =>
1167+
n.group === 'namespace' && (n.id === potentialNamespace || potentialNamespace.startsWith(n.id + '.'))
1168+
);
1169+
1170+
if (namespaceNode) {
1171+
namespaces.add(namespaceNode.id);
1172+
}
1173+
}
1174+
}
1175+
});
1176+
1177+
// Sort namespaces alphabetically
1178+
const sortedNamespaces = Array.from(namespaces).sort();
1179+
1180+
console.log("Found namespaces:", sortedNamespaces);
1181+
1182+
// Generate namespace filter checkboxes
1183+
const namespaceFiltersContainer = document.getElementById('namespace-filters');
1184+
if (namespaceFiltersContainer) {
1185+
// Clear loading placeholder
1186+
namespaceFiltersContainer.innerHTML = '';
1187+
1188+
// Add "Select All" checkbox
1189+
const selectAllDiv = document.createElement('div');
1190+
selectAllDiv.className = 'filter-item select-all';
1191+
1192+
const selectAllLabel = document.createElement('label');
1193+
1194+
const selectAllCheckbox = document.createElement('input');
1195+
selectAllCheckbox.type = 'checkbox';
1196+
selectAllCheckbox.className = 'namespace-select-all';
1197+
selectAllCheckbox.checked = true;
1198+
1199+
const selectAllText = document.createElement('span');
1200+
selectAllText.textContent = 'Select All';
1201+
1202+
selectAllLabel.appendChild(selectAllCheckbox);
1203+
selectAllLabel.appendChild(selectAllText);
1204+
selectAllDiv.appendChild(selectAllLabel);
1205+
namespaceFiltersContainer.appendChild(selectAllDiv);
1206+
1207+
// Add individual namespace checkboxes
1208+
sortedNamespaces.forEach(namespace => {
1209+
const div = document.createElement('div');
1210+
div.className = 'filter-item';
1211+
1212+
const label = document.createElement('label');
1213+
1214+
const checkbox = document.createElement('input');
1215+
checkbox.type = 'checkbox';
1216+
checkbox.className = 'namespace-filter';
1217+
checkbox.value = namespace;
1218+
checkbox.checked = true;
1219+
checkbox.setAttribute('data-namespace', namespace);
1220+
1221+
// Extract the last part of the namespace for display
1222+
const displayName = namespace.split('.').pop();
1223+
1224+
const text = document.createElement('span');
1225+
text.textContent = displayName;
1226+
text.title = namespace; // Show full namespace on hover
1227+
1228+
label.appendChild(checkbox);
1229+
label.appendChild(text);
1230+
div.appendChild(label);
1231+
namespaceFiltersContainer.appendChild(div);
1232+
});
1233+
1234+
// Set up event listeners for namespace filters
1235+
document.querySelectorAll('.namespace-filter').forEach(filter => {
1236+
filter.addEventListener('change', () => {
1237+
console.log('Namespace filter changed:', filter.value, filter.checked);
1238+
applyFilters();
1239+
1240+
// Update the "Select All" checkbox state
1241+
updateSelectAllCheckbox();
1242+
});
1243+
});
1244+
1245+
// Set up the "Select All" checkbox event listener
1246+
document.querySelector('.namespace-select-all')?.addEventListener('change', function() {
1247+
const isChecked = this.checked;
1248+
document.querySelectorAll('.namespace-filter').forEach(checkbox => {
1249+
checkbox.checked = isChecked;
1250+
});
1251+
applyFilters();
1252+
});
1253+
}
1254+
}
1255+
1256+
// Update the "Select All" checkbox based on individual checkbox states
1257+
function updateSelectAllCheckbox() {
1258+
const selectAllCheckbox = document.querySelector('.namespace-select-all');
1259+
const namespaceCheckboxes = document.querySelectorAll('.namespace-filter');
1260+
1261+
if (selectAllCheckbox && namespaceCheckboxes.length > 0) {
1262+
const allChecked = Array.from(namespaceCheckboxes).every(checkbox => checkbox.checked);
1263+
const someChecked = Array.from(namespaceCheckboxes).some(checkbox => checkbox.checked);
1264+
1265+
selectAllCheckbox.checked = allChecked;
1266+
selectAllCheckbox.indeterminate = !allChecked && someChecked;
1267+
}
1268+
}
1269+
11191270
// Add CSS styles for proper visualization
11201271
function addStyles() {
11211272
const styleElement = document.createElement('style');
@@ -1234,13 +1385,63 @@ document.addEventListener('DOMContentLoaded', function() {
12341385
.unused {
12351386
color: var(--unused-color);
12361387
}
1388+
1389+
/* Namespace filter styles */
1390+
#namespace-filters {
1391+
max-height: 200px;
1392+
overflow-y: auto;
1393+
margin-bottom: 15px;
1394+
border: 1px solid #eee;
1395+
border-radius: 4px;
1396+
padding: 5px;
1397+
}
1398+
1399+
.loading-placeholder {
1400+
font-style: italic;
1401+
color: #999;
1402+
text-align: center;
1403+
padding: 10px;
1404+
}
1405+
1406+
.filter-item {
1407+
margin: 5px 0;
1408+
}
1409+
1410+
.filter-item label {
1411+
display: flex;
1412+
align-items: center;
1413+
}
1414+
1415+
.select-all {
1416+
font-weight: bold;
1417+
border-bottom: 1px solid #eee;
1418+
padding-bottom: 5px;
1419+
margin-bottom: 8px;
1420+
}
1421+
1422+
/* Reset button styling */
1423+
#reset-filters {
1424+
margin-left: 10px;
1425+
font-size: 0.7em;
1426+
padding: 3px 8px;
1427+
background: #f5f5f5;
1428+
border: 1px solid #ddd;
1429+
border-radius: 3px;
1430+
cursor: pointer;
1431+
transition: all 0.2s;
1432+
}
1433+
1434+
#reset-filters:hover {
1435+
background: #e0e0e0;
1436+
}
12371437
`;
12381438

12391439
document.head.appendChild(styleElement);
12401440
}
12411441

12421442
// Initialize the visualization
12431443
initVisualization();
1444+
initializeFilters();
12441445
addStyles();
12451446
});
12461447

@@ -1282,3 +1483,56 @@ document.addEventListener('DOMContentLoaded', function() {
12821483

12831484
console.log("Additional event listeners setup complete");
12841485
});
1486+
1487+
// Add event listener for reset filters button
1488+
document.addEventListener('DOMContentLoaded', function() {
1489+
console.log("Setting up reset filters button");
1490+
1491+
// Add reset filters functionality
1492+
document.getElementById('reset-filters')?.addEventListener('click', function() {
1493+
console.log("Reset filters button clicked");
1494+
resetAllFilters();
1495+
});
1496+
});
1497+
1498+
// Function to reset all filters to default state
1499+
function resetAllFilters() {
1500+
console.log("Resetting all filters to defaults");
1501+
1502+
// Reset node type filters
1503+
document.querySelectorAll('.node-filter').forEach(checkbox => {
1504+
checkbox.checked = true;
1505+
});
1506+
1507+
// Reset link type filters
1508+
document.querySelectorAll('.link-filter').forEach(checkbox => {
1509+
checkbox.checked = true;
1510+
});
1511+
1512+
// Reset namespace filters
1513+
document.querySelectorAll('.namespace-filter').forEach(checkbox => {
1514+
checkbox.checked = true;
1515+
});
1516+
1517+
// Reset "Select All" namespace checkbox
1518+
const selectAllCheckbox = document.querySelector('.namespace-select-all');
1519+
if (selectAllCheckbox) {
1520+
selectAllCheckbox.checked = true;
1521+
selectAllCheckbox.indeterminate = false;
1522+
}
1523+
1524+
// Reset usage filters
1525+
document.getElementById('filter-used').checked = true;
1526+
document.getElementById('filter-unused').checked = true;
1527+
1528+
// Reset library filters
1529+
document.getElementById('filter-internal').checked = true;
1530+
document.getElementById('filter-external').checked = true;
1531+
1532+
// Apply filter changes
1533+
if (typeof applyFilters === 'function') {
1534+
applyFilters();
1535+
}
1536+
1537+
console.log("All filters have been reset");
1538+
}

0 commit comments

Comments
 (0)