diff --git a/mcpgateway/static/admin.js b/mcpgateway/static/admin.js index c23050f22..29cce79e0 100644 --- a/mcpgateway/static/admin.js +++ b/mcpgateway/static/admin.js @@ -8166,7 +8166,13 @@ function setupSelectorSearch() { const searchTools = safeGetElement("searchTools", true); if (searchTools) { searchTools.addEventListener("input", function () { - filterItems(this.value, ".tool-item", ["span"]); + filterSelectorItems( + this.value, + "#associatedTools", + ".tool-item", + "noToolsMessage", + "searchQuery", + ); }); } @@ -8174,7 +8180,13 @@ function setupSelectorSearch() { const searchResources = safeGetElement("searchResources", true); if (searchResources) { searchResources.addEventListener("input", function () { - filterItems(this.value, ".resource-item", ["span", ".text-xs"]); + filterSelectorItems( + this.value, + "#associatedResources", + ".resource-item", + "noResourcesMessage", + "searchResourcesQuery", + ); }); } @@ -8182,37 +8194,115 @@ function setupSelectorSearch() { const searchPrompts = safeGetElement("searchPrompts", true); if (searchPrompts) { searchPrompts.addEventListener("input", function () { - filterItems(this.value, ".prompt-item", ["span", ".text-xs"]); + filterSelectorItems( + this.value, + "#associatedPrompts", + ".prompt-item", + "noPromptsMessage", + "searchPromptsQuery", + ); }); } } /** - * Generic function to filter items in multi-select dropdowns + * Generic function to filter items in multi-select dropdowns with no results message */ -function filterItems(searchText, itemSelector, textSelectors) { - const items = document.querySelectorAll(itemSelector); - const search = searchText.toLowerCase(); +function filterSelectorItems( + searchText, + containerSelector, + itemSelector, + noResultsId, + searchQueryId, +) { + const container = document.querySelector(containerSelector); + if (!container) { + return; + } + + const items = container.querySelectorAll(itemSelector); + const search = searchText.toLowerCase().trim(); + let hasVisibleItems = false; items.forEach((item) => { let textContent = ""; - // Collect text from all specified selectors within the item - textSelectors.forEach((selector) => { - const elements = item.querySelectorAll(selector); - elements.forEach((el) => { - textContent += " " + el.textContent; - }); + // Get text from all text nodes within the item + const textElements = item.querySelectorAll( + "span, .text-xs, .font-medium", + ); + textElements.forEach((el) => { + textContent += " " + el.textContent; }); - if (textContent.toLowerCase().includes(search)) { + // Also get direct text content + textContent += " " + item.textContent; + + if (search === "" || textContent.toLowerCase().includes(search)) { item.style.display = ""; + hasVisibleItems = true; } else { item.style.display = "none"; } }); + + // Handle no results message + const noResultsMessage = safeGetElement(noResultsId, true); + const searchQuerySpan = safeGetElement(searchQueryId, true); + + if (search !== "" && !hasVisibleItems) { + if (noResultsMessage) { + noResultsMessage.style.display = "block"; + } + if (searchQuerySpan) { + searchQuerySpan.textContent = searchText; + } + } else { + if (noResultsMessage) { + noResultsMessage.style.display = "none"; + } + } } +/** + * Filter server table rows based on search text + */ +function filterServerTable(searchText) { + try { + const tbody = document.querySelector( + 'tbody[data-testid="server-list"]', + ); + if (!tbody) { + console.warn("Server table not found"); + return; + } + + const rows = tbody.querySelectorAll('tr[data-testid="server-item"]'); + const search = searchText.toLowerCase().trim(); + + rows.forEach((row) => { + let textContent = ""; + + // Get text from all cells in the row + const cells = row.querySelectorAll("td"); + cells.forEach((cell) => { + textContent += " " + cell.textContent; + }); + + if (search === "" || textContent.toLowerCase().includes(search)) { + row.style.display = ""; + } else { + row.style.display = "none"; + } + }); + } catch (error) { + console.error("Error filtering server table:", error); + } +} + +// Make server search function available globally +window.filterServerTable = filterServerTable; + function handleAuthTypeChange() { const authType = this.value; const basicFields = safeGetElement("auth-basic-fields-gw"); diff --git a/mcpgateway/templates/admin.html b/mcpgateway/templates/admin.html index d1290998f..0d87ee00f 100644 --- a/mcpgateway/templates/admin.html +++ b/mcpgateway/templates/admin.html @@ -1081,9 +1081,11 @@

{% endfor %} +
{% endfor %} +

}); // Add search functionality for filtering tools - document.addEventListener('DOMContentLoaded', function() { - const searchBox = document.getElementById('searchTools'); - const toolItems = document.querySelectorAll('#associatedTools .tool-item'); - const noToolsMessage = document.getElementById('noToolsMessage'); - const searchQuerySpan = document.getElementById('searchQuery'); - - searchBox.addEventListener('input', function() { - const filter = this.value.toLowerCase(); - let hasVisibleItems = false; - - toolItems.forEach(function(toolItem) { - const toolName = toolItem.querySelector('span').textContent.toLowerCase(); - if (toolName.includes(filter)) { - toolItem.style.display = ''; - hasVisibleItems = true; - } else { - toolItem.style.display = 'none'; - } - }); - if (hasVisibleItems) { - noToolsMessage.style.display = 'none'; - } else { - searchQuerySpan.textContent = filter; - noToolsMessage.style.display = 'block'; - } - }); - });