fix: make model-card click reliable and remove Tailwind CDN warning

- Use encoded model key in data attribute to avoid lookup mismatch
- Decode key on click before resolving showByModel data
- Guard localStorage writes with try/catch to avoid silent UI failures
- Scroll details section into view when a card is clicked
- Remove tailwindcdn script from template (use compiled CSS only)
This commit is contained in:
Luca Sacchi Ricciardi
2026-04-24 20:04:06 +02:00
parent 57663400ce
commit 0789e5b8e9
2 changed files with 19 additions and 7 deletions
+17 -3
View File
@@ -39,11 +39,15 @@ class LLMMonitorApp {
// Listener click card modello // Listener click card modello
document.getElementById("models-container")?.addEventListener("click", (event) => { document.getElementById("models-container")?.addEventListener("click", (event) => {
const card = event.target.closest("[data-model-name]"); const card = event.target.closest("[data-model-key]");
if (!card) { if (!card) {
return; return;
} }
this.showModelDetails(card.getAttribute("data-model-name")); const modelKey = card.getAttribute("data-model-key");
if (!modelKey) {
return;
}
this.showModelDetails(decodeURIComponent(modelKey));
}); });
} }
@@ -78,13 +82,21 @@ class LLMMonitorApp {
if (type === "DATA_UPDATED") { if (type === "DATA_UPDATED") {
if (health && JSON.stringify(this.lastData.health) !== JSON.stringify(health)) { if (health && JSON.stringify(this.lastData.health) !== JSON.stringify(health)) {
this.lastData.health = health; this.lastData.health = health;
try {
localStorage.setItem("llm_monitor_health", JSON.stringify(health)); localStorage.setItem("llm_monitor_health", JSON.stringify(health));
} catch (error) {
console.warn("Cannot persist health in localStorage:", error);
}
this.renderHealth(health); this.renderHealth(health);
} }
if (modelsData && JSON.stringify(this.lastData.models) !== JSON.stringify(modelsData)) { if (modelsData && JSON.stringify(this.lastData.models) !== JSON.stringify(modelsData)) {
this.lastData.models = modelsData; this.lastData.models = modelsData;
try {
localStorage.setItem("llm_monitor_models", JSON.stringify(modelsData)); localStorage.setItem("llm_monitor_models", JSON.stringify(modelsData));
} catch (error) {
console.warn("Cannot persist models in localStorage:", error);
}
this.renderModels(modelsData); this.renderModels(modelsData);
if (this.selectedModelName) { if (this.selectedModelName) {
this.showModelDetails(this.selectedModelName); this.showModelDetails(this.selectedModelName);
@@ -156,8 +168,9 @@ class LLMMonitorApp {
renderModelCard(model) { renderModelCard(model) {
const formattedDate = this.formatDate(model.modified_at); const formattedDate = this.formatDate(model.modified_at);
const modelName = this.escapeHtml(model.name); const modelName = this.escapeHtml(model.name);
const modelKey = encodeURIComponent(model.name);
return ` return `
<div data-model-name="${modelName}" class="bg-gray-700 rounded-lg p-4 border border-gray-600 hover:border-purple-500 transition cursor-pointer"> <div data-model-key="${modelKey}" class="bg-gray-700 rounded-lg p-4 border border-gray-600 hover:border-purple-500 transition cursor-pointer">
<div class="flex items-start justify-between mb-3"> <div class="flex items-start justify-between mb-3">
<h3 class="text-lg font-semibold">${modelName}</h3> <h3 class="text-lg font-semibold">${modelName}</h3>
<span class="bg-purple-600 px-3 py-1 rounded text-xs font-medium">Caricato</span> <span class="bg-purple-600 px-3 py-1 rounded text-xs font-medium">Caricato</span>
@@ -196,6 +209,7 @@ class LLMMonitorApp {
detailsSection.classList.remove("hidden"); detailsSection.classList.remove("hidden");
detailsName.textContent = modelName; detailsName.textContent = modelName;
detailsSection.scrollIntoView({ behavior: "smooth", block: "start" });
if (!showData) { if (!showData) {
detailsContent.textContent = "Dettagli show non disponibili per questo modello."; detailsContent.textContent = "Dettagli show non disponibili per questo modello.";
-2
View File
@@ -7,8 +7,6 @@
<link rel="icon" href="/favicon.ico" sizes="any"> <link rel="icon" href="/favicon.ico" sizes="any">
<!-- Tailwind CSS (compiled for production) --> <!-- Tailwind CSS (compiled for production) -->
<link rel="stylesheet" href="/static/css/output.css"> <link rel="stylesheet" href="/static/css/output.css">
<!-- Fallback CDN for development (if output.css not available) -->
<script src="https://cdn.tailwindcss.com"></script>
<style> <style>
@keyframes spin { @keyframes spin {
to { transform: rotate(360deg); } to { transform: rotate(360deg); }