feat: Cookbook Search Results UI & Lazy Metrics
This commit is contained in:
@@ -229,15 +229,69 @@ function renderResults(results) {
|
||||
|
||||
grid.innerHTML = results.map((m, i) => `
|
||||
<div class="card" style="display:flex; flex-direction:column; cursor:pointer" onclick="window.openModelModal(${i})">
|
||||
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:8px;">
|
||||
<div>
|
||||
<h3 style="margin:0; font-size:16px; word-break:break-all">${esc(m.id.split('/').pop())}</h3>
|
||||
<div class="meta" style="font-size:12px; margin-top:4px">${esc(m.author)}</div>
|
||||
</div>
|
||||
<span id="cb-s-badge-${i}" class="badge b-load" style="white-space:nowrap;">Analysiere...</span>
|
||||
</div>
|
||||
<div style="flex:1; margin-top:16px;"></div>
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:16px">
|
||||
<span class="badge b-idle" style="font-size:11px">GGUF</span>
|
||||
<span class="meta" style="font-size:12px">⬇ ${(m.downloads||0).toLocaleString()}</span>
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:16px; font-size:12px" class="meta">
|
||||
<span id="cb-s-metrics-${i}">Berechne Hardware-Fit...</span>
|
||||
<span style="display:flex; gap:8px; align-items:center">
|
||||
<span>⬇ ${(m.downloads||0).toLocaleString()}</span>
|
||||
<span id="cb-s-quant-${i}" class="badge b-idle" style="font-size:11px">GGUF</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`).join("");
|
||||
|
||||
// Lade Metriken im Hintergrund
|
||||
results.forEach((m, i) => fetchAnalysisForCard(i, m.id));
|
||||
}
|
||||
|
||||
async function fetchAnalysisForCard(index, repo_id) {
|
||||
try {
|
||||
const res = await api("/api/cookbook/analyze", {
|
||||
method: "POST", body: JSON.stringify({ repo_id, ctx: 8192 })
|
||||
});
|
||||
|
||||
const badgeEl = document.getElementById(`cb-s-badge-${index}`);
|
||||
const metricsEl = document.getElementById(`cb-s-metrics-${index}`);
|
||||
const quantEl = document.getElementById(`cb-s-quant-${index}`);
|
||||
|
||||
if (!badgeEl || !metricsEl || !quantEl) return; // card might be gone
|
||||
|
||||
if (!res.files || res.files.length === 0) {
|
||||
badgeEl.className = "badge b-err";
|
||||
badgeEl.textContent = "Keine GGUFs";
|
||||
metricsEl.textContent = "Keine Dateien gefunden";
|
||||
return;
|
||||
}
|
||||
|
||||
let best = res.files.find(f => f.quant && f.quant.includes("Q4_K_M"));
|
||||
if (!best) best = res.files[0];
|
||||
|
||||
const fit = best.fit;
|
||||
const cls = fit.level === "perfect" ? "b-run" : (fit.level === "marginal" ? "b-load" : "b-err");
|
||||
|
||||
badgeEl.className = `badge ${cls}`;
|
||||
badgeEl.textContent = fit.text;
|
||||
metricsEl.innerHTML = `~${fit.req_gb.toFixed(1)} GB RAM/VRAM · ~${Math.round(fit.tps)} t/s`;
|
||||
quantEl.textContent = best.quant || "GGUF";
|
||||
|
||||
} catch(e) {
|
||||
const badgeEl = document.getElementById(`cb-s-badge-${index}`);
|
||||
const metricsEl = document.getElementById(`cb-s-metrics-${index}`);
|
||||
if (badgeEl) {
|
||||
badgeEl.className = "badge b-err";
|
||||
badgeEl.textContent = "Fehler";
|
||||
}
|
||||
if (metricsEl) {
|
||||
metricsEl.textContent = "Metriken konnten nicht geladen werden";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Global hook for inline onclick
|
||||
|
||||
Reference in New Issue
Block a user