I am trying to add a status pane to my Panel web page which should show the status of the Python program which has been starting the server. I am starting the panel server from within my Python program like this:
server = pn.serve(
{"/": create_application},
port=args.web_port,
address=args.web_host,
show=not args.headless,
threaded=False, # access to the tornado server does not work with threaded=True
start=False,
admin=args.debug,
websocket_origin=[f"localhost:{args.web_port}",f"127.0.0.1:{args.web_port}"],
)
class PingHandler(RequestHandler):
def get(self):
self.write(b"pong")
server._tornado.add_handlers(r".*", [(r"/ping", PingHandler)])
server.start()
# with server start, the python process does not continue to run, we need to block the main thread
# and keep the server running
IOLoop.current().start()
Part of creating the app is this code:
status_pane = pn.pane.HTML("<div id='status-pane'><b>✅ Server connected</b></div>",
styles={"color": "green"},
sizing_mode="fixed",
name="Server Status")
JS_MONITOR_CODE = """
async function pingServer() {
const statusPane = document.getElementById("status-pane");
console.log("Status pane element in JS: ", statusPane);
if (!statusPane) {
console.error("Status pane element not found, stopping ping.");
if (window.pingIntervalId) {
clearInterval(window.pingIntervalId);
}
return;
}
try {
const res = await fetch("/ping");
if (!res.ok) throw new Error("Server responded with an error status.");
statusPane.innerHTML = "<b>✅ Server connected</b>";
statusPane.style.color = "green";
} catch (e) {
statusPane.innerHTML = "<b>❌ Server disconnected</b>";
statusPane.style.color = "red";
console.error("Ping failed:", e);
}
}
// Ensure the interval is started only once
if (!window.pingIntervalId) {
window.pingIntervalId = setInterval(pingServer, 2000);
console.log("JS: Ping interval started.");
pingServer(); // Initial call
}
"""
However, I could not find any way to inject that Javscript function into the page in a way that actually makes it work. If I just include the Javascript in a HTML pane, the getElementById never succeeds and always returns null.
I fear I am pretty ignorant when it comes to Javascript so I may be missing something trivial.
Is there a recommended/best way to make this work reliably?