From dc084ca84ea80eb3e0dcf12bd19fc17d78629987 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Wed, 15 Jan 2025 17:48:57 -0500 Subject: [PATCH 1/6] refactor: change aggregation doc name --- functions/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/index.js b/functions/index.js index 4a52ff9..8a0b9a8 100644 --- a/functions/index.js +++ b/functions/index.js @@ -16,7 +16,7 @@ async function calculateAggregatedCounts() { const aggregatedCounts = calculateYearCounts(publications); // Save the aggregation(s) - await db.collection('aggregations').doc('publicationCounts').set({ + await db.collection('aggregations').doc('publicationsByYear').set({ counts: aggregatedCounts, }); } From fcfb2bd33bf473cc55b9b633268dee7cb0dc9b4c Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Fri, 17 Jan 2025 17:19:08 -0500 Subject: [PATCH 2/6] feat: added function to aggregation documents from firestore --- src/utils/firebase.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/utils/firebase.ts b/src/utils/firebase.ts index c69b3e7..7c33014 100644 --- a/src/utils/firebase.ts +++ b/src/utils/firebase.ts @@ -267,3 +267,15 @@ const getUser = async (email): Promise => { return docSnap.data() as User; }; + +export async function getAggregation({ documentName }) { + const docRef = doc(db, 'aggregations', documentName); + const docSnap = await getDoc(docRef); + + if (docSnap.exists()) { + return docSnap.data()['counts']; + } else { + console.log('Document not found.'); + return null; + } +} From 87161709837249fbe887eeeb8eb3b25437634b7c Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Fri, 17 Jan 2025 17:23:46 -0500 Subject: [PATCH 3/6] refactor: updated CountsByYearPlot function to use fetched data from firestore --- src/components/BarChart.js | 83 +++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/src/components/BarChart.js b/src/components/BarChart.js index ce5cd34..89aa110 100644 --- a/src/components/BarChart.js +++ b/src/components/BarChart.js @@ -1,5 +1,6 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Vega } from 'react-vega'; +import { getAggregation } from '../utils/firebase.ts'; const bar_color = '#00c398'; // ccv green const bar_hover_color = '#ffc72c'; // ccv yellow @@ -431,44 +432,50 @@ const generateBarPlotWithCumuSum = (dataJson, xLabel) => { return spec; }; -const inputJson = [ - { label: '2008', count: 1 }, - { label: '2009', count: 2 }, - { label: '2010', count: 6 }, - { label: '2011', count: 3 }, - { label: '2012', count: 8 }, - { label: '2013', count: 18 }, - { label: '2014', count: 35 }, - { label: '2015', count: 41 }, - { label: '2016', count: 35 }, - { label: '2017', count: 60 }, - { label: '2018', count: 70 }, - { label: '2019', count: 60 }, - { label: '2020', count: 70 }, - { label: '2021', count: 58 }, - { label: '2022', count: 62 }, - { label: '2023', count: 80 }, - { label: '2024', count: 5 }, -]; - -export function CountsByYearPlot({ type }) { - let vegaSpec = {}; +export const CountsByYearPlot = ({ type }) => { const xLabel = 'Year'; - if (type === 'bar') { - vegaSpec = generateBarPlot({ - data: inputJson, - xLabel: xLabel, - yLabel: 'Publications', - }); - } else if (type === 'cumu-line') { - vegaSpec = generateCumuSumPlot({ - data: inputJson, - xLabel: xLabel, - yLabel: 'Cumulative Publications', - }); - } else if (type === 'bar-cumu-line') { - vegaSpec = generateBarPlotWithCumuSum(inputJson, xLabel); + const [vegaSpec, setVegaSpec] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + const fetchData = async () => { + try { + const fetchedData = await getAggregation({ documentName: 'publicationsByYear' }); + // console.log(fetchedData); + let spec; + if (type === 'bar') { + spec = generateBarPlot({ + data: fetchedData, + xLabel: xLabel, + yLabel: 'Publications', + }); + } else if (type === 'cumu-line') { + spec = generateCumuSumPlot({ + data: fetchedData, + xLabel: xLabel, + yLabel: 'Cumulative Publications', + }); + } else if (type === 'bar-cumu-line') { + spec = generateBarPlotWithCumuSum(fetchedData, xLabel); + } + setVegaSpec(spec); + } catch (error) { + console.error('Error fetching document:', error); + } finally { + setLoading(false); + } + }; + + fetchData(); + }, [type]); + + if (loading) { + return
Loading...
; + } + + if (!vegaSpec) { + return
Error: Invalid plot type specified
; } return ; -} +}; From 719ea5190e6960984636d42fc6925f8f5f88706b Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Fri, 17 Jan 2025 17:24:12 -0500 Subject: [PATCH 4/6] refactor: formatting --- functions/index.js | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/functions/index.js b/functions/index.js index 8a0b9a8..45e775e 100644 --- a/functions/index.js +++ b/functions/index.js @@ -7,12 +7,12 @@ const { calculateYearCounts } = require('./aggregator'); initializeApp(); const db = getFirestore(); -// Calculate and save aggregations +// Calculate and save aggregations async function calculateAggregatedCounts() { const publicationsSnapshot = await db.collection('publications').get(); - const publications = publicationsSnapshot.docs.map(doc => doc.data()); + const publications = publicationsSnapshot.docs.map((doc) => doc.data()); - // Count of docs by year + // Count of docs by year const aggregatedCounts = calculateYearCounts(publications); // Save the aggregation(s) @@ -22,21 +22,18 @@ async function calculateAggregatedCounts() { } // onDocumentWritten triggers on create, update, or delete -exports.aggregatePublicationsOnWrite = onDocumentWritten( - 'publications/{docId}', - async (event) => { - try { - // log before and after data - const beforeData = event.data.before.data(); - const afterData = event.data.after.data(); +exports.aggregatePublicationsOnWrite = onDocumentWritten('publications/{docId}', async (event) => { + try { + // log before and after data + const beforeData = event.data.before.data(); + const afterData = event.data.after.data(); - console.log(`Document written: ${event.params.docId}`); - console.log('Before data:', beforeData); - console.log('After data:', afterData); + console.log(`Document written: ${event.params.docId}`); + console.log('Before data:', beforeData); + console.log('After data:', afterData); - await calculateAggregatedCounts(); - } catch (error) { - console.error('Error recalculating counts on document write:', error); - } + await calculateAggregatedCounts(); + } catch (error) { + console.error('Error recalculating counts on document write:', error); } -); +}); From 969291e1e9e8982ec0ee55db311b0ebecf5364af Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Wed, 22 Jan 2025 10:15:15 -0500 Subject: [PATCH 5/6] chore: remove log comment --- src/components/BarChart.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/BarChart.js b/src/components/BarChart.js index 89aa110..e0906c4 100644 --- a/src/components/BarChart.js +++ b/src/components/BarChart.js @@ -441,7 +441,6 @@ export const CountsByYearPlot = ({ type }) => { const fetchData = async () => { try { const fetchedData = await getAggregation({ documentName: 'publicationsByYear' }); - // console.log(fetchedData); let spec; if (type === 'bar') { spec = generateBarPlot({ From 11eb152f535260aa083880676b2e628d0e9dcda9 Mon Sep 17 00:00:00 2001 From: George Dang <53052793+gtdang@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:46:28 -0500 Subject: [PATCH 6/6] refactor: only allow export actions on plots --- src/components/BarChart.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/BarChart.js b/src/components/BarChart.js index e0906c4..52bb789 100644 --- a/src/components/BarChart.js +++ b/src/components/BarChart.js @@ -476,5 +476,15 @@ export const CountsByYearPlot = ({ type }) => { return
Error: Invalid plot type specified
; } - return ; + return ( + + ); };