diff --git a/dashboard/dashboard.html b/dashboard/dashboard.html index c18a919..8ec42ab 100644 --- a/dashboard/dashboard.html +++ b/dashboard/dashboard.html @@ -35,6 +35,9 @@ + diff --git a/dashboard/dashboard.js b/dashboard/dashboard.js index 97368f9..ec37d61 100644 --- a/dashboard/dashboard.js +++ b/dashboard/dashboard.js @@ -263,6 +263,10 @@ function setupEventListeners() { checkSessionAndDiscoverStudents(); }); + if (el.inspectFeedBtn) { + el.inspectFeedBtn.addEventListener('click', handleInspectFeed); + } + el.setManualIdBtn.addEventListener('click', () => { const customId = el.manualStudentId.value.trim(); if (!customId) return; @@ -308,6 +312,69 @@ function setupEventListeners() { }); } +async function handleInspectFeed() { + log('🔬 Inspecting live Brightwheel tab...', 'info'); + try { + const [bwTab] = await chrome.tabs.query({ url: 'https://schools.mybrightwheel.com/*' }); + if (!bwTab || !bwTab.id) { + log('No active Brightwheel tab found at schools.mybrightwheel.com. Please ensure the feed is open in a tab.', 'error'); + return; + } + + chrome.tabs.sendMessage(bwTab.id, { + action: 'INSPECT_LIVE_FEED', + studentId: state.selectedStudentId + }, (res) => { + if (!res || !res.success) { + log('Inspection response error: ' + (res?.error || 'Could not communicate with tab. Try refreshing the Brightwheel tab.'), 'error'); + return; + } + + log(`✅ Live Inspection Complete for: ${res.currentUrl}`, 'success'); + log(`Page Title: "${res.pageTitle}"`, 'info'); + log(`DOM Cards Detected on Page: ${res.domCards?.length || 0}`, 'info'); + + if (res.domCards && res.domCards.length > 0) { + res.domCards.slice(0, 3).forEach((dc, i) => { + log(` [DOM Card ${i + 1}] Text: "${dc.raw_text.replace(/\s+/g, ' ').substring(0, 100)}..."`, 'info'); + }); + } + + const acts = res.apiSampleActivities || []; + log(`API Sample Activities Received: ${acts.length}`, 'success'); + + acts.forEach((a, idx) => { + const type = a.activity_type || a.action_type || a.type; + const presentKeys = Object.keys(a).filter(k => a[k] !== null && a[k] !== undefined && a[k] !== ''); + log(`[API Item ${idx + 1}] Type="${type}", Note="${a.note || a.body || ''}", Keys=[${presentKeys.join(', ')}]`, 'info'); + + if (type === 'ac_video' || type === 'video') { + log(` -> Video payload: media=${JSON.stringify(a.media || null)}, video_url=${a.video_url || null}`, 'warn'); + } + if (type === 'ac_nap' || type === 'nap') { + log(` -> Nap payload: action_type=${a.action_type}, nap_start=${a.nap_start || a.start_time}, nap_end=${a.nap_end || a.end_time}, duration=${a.duration || a.duration_minutes}`, 'warn'); + } + if (type === 'ac_checkin' || type === 'checkin') { + log(` -> Checkin payload: action_type=${a.action_type}, signed_in_by=${a.signed_in_by || a.actor_name || a.guardian_name}, event_type=${a.event_type}`, 'warn'); + } + }); + + // Automatically download inspection JSON report + const blob = new Blob([JSON.stringify(res, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `brightwheel_inspection_${state.selectedStudentId}_${Date.now()}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + log(`📁 Downloaded full inspection report to your Downloads folder (${(blob.size/1024).toFixed(1)} KB).`, 'success'); + }); + } catch (e) { + log('Inspection error: ' + e.message, 'error'); + } +} + // ------------------------------------------------------------- // Main Export Process Engine // ------------------------------------------------------------- diff --git a/scripts/content_script.js b/scripts/content_script.js index f741187..65f292e 100644 --- a/scripts/content_script.js +++ b/scripts/content_script.js @@ -40,39 +40,47 @@ return true; } - if (message.action === 'SCRAPE_DOM_FEED') { - try { - const domActivities = scrapeDomFeedCards(); - sendResponse({ success: true, activities: domActivities, htmlSample: document.body.innerHTML.substring(0, 5000) }); - } catch (err) { - sendResponse({ success: false, error: err.message }); - } - return true; - } + if (message.action === 'INSPECT_LIVE_FEED') { + (async () => { + try { + const studentId = message.studentId || detectCurrentStudentId(); + const apiListRes = await fetch(`https://schools.mybrightwheel.com/api/v1/students/${studentId}/activities?page_size=25`, { + credentials: 'include', + headers: { 'Accept': 'application/json' } + }).then(r => r.json()).catch(e => ({ error: e.message })); - if (message.action === 'FETCH_WITH_CREDENTIALS') { - fetch(message.url, { - method: message.method || 'GET', - headers: { - 'Accept': 'application/json', - ...(message.headers || {}) - }, - credentials: 'include' - }) - .then(async (res) => { - if (!res.ok) { - const errorText = await res.text().catch(() => ''); - return sendResponse({ success: false, status: res.status, statusText: res.statusText, body: errorText }); + const rawActs = apiListRes?.activities || apiListRes?.items || []; + + // Sample detail fetches for video, nap, checkin + const sampleDetails = {}; + for (const act of rawActs.slice(0, 10)) { + const type = act.activity_type || act.action_type || act.type; + if (!sampleDetails[type] && act.id) { + const detail = await fetch(`https://schools.mybrightwheel.com/api/v1/students/${studentId}/activities/${act.id}`, { + credentials: 'include', + headers: { 'Accept': 'application/json' } + }).then(r => r.json()).catch(e => ({ error: e.message })); + sampleDetails[type] = detail; + } } - const json = await res.json(); - sendResponse({ success: true, status: res.status, data: json }); - }) - .catch((err) => { + + const domCards = scrapeDomFeedCards(); + + sendResponse({ + success: true, + studentId, + apiSampleActivities: rawActs.slice(0, 10), + sampleDetails, + domCards: domCards.slice(0, 20), + pageTitle: document.title, + currentUrl: window.location.href + }); + } catch (err) { sendResponse({ success: false, error: err.message }); - }); + } + })(); return true; // async } - }); // DOM Scraper for Brightwheel Web Feed function scrapeDomFeedCards() {