Spaces:
Sleeping
Sleeping
| /** | |
| * ClauseGuard — Popup Script v4.3 | |
| * Shows user status (logged in / guest), scan results, usage. | |
| * | |
| * FIXED v4.3: sidePanel.open() is properly awaited. | |
| * FIXED v4.3: CRITICAL severity is now counted and displayed. | |
| * FIXED v4.3: Shows scan source ("Legal-BERT" / "Local") accurately. | |
| */ | |
| document.addEventListener("DOMContentLoaded", async () => { | |
| const resultsView = document.getElementById("results-view"); | |
| const emptyView = document.getElementById("empty-view"); | |
| const limitBanner = document.getElementById("limit-banner"); | |
| const userBar = document.getElementById("user-bar"); | |
| const userEmail = document.getElementById("user-email"); | |
| const userPlan = document.getElementById("user-plan"); | |
| const guestBar = document.getElementById("guest-bar"); | |
| let tab; | |
| try { const [t] = await chrome.tabs.query({ active: true, currentWindow: true }); tab = t; } catch { return; } | |
| if (!tab?.id) return; | |
| // Load user info | |
| let auth = null; | |
| try { auth = await chrome.runtime.sendMessage({ type: "GET_USER" }); } catch {} | |
| if (auth?.isLoggedIn) { | |
| if (userBar) userBar.style.display = "flex"; | |
| if (guestBar) guestBar.style.display = "none"; | |
| if (userEmail) userEmail.textContent = auth.email || "User"; | |
| if (userPlan) { | |
| userPlan.textContent = auth.plan?.toUpperCase() || "FREE"; | |
| userPlan.className = "plan-badge plan-" + (auth.plan || "free"); | |
| } | |
| } else { | |
| if (userBar) userBar.style.display = "none"; | |
| if (guestBar) guestBar.style.display = "flex"; | |
| } | |
| // Check usage | |
| let usage = null; | |
| try { usage = await chrome.runtime.sendMessage({ type: "CHECK_USAGE" }); } catch {} | |
| updateUsage(usage); | |
| if (usage && !usage.allowed && limitBanner) limitBanner.style.display = "block"; | |
| // Load results | |
| let results = null; | |
| try { results = await chrome.runtime.sendMessage({ type: "GET_RESULTS", tabId: tab.id }); } catch {} | |
| if (results && results.risk_score !== undefined) { | |
| showResults(results); | |
| } else { | |
| if (emptyView) emptyView.style.display = "block"; | |
| if (resultsView) resultsView.style.display = "none"; | |
| } | |
| // Scan button | |
| const btnScan = document.getElementById("btn-scan"); | |
| if (btnScan) { | |
| btnScan.addEventListener("click", async () => { | |
| if (usage && !usage.allowed) { if (limitBanner) limitBanner.style.display = "block"; return; } | |
| btnScan.textContent = "Scanning..."; btnScan.disabled = true; | |
| try { | |
| await chrome.tabs.sendMessage(tab.id, { type: "TRIGGER_SCAN" }); | |
| setTimeout(async () => { | |
| try { | |
| const r = await chrome.runtime.sendMessage({ type: "GET_RESULTS", tabId: tab.id }); | |
| if (r?.risk_score !== undefined) showResults(r); | |
| } catch {} | |
| try { usage = await chrome.runtime.sendMessage({ type: "CHECK_USAGE" }); updateUsage(usage); } catch {} | |
| btnScan.textContent = "Scan this page"; btnScan.disabled = false; | |
| }, 3000); | |
| } catch { btnScan.textContent = "Error — refresh page"; btnScan.disabled = false; } | |
| }); | |
| } | |
| // Re-scan | |
| const btnRescan = document.getElementById("btn-rescan"); | |
| if (btnRescan) btnRescan.addEventListener("click", async () => { | |
| if (usage && !usage.allowed) { if (limitBanner) limitBanner.style.display = "block"; return; } | |
| try { await chrome.tabs.sendMessage(tab.id, { type: "TRIGGER_SCAN" }); } catch {} window.close(); | |
| }); | |
| // FIX v4.3: Properly await async sidePanel.open() so errors are caught | |
| const btnDetails = document.getElementById("btn-details"); | |
| if (btnDetails) btnDetails.addEventListener("click", async () => { | |
| try { await chrome.sidePanel.open({ tabId: tab.id }); } catch(e) { console.warn("sidePanel.open failed:", e); } | |
| window.close(); | |
| }); | |
| // Login button | |
| const btnLogin = document.getElementById("btn-login"); | |
| if (btnLogin) btnLogin.addEventListener("click", () => { | |
| chrome.tabs.create({ url: "https://clauseguardweb.netlify.app/auth/login" }); | |
| }); | |
| }); | |
| function showResults(results) { | |
| const rv = document.getElementById("results-view"); | |
| const ev = document.getElementById("empty-view"); | |
| if (rv) rv.style.display = "block"; | |
| if (ev) ev.style.display = "none"; | |
| const el = (id) => document.getElementById(id); | |
| if (el("risk-score")) el("risk-score").textContent = results.risk_score; | |
| const grade = results.grade || "C"; | |
| const badge = el("grade-badge"); | |
| if (badge) { badge.className = "grade grade-" + grade.toLowerCase(); badge.textContent = "Grade " + grade; } | |
| const bar = el("bar-fill"); | |
| if (bar) { | |
| bar.style.width = results.risk_score + "%"; | |
| bar.className = "bar-fill " + (results.risk_score >= 60 ? "bar-red" : results.risk_score >= 30 ? "bar-amber" : "bar-green"); | |
| } | |
| // FIX v4.3: Count CRITICAL severity too (backend can return it) | |
| const counts = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 }; | |
| (results.results || []).forEach(r => (r.categories || []).forEach(c => { | |
| if (counts[c.severity] !== undefined) counts[c.severity]++; | |
| else counts.MEDIUM++; // Unknown severities default to MEDIUM | |
| })); | |
| // Merge CRITICAL into HIGH for display (popup only has 3 columns) | |
| if (el("c-high")) el("c-high").textContent = counts.CRITICAL + counts.HIGH; | |
| if (el("c-med")) el("c-med").textContent = counts.MEDIUM; | |
| if (el("c-low")) el("c-low").textContent = counts.LOW; | |
| // Show source indicator | |
| const src = el("scan-source"); | |
| if (src) src.textContent = results.source === "api" ? "Legal-BERT" : results.source === "local" ? "Local (offline)" : ""; | |
| } | |
| function updateUsage(usage) { | |
| if (!usage) return; | |
| const text = document.getElementById("usage-text"); | |
| const fill = document.getElementById("usage-fill"); | |
| if (!text || !fill) return; | |
| if (usage.plan === "free") { | |
| text.textContent = usage.used + "/" + usage.limit + " scans"; | |
| const pct = Math.min(100, (usage.used / usage.limit) * 100); | |
| fill.style.width = pct + "%"; | |
| if (pct >= 100) fill.style.background = "#ef4444"; | |
| else if (pct >= 70) fill.style.background = "#f59e0b"; | |
| } else { | |
| text.textContent = "Unlimited"; | |
| fill.style.width = "100%"; fill.style.background = "#22c55e"; | |
| } | |
| } | |