Add service grouping feature to README and implement dynamic rendering in index.html
This commit is contained in:
83
index.html
83
index.html
@@ -16,8 +16,8 @@
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="grid" id="services-grid">
|
||||
<!-- Services will be populated dynamically from /services.xml -->
|
||||
<section id="services-container">
|
||||
<!-- Service groups will be populated dynamically from /services.xml -->
|
||||
</section>
|
||||
|
||||
<section class="notes">
|
||||
@@ -35,7 +35,7 @@
|
||||
<script>
|
||||
// Fetch services.xml and render the service cards with logos.
|
||||
(async function(){
|
||||
const grid = document.getElementById('services-grid');
|
||||
const container = document.getElementById('services-container');
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const host = window.location.hostname;
|
||||
let allServices = []; // Store all service elements for filtering
|
||||
@@ -46,9 +46,61 @@
|
||||
const text = await res.text();
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(text, 'application/xml');
|
||||
const services = Array.from(doc.getElementsByTagName('service'));
|
||||
if(services.length===0){ grid.innerHTML = '<p class="notes">No services found in services.xml</p>'; return; }
|
||||
services.forEach(s=>{
|
||||
|
||||
// Check if we have groups or just services
|
||||
const groups = Array.from(doc.getElementsByTagName('group'));
|
||||
const hasGroups = groups.length > 0;
|
||||
|
||||
if(hasGroups){
|
||||
// Render grouped services
|
||||
groups.forEach(group => {
|
||||
const groupName = group.getAttribute('name') || 'Services';
|
||||
const services = Array.from(group.getElementsByTagName('service'));
|
||||
|
||||
if(services.length === 0) return;
|
||||
|
||||
// Create group section
|
||||
const groupSection = document.createElement('section');
|
||||
groupSection.className = 'service-group';
|
||||
|
||||
const groupHeader = document.createElement('h2');
|
||||
groupHeader.className = 'group-header';
|
||||
groupHeader.textContent = groupName;
|
||||
groupSection.appendChild(groupHeader);
|
||||
|
||||
const grid = document.createElement('div');
|
||||
grid.className = 'grid';
|
||||
|
||||
services.forEach(s => {
|
||||
const card = createServiceCard(s, host, allServices);
|
||||
grid.appendChild(card);
|
||||
});
|
||||
|
||||
groupSection.appendChild(grid);
|
||||
container.appendChild(groupSection);
|
||||
});
|
||||
} else {
|
||||
// Fallback: render ungrouped services
|
||||
const services = Array.from(doc.getElementsByTagName('service'));
|
||||
if(services.length === 0){
|
||||
container.innerHTML = '<p class="notes">No services found in services.xml</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
const grid = document.createElement('div');
|
||||
grid.className = 'grid';
|
||||
grid.id = 'services-grid';
|
||||
|
||||
services.forEach(s => {
|
||||
const card = createServiceCard(s, host, allServices);
|
||||
grid.appendChild(card);
|
||||
});
|
||||
|
||||
container.appendChild(grid);
|
||||
}
|
||||
|
||||
// Function to create a service card
|
||||
function createServiceCard(s, host, allServices) {
|
||||
const name = s.getAttribute('name') || s.getAttribute('id') || 'unknown';
|
||||
const proto = s.getAttribute('proto') || 'http';
|
||||
const port = s.getAttribute('port') || '';
|
||||
@@ -170,14 +222,18 @@
|
||||
a.appendChild(infoBtn);
|
||||
}
|
||||
|
||||
grid.appendChild(a);
|
||||
allServices.push(a);
|
||||
});
|
||||
return a;
|
||||
}
|
||||
|
||||
// Search functionality
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const searchTerm = e.target.value.toLowerCase().trim();
|
||||
let visibleCount = 0;
|
||||
|
||||
// Also hide/show group headers
|
||||
const groupSections = container.querySelectorAll('.service-group');
|
||||
|
||||
allServices.forEach(card => {
|
||||
const serviceName = card.dataset.serviceName;
|
||||
if(serviceName.includes(searchTerm)){
|
||||
@@ -187,14 +243,21 @@
|
||||
card.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Hide empty groups
|
||||
groupSections.forEach(section => {
|
||||
const visibleCards = section.querySelectorAll('.card:not([style*="display: none"])');
|
||||
section.style.display = visibleCards.length > 0 ? '' : 'none';
|
||||
});
|
||||
|
||||
// Show message if no results
|
||||
const existingMsg = grid.querySelector('.no-results');
|
||||
const existingMsg = container.querySelector('.no-results');
|
||||
if(existingMsg) existingMsg.remove();
|
||||
if(visibleCount === 0 && searchTerm !== ''){
|
||||
const msg = document.createElement('p');
|
||||
msg.className = 'notes no-results';
|
||||
msg.textContent = `No services found matching "${e.target.value}"`;
|
||||
grid.appendChild(msg);
|
||||
container.appendChild(msg);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user