Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semesters singleton migration #723

Merged
merged 13 commits into from
Mar 5, 2023
32 changes: 32 additions & 0 deletions scripts/migration/semesters-singleton-list-migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable no-console */

import { usernameCollection, semestersCollection } from '../firebase-config';

/**
* Perform migration of semester to plans with a list of semesters
*/
async function runOnUser(userEmail: string) {
const semestersDoc = await semestersCollection.doc(userEmail).get();
const semesters = semestersDoc.data()?.semesters ?? [];
await semestersCollection.doc(userEmail).update({
plans: [{ semesters }],
});
}

async function main() {
const userEmail = process.argv[2];
if (userEmail != null) {
await runOnUser(userEmail);
return;
}
const collection = await usernameCollection.get();
for (const { id } of collection.docs) {
console.group(`Running on ${id}...`);
// Intentionally await in a loop to have no interleaved console logs.
// eslint-disable-next-line no-await-in-loop
await runOnUser(id);
console.groupEnd();
}
}

main();
4 changes: 3 additions & 1 deletion scripts/track-users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
trackUsersCollection,
} from './firebase-config';

import { getFirstPlan } from '../src/utilities';

const average = (array: readonly number[]) => array.reduce((a, b) => a + b) / array.length;
function seasonToMonth(season: string) {
switch (season) {
Expand Down Expand Up @@ -133,7 +135,7 @@ async function trackUsers() {
return;
}

const { semesters } = doc.data();
const semesters = getFirstPlan(doc.data());

let oldSemesterCount = 0;
let newSemesterCount = 0;
Expand Down
8 changes: 5 additions & 3 deletions src/global-firestore-data/user-semesters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import {
export const editSemesters = (
updater: (oldSemesters: readonly FirestoreSemester[]) => readonly FirestoreSemester[]
): void => {
const newSemesters = updater(store.state.semesters);
store.commit('setSemesters', newSemesters);
const semesters = updater(store.state.semesters);
store.commit('setSemesters', semesters);
// TODO: update when multiple plans frontend implemented
updateDoc(doc(semestersCollection, store.state.currentFirebaseUser.email), {
semesters: newSemesters,
semesters,
plans: [{ semesters }],
});
};

Expand Down
10 changes: 8 additions & 2 deletions src/store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Store } from 'vuex';
import { doc, getDoc, onSnapshot, setDoc } from 'firebase/firestore';
import { doc, getDoc, onSnapshot, setDoc, updateDoc } from 'firebase/firestore';

import * as fb from './firebase-config';
import computeGroupedRequirementFulfillmentReports from './requirements/requirement-frontend-computation';
Expand All @@ -13,6 +13,7 @@ import {
getCurrentYear,
sortedSemesters,
isPlaceholderCourse,
getFirstPlan,
} from './utilities';
import featureFlagCheckers from './feature-flags';

Expand Down Expand Up @@ -273,8 +274,12 @@ export const initializeFirestoreListeners = (onLoad: () => void): (() => void) =
getDoc(doc(fb.semestersCollection, simplifiedUser.email)).then(snapshot => {
const data = snapshot.data();
if (data) {
const { orderByNewest, semesters } = data;
const semesters = getFirstPlan(data);
const { orderByNewest } = data;
store.commit('setSemesters', semesters);
updateDoc(doc(fb.semestersCollection, simplifiedUser.email), {
plans: [{ semesters }], // TODO: andxu282 update later
});
// if user hasn't yet chosen an ordering, choose true by default
store.commit('setOrderByNewest', orderByNewest === undefined ? true : orderByNewest);
} else {
Expand All @@ -286,6 +291,7 @@ export const initializeFirestoreListeners = (onLoad: () => void): (() => void) =
store.commit('setSemesters', [newSemester]);
setDoc(doc(fb.semestersCollection, simplifiedUser.email), {
orderByNewest: true,
plans: [{ semesters: [newSemester] }], // TODO: andxu282 update later
semesters: [newSemester],
});
}
Expand Down
1 change: 1 addition & 0 deletions src/user-data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type FirestoreSemester = {
};

type FirestoreSemestersData = {
readonly plans?: readonly { semesters: readonly FirestoreSemester[] }[];
readonly semesters: readonly FirestoreSemester[];
readonly orderByNewest: boolean;
};
Expand Down
11 changes: 11 additions & 0 deletions src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ export const SeasonOrdinal = {
Fall: 3,
} as const;

/**
* Get a user's first plan given their semesters
* @param semestersDoc A document in the `user-semesters` collection
* @returns The user's first plan
*/
export const getFirstPlan = ({
semesters,
plans,
}: FirestoreSemestersData): readonly FirestoreSemester[] =>
plans && plans.length > 0 ? plans[0].semesters : semesters;

/**
* Returns given semesters sorted in either increasing or decreasing order of date
* @param semesters the semesters to return sorted
Expand Down