feat: add module filter to tester UI and moduleName to ToolMetadata
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 26s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 26s
This commit is contained in:
@@ -112,6 +112,9 @@
|
||||
|
||||
<div class="flex gap-4 mb-6 mt-6">
|
||||
<input type="text" id="searchInput" placeholder="Search by tool name..." class="bg-[#18181b] border border-[#3f3f46] text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 outline-none" oninput="applyFilters()">
|
||||
<select id="moduleFilter" class="bg-[#18181b] border border-[#3f3f46] text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-48 p-2.5 outline-none" onchange="applyFilters()">
|
||||
<option value="">All Modules</option>
|
||||
</select>
|
||||
<select id="categoryFilter" class="bg-[#18181b] border border-[#3f3f46] text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-48 p-2.5 outline-none" onchange="applyFilters()">
|
||||
<option value="">All Categories</option>
|
||||
</select>
|
||||
@@ -151,6 +154,7 @@
|
||||
<table class="table" id="toolsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:10%">Module</th>
|
||||
<th style="width:10%">Category</th>
|
||||
<th style="width:25%">Tool Name</th>
|
||||
<th style="width:25%">Payload</th>
|
||||
@@ -285,6 +289,7 @@
|
||||
const savedPayloads = JSON.parse(localStorage.getItem('mcp_tester_payloads') || '{}');
|
||||
|
||||
const categories = new Set();
|
||||
const modules = new Set();
|
||||
allTools.forEach(t => {
|
||||
t._customPayload = savedPayloads[t.name] || null;
|
||||
t._lastStatus = 'NOT RUN';
|
||||
@@ -292,19 +297,26 @@
|
||||
t._latency = 0;
|
||||
t._responseData = null;
|
||||
categories.add(t.categoryKey || 'oth');
|
||||
if (t.moduleName) {
|
||||
modules.add(t.moduleName.replace('dap-was-', ''));
|
||||
}
|
||||
});
|
||||
|
||||
const catSelect = document.getElementById('categoryFilter');
|
||||
catSelect.innerHTML = '<option value="">All Categories</option>';
|
||||
Array.from(categories).sort().forEach(cat => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = cat;
|
||||
opt.textContent = cat.toUpperCase();
|
||||
catSelect.appendChild(opt);
|
||||
catSelect.innerHTML += `<option value="${cat}">${cat.toUpperCase()}</option>`;
|
||||
});
|
||||
|
||||
const modSelect = document.getElementById('moduleFilter');
|
||||
modSelect.innerHTML = '<option value="">All Modules</option>';
|
||||
Array.from(modules).sort().forEach(mod => {
|
||||
modSelect.innerHTML += `<option value="${mod}">${mod}</option>`;
|
||||
});
|
||||
|
||||
applyFilters();
|
||||
} catch (error) {
|
||||
document.getElementById('toolsTbody').innerHTML = '<tr><td colspan="5" class="text-center text-red-400 py-8">Failed to load tools.</td></tr>';
|
||||
document.getElementById('toolsTbody').innerHTML = '<tr><td colspan="6" class="text-center text-red-400 py-8">Failed to load tools.</td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,11 +353,14 @@
|
||||
function applyFilters() {
|
||||
const search = document.getElementById('searchInput').value.toLowerCase();
|
||||
const category = document.getElementById('categoryFilter').value;
|
||||
const moduleFlt = document.getElementById('moduleFilter').value;
|
||||
|
||||
filteredTools = allTools.filter(t => {
|
||||
const matchSearch = t.name.toLowerCase().includes(search) || (t.description || '').toLowerCase().includes(search);
|
||||
const matchCategory = !category || (t.categoryKey || 'oth') === category;
|
||||
return matchSearch && matchCategory;
|
||||
const toolMod = t.moduleName ? t.moduleName.replace('dap-was-', '') : '';
|
||||
const matchModule = !moduleFlt || toolMod === moduleFlt;
|
||||
return matchSearch && matchCategory && matchModule;
|
||||
});
|
||||
|
||||
document.getElementById('visibleCount').textContent = `(${filteredTools.length} tools)`;
|
||||
@@ -356,7 +371,7 @@
|
||||
function renderTable() {
|
||||
const tbody = document.getElementById('toolsTbody');
|
||||
if (filteredTools.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center text-zinc-500 py-8">No tools match the filter.</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-zinc-500 py-8">No tools match the filter.</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -380,6 +395,7 @@
|
||||
|
||||
html += `
|
||||
<tr id="row-${index}">
|
||||
<td><span class="cat-badge" style="background:rgba(59,130,246,0.1); color:#60a5fa; border:1px solid rgba(59,130,246,0.2);">${tool.moduleName ? tool.moduleName.replace('dap-was-', '') : 'unknown'}</span></td>
|
||||
<td><span class="cat-badge">${tool.categoryKey || 'oth'}</span></td>
|
||||
<td class="font-medium text-slate-200">${tool.name}</td>
|
||||
<td class="text-sm text-zinc-400 geist-mono flex items-center gap-3">
|
||||
|
||||
@@ -87,6 +87,9 @@ public class ToolRegistryHeartbeatSender {
|
||||
@Value("${axhub.tool.url:http://localhost:8080}")
|
||||
private String podUrl;
|
||||
|
||||
@Value("${spring.application.name:}")
|
||||
private String applicationName;
|
||||
|
||||
private List<ToolMetadata> registeredTools = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
@@ -136,6 +139,7 @@ public class ToolRegistryHeartbeatSender {
|
||||
meta.setIntegrationType("REST");
|
||||
meta.setMciServiceId(hintAnnotation != null ? hintAnnotation.mappingId() : "");
|
||||
meta.setPodUrl(podUrl);
|
||||
meta.setModuleName(applicationName);
|
||||
meta.setEndpoint(podUrl.replaceAll("/+$", "") + "/mcp/" + subToolName);
|
||||
|
||||
meta.setVisible(true);
|
||||
|
||||
@@ -64,6 +64,9 @@ public class ToolMetadata {
|
||||
// 2-1. 도메인 부서 그룹명 (category_key, 슬러그 형식)
|
||||
private String categoryKey;
|
||||
|
||||
// 2-1-1. 어플리케이션(모듈) 이름 (예: dap-was-cus)
|
||||
private String moduleName;
|
||||
|
||||
// 2-2. 툴 처리 엔드포인트 URI 경로 (예: /api/tool/customer-info)
|
||||
private String endpoint;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user