mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-22 13:34:17 +02:00
fix: dev apps log panel UX improvements (#3698)
This commit is contained in:
parent
9b89eb192d
commit
dd7d89aaae
1 changed files with 70 additions and 4 deletions
|
|
@ -597,6 +597,33 @@ _LOG_PANEL_HTML = """\
|
|||
var countEl = document.getElementById("mcp-log-count");
|
||||
var openBtn = document.getElementById("mcp-log-open");
|
||||
var resizeHandle = document.getElementById("mcp-log-resize");
|
||||
var allFilterKeys = ["tools", "notifications", "bridge", "errors"];
|
||||
|
||||
function syncURL() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
if (!panel.classList.contains("hidden")) {
|
||||
params.set("log", "open");
|
||||
} else {
|
||||
params.delete("log");
|
||||
}
|
||||
var on = [];
|
||||
for (var i = 0; i < allFilterKeys.length; i++) {
|
||||
if (activeFilters[allFilterKeys[i]]) on.push(allFilterKeys[i]);
|
||||
}
|
||||
if (on.length === allFilterKeys.length) {
|
||||
params.delete("filters");
|
||||
} else {
|
||||
params.set("filters", on.join(","));
|
||||
}
|
||||
if (minLevel === 0) {
|
||||
params.delete("level");
|
||||
} else {
|
||||
params.set("level", levelOrder[minLevel]);
|
||||
}
|
||||
var qs = params.toString();
|
||||
var url = window.location.pathname + (qs ? "?" + qs : "");
|
||||
history.replaceState(null, "", url);
|
||||
}
|
||||
|
||||
function setFrameLayout(w) {
|
||||
var frame = document.getElementById("app-frame");
|
||||
|
|
@ -609,12 +636,15 @@ _LOG_PANEL_HTML = """\
|
|||
panel.classList.add("hidden");
|
||||
openBtn.style.display = "block";
|
||||
setFrameLayout("100%");
|
||||
syncURL();
|
||||
});
|
||||
|
||||
openBtn.addEventListener("click", function() {
|
||||
panel.classList.remove("hidden");
|
||||
openBtn.style.display = "none";
|
||||
setFrameLayout("calc(100% - " + panelWidth + "px)");
|
||||
entries.scrollTop = entries.scrollHeight;
|
||||
syncURL();
|
||||
});
|
||||
|
||||
resizeHandle.addEventListener("mousedown", function(e) {
|
||||
|
|
@ -652,6 +682,34 @@ _LOG_PANEL_HTML = """\
|
|||
var levelOrder = ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"];
|
||||
var minLevel = 0;
|
||||
|
||||
// Restore state from URL params
|
||||
(function restoreURL() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
if (params.get("log") === "open") {
|
||||
panel.classList.remove("hidden");
|
||||
openBtn.style.display = "none";
|
||||
setFrameLayout("calc(100% - " + panelWidth + "px)");
|
||||
}
|
||||
var fp = params.get("filters");
|
||||
if (fp !== null) {
|
||||
var on = fp ? fp.split(",") : [];
|
||||
for (var i = 0; i < allFilterKeys.length; i++) {
|
||||
var k = allFilterKeys[i];
|
||||
activeFilters[k] = on.indexOf(k) !== -1;
|
||||
var btn = document.querySelector("[data-filter='" + k + "']");
|
||||
if (btn) btn.classList.toggle("active", activeFilters[k]);
|
||||
}
|
||||
}
|
||||
var lp = params.get("level");
|
||||
if (lp) {
|
||||
var idx = levelOrder.indexOf(lp);
|
||||
if (idx >= 0) {
|
||||
minLevel = idx;
|
||||
document.getElementById("mcp-log-level-select").value = lp;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
document.getElementById("mcp-log-filters").addEventListener("click", function(e) {
|
||||
var btn = e.target.closest("[data-filter]");
|
||||
if (!btn) return;
|
||||
|
|
@ -659,11 +717,13 @@ _LOG_PANEL_HTML = """\
|
|||
activeFilters[f] = !activeFilters[f];
|
||||
btn.classList.toggle("active", activeFilters[f]);
|
||||
applyFilters();
|
||||
syncURL();
|
||||
});
|
||||
|
||||
document.getElementById("mcp-log-level-select").addEventListener("change", function(e) {
|
||||
minLevel = levelOrder.indexOf(e.target.value);
|
||||
applyFilters();
|
||||
syncURL();
|
||||
});
|
||||
|
||||
function shouldShow(el) {
|
||||
|
|
@ -799,6 +859,7 @@ _LOG_PANEL_HTML = """\
|
|||
}
|
||||
|
||||
var polling = false;
|
||||
var firstPoll = true;
|
||||
function poll() {
|
||||
if (polling) return;
|
||||
polling = true;
|
||||
|
|
@ -809,14 +870,16 @@ _LOG_PANEL_HTML = """\
|
|||
lastId = data[data.length - 1].id;
|
||||
totalCount += data.length;
|
||||
countEl.textContent = String(totalCount);
|
||||
var atBottom = entries.scrollHeight - entries.scrollTop - entries.clientHeight < 40;
|
||||
var panelVisible = !panel.classList.contains("hidden");
|
||||
var atBottom = !panelVisible || entries.scrollHeight - entries.scrollTop - entries.clientHeight < 40;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var el = renderEntry(data[i]);
|
||||
el.classList.add("new");
|
||||
if (!shouldShow(el)) el.style.display = "none";
|
||||
entries.appendChild(el);
|
||||
}
|
||||
if (atBottom) entries.scrollTop = entries.scrollHeight;
|
||||
if (atBottom || (firstPoll && panelVisible)) entries.scrollTop = entries.scrollHeight;
|
||||
firstPoll = false;
|
||||
})
|
||||
.catch(function() {})
|
||||
.finally(function() { polling = false; });
|
||||
|
|
@ -1635,7 +1698,10 @@ async def run_dev_apps(
|
|||
# Check ports before starting anything
|
||||
import socket
|
||||
|
||||
for port, label in [(mcp_port, "MCP server"), (dev_port, "dev UI")]:
|
||||
for port, label, flag in [
|
||||
(mcp_port, "MCP server", "--mcp-port"),
|
||||
(dev_port, "dev UI", "--dev-port"),
|
||||
]:
|
||||
in_use = False
|
||||
for family, addr in (
|
||||
(socket.AF_INET, ("127.0.0.1", port)),
|
||||
|
|
@ -1651,7 +1717,7 @@ async def run_dev_apps(
|
|||
if in_use:
|
||||
logger.error(
|
||||
f"Port {port} ({label}) is already in use. "
|
||||
f"Try --mcp-port or --dev-port to use different ports."
|
||||
f"Try {flag} to use a different port."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue