From d3bd04d1ea1e975b7e3f59d9a9deebd7d4f19d8b Mon Sep 17 00:00:00 2001 From: Samson Nkrumah Date: Wed, 8 Apr 2026 07:21:02 +0100 Subject: [PATCH 1/5] fix: use server-side pagination for conference list tab The conference list tab now fetches one page at a time from the API using ?limit=20&offset=N instead of loading all conferences into memory and slicing with JavaScript. - Graphs tab still loads all conferences (fast now without expand_fields) - Conference list tab fetches paginated data via API - Pagination controls emit page-changed event to trigger API fetch - Loading state shown while fetching - Backward compatible: graphs/filters still work with full conference data --- static/js/app-dashboard/components/app.vue | 39 +++++++++- .../components/conferencesTab.vue | 73 +++++++++---------- 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/static/js/app-dashboard/components/app.vue b/static/js/app-dashboard/components/app.vue index 237a03a..d73aa8b 100644 --- a/static/js/app-dashboard/components/app.vue +++ b/static/js/app-dashboard/components/app.vue @@ -117,7 +117,14 @@ />
- +
@@ -147,6 +154,11 @@ export default { data: {}, conferences: null, + paginatedConferences: null, + conferencesCount: 0, + conferencesPage: 1, + conferencesPerPage: 20, + conferencesLoading: false, sessions: null, connections: null, issues: null, @@ -191,8 +203,7 @@ export default { this.data.conferences = await peermetrics.get(peermetrics.urls.conferences(), { appId: peermetrics.app.id - }) - .catch(e => { + }).catch(e => { console.warn(e) }); @@ -201,6 +212,8 @@ export default { this.conferences = Object.freeze(this.data.conferences); } + await this.fetchConferences(); + this.data.sessions = await peermetrics.get(peermetrics.urls.sessions, { appId: peermetrics.app.id }) @@ -291,6 +304,26 @@ export default { return Object.values(object).sort((a, b) => a.value > b.value ? 1 : -1) }, + async fetchConferences(page) { + if (page) this.conferencesPage = page; + this.conferencesLoading = true; + const offset = (this.conferencesPage - 1) * this.conferencesPerPage; + try { + const response = await peermetrics.get(peermetrics.urls.conferences(), { + appId: peermetrics.app.id, + limit: this.conferencesPerPage, + offset: offset, + }); + if (response) { + this.paginatedConferences = Object.freeze(response.results || []); + this.conferencesCount = response.count || 0; + } + } catch (e) { + console.warn(e); + } + this.conferencesLoading = false; + }, + applyFilters () { // if no filters are applied, use all the data if (!this.selectedAppVersion && !this.selectedBrowser && !this.selectedOs && !this.selectedCountry) { diff --git a/static/js/app-dashboard/components/conferencesTab.vue b/static/js/app-dashboard/components/conferencesTab.vue index 68b7292..0b6586a 100644 --- a/static/js/app-dashboard/components/conferencesTab.vue +++ b/static/js/app-dashboard/components/conferencesTab.vue @@ -5,9 +5,12 @@
@@ -52,7 +39,6 @@ From 25135b929686e707707f6b1346ac9d9f16b6fec4 Mon Sep 17 00:00:00 2001 From: Samson Nkrumah Date: Wed, 8 Apr 2026 07:34:32 +0100 Subject: [PATCH 2/5] fix: handle missing issues array in conference list The API list endpoint no longer returns issues (expand_fields removed in api#19). The hasError/hasWarning helpers crashed when conference.issues was undefined. Added null check so charts render without issues data. --- static/js/mixins/conferences.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/js/mixins/conferences.js b/static/js/mixins/conferences.js index 82471ed..42ead6d 100644 --- a/static/js/mixins/conferences.js +++ b/static/js/mixins/conferences.js @@ -28,10 +28,10 @@ const conferencesFunctions = { return !!conference.conference_name; }, hasError(conference) { - return conference.issues.some((issue) => issue.type === 'error') + return conference.issues && conference.issues.some((issue) => issue.type === 'error') }, hasWarning(conference) { - return conference.issues.some((issue) => issue.type === 'warning') + return conference.issues && conference.issues.some((issue) => issue.type === 'warning') }, createPath(conference) { return peermetrics.createPath('conference', conference.id) From 50d307c817d20db6f274e7eb94bdf66920503a59 Mon Sep 17 00:00:00 2001 From: Samson Nkrumah Date: Wed, 8 Apr 2026 07:40:40 +0100 Subject: [PATCH 3/5] fix: guard conference.issues access on participant page The participant conferences tab accessed conference.issues.length without checking if issues exists. With expand_fields removed from the API list endpoint, this would crash. --- static/js/participant/components/conferencesTab.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/participant/components/conferencesTab.vue b/static/js/participant/components/conferencesTab.vue index 5f71b88..00606fb 100644 --- a/static/js/participant/components/conferencesTab.vue +++ b/static/js/participant/components/conferencesTab.vue @@ -140,7 +140,7 @@ export default { // if an sfu, show all conferences that had at least one issue if (this.isSfu) { return this.conferences.filter((conference) => { - return conference.issues.length + return conference.issues && conference.issues.length }) } From c955984ba5f659cf5f07486d4248378d0a9bfc1f Mon Sep 17 00:00:00 2001 From: Samson Nkrumah Date: Wed, 8 Apr 2026 15:26:02 +0100 Subject: [PATCH 4/5] fix: restore error/warning icons on conference list The conference list was missing error/warning icons after expand_fields was removed. Now uses has_errors and has_warnings boolean flags from the API (annotated via Exists() subquery, no N+1). --- static/js/app-dashboard/components/conferencesTab.vue | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/static/js/app-dashboard/components/conferencesTab.vue b/static/js/app-dashboard/components/conferencesTab.vue index 0b6586a..303015b 100644 --- a/static/js/app-dashboard/components/conferencesTab.vue +++ b/static/js/app-dashboard/components/conferencesTab.vue @@ -20,6 +20,17 @@ No conference name, {{ conference.conference_id }} + + + From ec4a631abbc877d002ce36fdc2f945ee3c5bc50c Mon Sep 17 00:00:00 2001 From: Samson Nkrumah Date: Wed, 8 Apr 2026 15:35:01 +0100 Subject: [PATCH 5/5] fix: limit all dashboard API calls to daysHistory time window All four API calls (issues, conferences, sessions, connections) now pass created_at_gte using the daysHistory value (30 days). This prevents the dashboard from loading months of historical data when the dataset grows. Sessions endpoint already enforces a 30-day limit server-side, so the param is redundant there but consistent. --- static/js/app-dashboard/components/app.vue | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/static/js/app-dashboard/components/app.vue b/static/js/app-dashboard/components/app.vue index d73aa8b..7477e35 100644 --- a/static/js/app-dashboard/components/app.vue +++ b/static/js/app-dashboard/components/app.vue @@ -191,8 +191,13 @@ export default { }, async created() { + const since = new Date(); + since.setDate(since.getDate() - peermetrics.daysHistory); + const created_at_gte = since.toISOString(); + this.data.issues = await peermetrics.get(peermetrics.urls.issues(), { - appId: peermetrics.app.id + appId: peermetrics.app.id, + created_at_gte, }).catch(e => { console.warn(e) }); @@ -202,7 +207,8 @@ export default { } this.data.conferences = await peermetrics.get(peermetrics.urls.conferences(), { - appId: peermetrics.app.id + appId: peermetrics.app.id, + created_at_gte, }).catch(e => { console.warn(e) }); @@ -215,17 +221,19 @@ export default { await this.fetchConferences(); this.data.sessions = await peermetrics.get(peermetrics.urls.sessions, { - appId: peermetrics.app.id + appId: peermetrics.app.id, + created_at_gte, }) .catch(e => console.warn(e)); - + if(this.data.sessions) { this.data.sessions = peermetrics.utils.populateIssues(this.data.sessions, this.data.issues) this.sessions = Object.freeze(this.data.sessions); } this.data.connections = await peermetrics.get(peermetrics.urls.connections(), { - appId: peermetrics.app.id + appId: peermetrics.app.id, + created_at_gte, }) .catch(e => { console.warn(e)