Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 50 additions & 7 deletions mcpgateway/static/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8718,6 +8718,7 @@ function showTab(tabName) {
{
method: "GET",
credentials: "same-origin",
cache: "no-store",
headers: {
Accept: "text/html",
},
Expand Down Expand Up @@ -25236,9 +25237,9 @@ function initializePluginFunctions() {
function updateBadgeHighlighting(type, value) {
// Define selectors for each type
const selectors = {
hook: "[onclick^='filterByHook']",
tag: "[onclick^='filterByTag']",
author: "[onclick^='filterByAuthor']",
hook: "[data-filter-hook]",
tag: "[data-filter-tag]",
author: "[data-filter-author]",
};

const selector = selectors[type];
Expand All @@ -25251,12 +25252,16 @@ function initializePluginFunctions() {

badges.forEach((badge) => {
// Check if this is the "All" badge (empty value)
const isAllBadge = badge.getAttribute("onclick").includes("('')");
const isAllBadge =
badge.dataset.filterHook === "" ||
badge.dataset.filterTag === "" ||
badge.dataset.filterAuthor === "";

// Check if this badge matches the selected value
const badgeValue = badge
.getAttribute("onclick")
.match(/'([^']*)'/)?.[1];
const badgeValue =
badge.dataset.filterHook ??
badge.dataset.filterTag ??
badge.dataset.filterAuthor;
const isSelected =
value === ""
? isAllBadge
Expand Down Expand Up @@ -25444,6 +25449,44 @@ function initializePluginFunctions() {
modal.classList.add("hidden");
}
};

// Single listener on the filter section β€” catches input/change from all child controls
const filtersSection = document.getElementById("plugin-filters");
if (filtersSection) {
filtersSection.addEventListener("input", () => window.filterPlugins());
filtersSection.addEventListener("change", () => window.filterPlugins());
}

// Single delegated click/keydown listener for badges, View Details, and modal close.
// Returns true if an action was dispatched, false otherwise.
function dispatchPluginAction(target) {
const hookEl = target.closest("[data-filter-hook]");
const tagEl = target.closest("[data-filter-tag]");
const authorEl = target.closest("[data-filter-author]");
const detailEl = target.closest("[data-show-plugin]");
const closeEl = target.closest("[data-close-plugin-modal]");

if (hookEl) window.filterByHook(hookEl.dataset.filterHook);
else if (tagEl) window.filterByTag(tagEl.dataset.filterTag);
else if (authorEl) window.filterByAuthor(authorEl.dataset.filterAuthor);
else if (detailEl) {
window.showPluginDetails(detailEl.dataset.showPlugin);
} else if (closeEl) window.closePluginDetails();
else return false;
return true;
}

const pluginsPanel = document.getElementById("plugins-panel");
if (pluginsPanel) {
pluginsPanel.addEventListener("click", (e) =>
dispatchPluginAction(e.target),
);
pluginsPanel.addEventListener("keydown", (e) => {
if (e.key !== "Enter" && e.key !== " ") return;
if (!dispatchPluginAction(e.target)) return;
e.preventDefault();
});
}
}

// Initialize plugin functions if plugins panel exists
Expand Down
26 changes: 10 additions & 16 deletions mcpgateway/templates/plugins_partial.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
<div class="space-y-2">
<div
class="flex justify-between items-center p-2 bg-indigo-50 rounded dark:bg-indigo-900/20 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-900/30 transition-colors border border-indigo-200 dark:border-indigo-800"
onclick="filterByHook('')" onkeydown="handleKeydown(event, () => filterByHook(''))" role="button" tabindex="0"
data-filter-hook="" role="button" tabindex="0"
>
<span
class="text-sm font-medium text-indigo-700 dark:text-indigo-300"
Expand All @@ -95,7 +95,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
{% for hook, count in stats.plugins_by_hook.items() %}
<div
class="flex justify-between items-center p-2 bg-gray-50 rounded dark:bg-gray-700 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600 transition-colors"
onclick="filterByHook({{ hook|tojson_attr }})" onkeydown="handleKeydown(event, () => filterByHook({{ hook|tojson_attr }}))" role="button" tabindex="0"
data-filter-hook="{{ hook }}" role="button" tabindex="0"
>
<span class="text-sm font-medium text-gray-700 dark:text-gray-300"
>{{ hook.replace('_', ' ').title() }}</span
Expand Down Expand Up @@ -131,7 +131,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
<div class="flex flex-wrap gap-2">
<span
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200 cursor-pointer hover:bg-indigo-200 dark:hover:bg-indigo-800 transition-colors border border-indigo-300 dark:border-indigo-700"
onclick="filterByTag('')" onkeydown="handleKeydown(event, () => filterByTag(''))" role="button" tabindex="0"
data-filter-tag="" role="button" tabindex="0"
>
All Tags
<span class="ml-1 text-xs text-indigo-600 dark:text-indigo-300"
Expand All @@ -141,7 +141,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
{% for tag, count in stats.plugins_by_tag.items() %}
<span
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200 cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
onclick="filterByTag({{ tag|tojson_attr }})" onkeydown="handleKeydown(event, () => filterByTag({{ tag|tojson_attr }}))" role="button" tabindex="0"
data-filter-tag="{{ tag }}" role="button" tabindex="0"
>
{{ tag }}
<span class="ml-1 text-xs text-gray-500 dark:text-gray-400"
Expand Down Expand Up @@ -173,7 +173,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
<div class="flex flex-wrap gap-2">
<span
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200 cursor-pointer hover:bg-indigo-200 dark:hover:bg-indigo-800 transition-colors border border-indigo-300 dark:border-indigo-700"
onclick="filterByAuthor('')" onkeydown="handleKeydown(event, () => filterByAuthor(''))" role="button" tabindex="0"
data-filter-author="" role="button" tabindex="0"
>
All Authors
<span class="ml-1 text-xs text-indigo-600 dark:text-indigo-300"
Expand All @@ -183,7 +183,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
{% for author, count in stats.plugins_by_author.items() %}
<span
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200 cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
onclick="filterByAuthor({{ author|tojson_attr }})" onkeydown="handleKeydown(event, () => filterByAuthor({{ author|tojson_attr }}))" role="button" tabindex="0"
data-filter-author="{{ author }}" role="button" tabindex="0"
>
{{ author }}
<span class="ml-1 text-xs text-gray-500 dark:text-gray-400"
Expand All @@ -196,21 +196,19 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
</div>

<!-- Search and Filter Controls -->
<div class="bg-white rounded-lg shadow p-4 dark:bg-gray-800">
<div id="plugin-filters" class="bg-white rounded-lg shadow p-4 dark:bg-gray-800">
<div class="flex flex-col md:flex-row gap-4">
<div class="flex-1">
<input
type="text"
id="plugin-search"
placeholder="Search plugins by name, description, or author..."
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
oninput="filterPlugins()"
/>
</div>
<div class="flex gap-2">
<select
id="plugin-mode-filter"
onchange="filterPlugins()"
class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">All Modes</option>
Expand All @@ -220,7 +218,6 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
</select>
<select
id="plugin-status-filter"
onchange="filterPlugins()"
class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">All Status</option>
Expand All @@ -229,21 +226,18 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
</select>
<select
id="plugin-hook-filter"
onchange="filterPlugins()"
class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">All Hooks</option>
</select>
<select
id="plugin-tag-filter"
onchange="filterPlugins()"
class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">All Tags</option>
</select>
<select
id="plugin-author-filter"
onchange="filterPlugins()"
class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
>
<option value="">All Authors</option>
Expand All @@ -263,7 +257,7 @@ <h3 class="text-lg font-medium mb-4 dark:text-gray-200 flex items-center">
data-name="{{ plugin.name | lower }}"
data-description="{{ plugin.description | decode_html | lower }}"
data-author="{{ plugin.author | lower }}"
data-mode="{{ plugin.mode }}"
data-mode="{{ plugin.mode | lower }}"
data-status="{{ plugin.status }}"
data-hooks="{{ plugin.hooks | join(',') if plugin.hooks else '' }}"
data-tags="{{ plugin.tags | join(',') if plugin.tags else '' }}"
Expand Down Expand Up @@ -378,7 +372,7 @@ <h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">

<!-- Action Button -->
<button
onclick="showPluginDetails({{ plugin.name|tojson_attr }})"
data-show-plugin="{{ plugin.name }}"
class="w-full mt-4 px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors"
>
View Details β†’
Expand Down Expand Up @@ -429,7 +423,7 @@ <h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-gray-100">
Plugin Details
</h3>
<button
onclick="closePluginDetails()"
data-close-plugin-modal
class="text-gray-400 hover:text-gray-500"
>
<svg
Expand Down
Loading
Loading