Fix model details modal and make running models primary page
This commit is contained in:
+35
-56
@@ -39,62 +39,6 @@ class LLMMonitorApp {
|
|||||||
this.requestSync();
|
this.requestSync();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listener click card modello
|
|
||||||
document.getElementById("models-container")?.addEventListener("click", (event) => {
|
|
||||||
const card = event.target.closest("[data-model-key]");
|
|
||||||
if (!card) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const modelKey = card.getAttribute("data-model-key");
|
|
||||||
if (!modelKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.showModelDetails(decodeURIComponent(modelKey));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Apertura modal on-hover (con piccolo delay per evitare aperture involontarie)
|
|
||||||
document.getElementById("models-container")?.addEventListener("mouseover", (event) => {
|
|
||||||
const card = event.target.closest("[data-model-key]");
|
|
||||||
if (!card) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evita trigger quando il mouse si muove dentro la stessa card
|
|
||||||
if (event.relatedTarget && card.contains(event.relatedTarget)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const modelKey = card.getAttribute("data-model-key");
|
|
||||||
if (!modelKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hoverOpenTimer) {
|
|
||||||
clearTimeout(this.hoverOpenTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hoverOpenTimer = setTimeout(() => {
|
|
||||||
this.showModelDetails(decodeURIComponent(modelKey));
|
|
||||||
}, this.hoverOpenDelayMs);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("models-container")?.addEventListener("mouseout", (event) => {
|
|
||||||
const card = event.target.closest("[data-model-key]");
|
|
||||||
if (!card) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non cancellare se si resta all'interno della stessa card
|
|
||||||
if (event.relatedTarget && card.contains(event.relatedTarget)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hoverOpenTimer) {
|
|
||||||
clearTimeout(this.hoverOpenTimer);
|
|
||||||
this.hoverOpenTimer = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Chiusura modal con pulsante X
|
// Chiusura modal con pulsante X
|
||||||
document.getElementById("model-details-close")?.addEventListener("click", () => {
|
document.getElementById("model-details-close")?.addEventListener("click", () => {
|
||||||
this.hideModelDetails();
|
this.hideModelDetails();
|
||||||
@@ -223,9 +167,44 @@ class LLMMonitorApp {
|
|||||||
// Aggiornare solo se veramente diverso
|
// Aggiornare solo se veramente diverso
|
||||||
if (container.innerHTML !== newHTML) {
|
if (container.innerHTML !== newHTML) {
|
||||||
container.innerHTML = newHTML;
|
container.innerHTML = newHTML;
|
||||||
|
this.bindModelCardInteractions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Associare eventi card dopo ogni render (piu affidabile della delega su hover)
|
||||||
|
bindModelCardInteractions() {
|
||||||
|
const cards = document.querySelectorAll("#models-container [data-model-key]");
|
||||||
|
cards.forEach((card) => {
|
||||||
|
const modelKey = card.getAttribute("data-model-key");
|
||||||
|
if (!modelKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelName = decodeURIComponent(modelKey);
|
||||||
|
|
||||||
|
card.addEventListener("click", () => {
|
||||||
|
this.showModelDetails(modelName);
|
||||||
|
});
|
||||||
|
|
||||||
|
card.addEventListener("mouseenter", () => {
|
||||||
|
if (this.hoverOpenTimer) {
|
||||||
|
clearTimeout(this.hoverOpenTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hoverOpenTimer = setTimeout(() => {
|
||||||
|
this.showModelDetails(modelName);
|
||||||
|
}, this.hoverOpenDelayMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
card.addEventListener("mouseleave", () => {
|
||||||
|
if (this.hoverOpenTimer) {
|
||||||
|
clearTimeout(this.hoverOpenTimer);
|
||||||
|
this.hoverOpenTimer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Renderizzare singola card modello
|
// Renderizzare singola card modello
|
||||||
renderModelCard(model) {
|
renderModelCard(model) {
|
||||||
const formattedDate = this.formatDate(model.modified_at);
|
const formattedDate = this.formatDate(model.modified_at);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<a href="/dashboard" class="text-sm bg-gray-700 hover:bg-gray-600 px-3 py-2 rounded-lg transition">Dashboard</a>
|
<a href="/models-available" class="text-sm bg-gray-700 hover:bg-gray-600 px-3 py-2 rounded-lg transition">Modelli Disponibili</a>
|
||||||
<button id="refresh-btn" class="text-sm bg-purple-600 hover:bg-purple-700 px-3 py-2 rounded-lg transition">Aggiorna</button>
|
<button id="refresh-btn" class="text-sm bg-purple-600 hover:bg-purple-700 px-3 py-2 rounded-lg transition">Aggiorna</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -53,12 +53,18 @@ templates_path = Path(__file__).parent / "app" / "web" / "templates"
|
|||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
async def root():
|
async def root():
|
||||||
"""Redirect alla dashboard"""
|
"""Pagina principale: modelli residenti in memoria (ollama ps)."""
|
||||||
return FileResponse(templates_path / "index.html")
|
return FileResponse(templates_path / "models_running.html")
|
||||||
|
|
||||||
@app.get("/dashboard")
|
@app.get("/dashboard")
|
||||||
async def dashboard():
|
async def dashboard():
|
||||||
"""Dashboard principale"""
|
"""Alias legacy della pagina principale."""
|
||||||
|
return FileResponse(templates_path / "models_running.html")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/models-available")
|
||||||
|
async def models_available_page():
|
||||||
|
"""Pagina modelli disponibili su disco."""
|
||||||
return FileResponse(templates_path / "index.html")
|
return FileResponse(templates_path / "index.html")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user