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

Spring 2023 Pre-Enroll Release #821

Merged
merged 36 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2e28e98
Create workflow to backup Firestore (#754)
benjamin-shen Nov 17, 2022
0c5bf6b
Bump json5 from 1.0.1 to 1.0.2 (#767)
dependabot[bot] Jan 23, 2023
fd1388d
Bump qs from 6.5.2 to 6.5.3 (#765)
dependabot[bot] Jan 23, 2023
9c0c906
Bump decode-uri-component from 0.2.0 to 0.2.2 (#763)
dependabot[bot] Jan 23, 2023
07798de
Bump vite from 2.6.14 to 2.9.13 (#708)
dependabot[bot] Jan 23, 2023
9d53aed
Bump jsonwebtoken and firebase-admin (#769)
dependabot[bot] Jan 23, 2023
0382696
Bump minimatch and serve (#770)
dependabot[bot] Jan 23, 2023
39d34dd
new spring roster (#772)
mirandayu131 Feb 3, 2023
fb3724b
Bump @sideway/formula from 3.0.0 to 3.0.1 (#774)
dependabot[bot] Feb 9, 2023
9e3c340
Bump @vitejs/plugin-vue (#775)
zachary-kent Feb 10, 2023
c99d409
Added Applied Economics Minor (#773)
mirandayu131 Feb 13, 2023
bf095d0
Added Earth and atmosphere Minor (#779)
rohanmaheshwari430 Feb 22, 2023
9f9a6b9
Update README.md (#778)
rohanmaheshwari430 Feb 24, 2023
af1a926
add pablo to contributers (#781)
PabloRaigoza Feb 24, 2023
01755a9
Add Kaylin to README.md (#782)
KaylinChan Feb 24, 2023
28579b0
Add name to README (#783)
elizabeth-tang Feb 24, 2023
3d046c9
Update Spring 2023 Contributors in README.md (#784)
noschiff Mar 1, 2023
c16403f
Added Game Design Minor (#785)
KaylinChan Mar 1, 2023
c60a27b
Added Standardized Abbreviations for Colleges, Majors, and Minors (#780)
jerrry1123 Mar 2, 2023
51d8c92
Semesters singleton migration (#723)
andxu282 Mar 5, 2023
0dba333
Add data science minor (#788)
elizabeth-tang Mar 5, 2023
ad1a1ec
Fix DBME (#797)
elizabeth-tang Mar 7, 2023
3715017
Refactor Teleport Modal to use Composition API (#791)
zachary-kent Mar 9, 2023
41bc380
courses + meta data script (#796)
rohanmaheshwari430 Mar 10, 2023
9cb2f74
Bump webpack from 5.74.0 to 5.76.1 (#800)
dependabot[bot] Mar 15, 2023
ccc4dcf
Analytics User Properties (#803)
zachary-kent Mar 25, 2023
81639e1
Course retrieval function and New course interface (#805)
rohanmaheshwari430 Mar 28, 2023
2bd5df9
Add ansc minor (#793)
PabloRaigoza Mar 31, 2023
9627394
Course color and credits dropdown (#808)
KaylinChan Apr 11, 2023
3a1beb8
Changing Courses Retrieval Method in BottomBar component (#804)
rohanmaheshwari430 Apr 22, 2023
0af9154
Parsed Other Yes List (#801)
mirandayu131 Apr 26, 2023
42692af
Update package.json (#823)
rohanmaheshwari430 Apr 28, 2023
caca879
Removed commented code (#824)
zachary-kent Apr 29, 2023
a87d12d
Populate Firestore with specific roster's courses (#820)
rohanmaheshwari430 May 2, 2023
5f0a73a
Fetch Approved Liberal Studies Courses (#811)
mirandayu131 May 2, 2023
8096cef
Modify Liberal Studies Checker (#818)
mirandayu131 May 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Analytics User Properties (#803)
  • Loading branch information
zachary-kent authored Mar 25, 2023
commit ccc4dcf82d085de627d79007adff3932757396e7
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@babel/preset-env": "^7.13.12",
"@babel/preset-typescript": "^7.13.0",
"@tsconfig/node14": "^1.0.3",
"@types/gtag.js": "^0.0.12",
"@types/jest": "^26.0.21",
"@types/minimist": "^1.2.2",
"@types/node-fetch": "^2.5.8",
Expand Down
9 changes: 5 additions & 4 deletions src/components/BottomBar/BottomBarState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { reactive } from 'vue';
import { GTag, GTagEvent } from '../../gtag';
import { VueGtag } from 'vue-gtag-next';
import { GTagEvent } from '../../gtag';
import { checkNotNull } from '../../utilities';

import {
Expand Down Expand Up @@ -117,7 +118,7 @@ export const addCourseToBottomBar = (course: FirestoreSemesterCourse): void => {
]);
};

export const toggleBottomBar = (gtag?: GTag): void => {
export const toggleBottomBar = (gtag?: VueGtag): void => {
vueForBottomBar.isExpanded = !vueForBottomBar.isExpanded;
if (vueForBottomBar.isExpanded) {
GTagEvent(gtag, 'bottom-bar-open');
Expand All @@ -126,7 +127,7 @@ export const toggleBottomBar = (gtag?: GTag): void => {
}
};

export const closeBottomBar = (gtag?: GTag): void => {
export const closeBottomBar = (gtag?: VueGtag): void => {
vueForBottomBar.isExpanded = false;
GTagEvent(gtag, 'bottom-bar-close');
};
Expand All @@ -135,7 +136,7 @@ export const changeBottomBarCourseFocus = (index: number): void => {
vueForBottomBar.bottomCourseFocus = index;
};

export const deleteBottomBarCourse = (index: number, gtag?: GTag): void => {
export const deleteBottomBarCourse = (index: number, gtag?: VueGtag): void => {
GTagEvent(gtag, 'bottom-bar-delete-tab');
vueForBottomBar.bottomCourses = vueForBottomBar.bottomCourses.filter((_, i) => i !== index);
if (vueForBottomBar.bottomCourseFocus >= vueForBottomBar.bottomCourses.length) {
Expand Down
15 changes: 8 additions & 7 deletions src/global-firestore-data/user-semesters.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { doc, updateDoc } from 'firebase/firestore';

import { VueGtag } from 'vue-gtag-next';
import { semestersCollection } from '../firebase-config';
import store from '../store';
import { GTag, GTagEvent } from '../gtag';
import { GTagEvent } from '../gtag';
import { sortedSemesters } from '../utilities';

import {
Expand Down Expand Up @@ -68,7 +69,7 @@ export const semesterEquals = (
export const addSemester = (
year: number,
season: FirestoreSemesterSeason,
gtag?: GTag,
gtag?: VueGtag,
courses: readonly FirestoreSemesterCourse[] = []
): void => {
GTagEvent(gtag, 'add-semester');
Expand All @@ -78,7 +79,7 @@ export const addSemester = (
export const deleteSemester = (
year: number,
season: FirestoreSemesterSeason,
gtag?: GTag
gtag?: VueGtag
): void => {
GTagEvent(gtag, 'delete-semester');
const semester = store.state.semesters.find(sem => semesterEquals(sem, year, season));
Expand All @@ -93,7 +94,7 @@ export const addCourseToSemester = (
season: FirestoreSemesterSeason,
newCourse: FirestoreSemesterCourse,
choiceUpdater: (choice: FirestoreCourseOptInOptOutChoices) => FirestoreCourseOptInOptOutChoices,
gtag?: GTag
gtag?: VueGtag
): void => {
GTagEvent(gtag, 'add-course');
editSemesters(oldSemesters => {
Expand All @@ -115,7 +116,7 @@ export const deleteCourseFromSemester = (
year: number,
season: FirestoreSemesterSeason,
courseUniqueID: number,
gtag?: GTag
gtag?: VueGtag
): void => {
GTagEvent(gtag, 'delete-course');
const semester = store.state.semesters.find(sem => semesterEquals(sem, year, season));
Expand All @@ -135,7 +136,7 @@ export const deleteCourseFromSemester = (
export const deleteAllCoursesFromSemester = (
year: number,
season: FirestoreSemesterSeason,
gtag?: GTag
gtag?: VueGtag
): void => {
GTagEvent(gtag, 'delete-semester-courses');
const semester = store.state.semesters.find(sem => semesterEquals(sem, year, season));
Expand All @@ -150,7 +151,7 @@ export const deleteAllCoursesFromSemester = (
}
};

export const deleteCourseFromSemesters = (courseUniqueID: number, gtag?: GTag): void => {
export const deleteCourseFromSemesters = (courseUniqueID: number, gtag?: VueGtag): void => {
GTagEvent(gtag, 'delete-course');
editSemesters(oldSemesters =>
oldSemesters.map(semester => {
Expand Down
21 changes: 16 additions & 5 deletions src/gtag.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import { VueGtag, query } from 'vue-gtag-next';

type EventPayload = { event_category: string; event_label: string; value: number };
type LoginEventPayload = { method: string };

export type GTag = {
event(eventType: string, eventPayload: LoginEventPayload | EventPayload): void;
/**
* Set a user's properties for analytics
*
* @param gtag the `VueGtag` instance to query
* @param properties the user's properties
*/
export const setUserProperties = (onboardingData: AppOnboardingData) => {
const gtag = query as Gtag.Gtag;
gtag('set', 'user_properties', {
major: onboardingData.major,
gradYear: onboardingData.gradYear,
});
};

/** GTagLoginEvent represents the gtag that tracks when users login. */
export const GTagLoginEvent = (gtag: GTag | undefined, method: string): void => {
export const GTagLoginEvent = (gtag: VueGtag | undefined, method: string): void => {
if (!gtag) return;
gtag.event('login', { method });
};
Expand Down Expand Up @@ -41,7 +52,7 @@ type EventType =
* @param gtag is the global site tag that sends events to Google Analytics
* @param eventType specifies the type of event that the gtag sends
*/
export const GTagEvent = (gtag: GTag | undefined, eventType: EventType): void => {
export const GTagEvent = (gtag: VueGtag | undefined, eventType: EventType): void => {
if (!gtag) return;
let eventPayload: EventPayload | undefined;
switch (eventType) {
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ auth.onAuthStateChanged(() => {
app.use(router);
// Enable Google analytics with custom events
app.use(VueGtag, {
property: { id: 'UA-124837875-2' },
property: { id: 'G-BQ6CTZQPSF' },
});
app.use(store);
app.mount('#app');
Expand Down
77 changes: 43 additions & 34 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
getFirstPlan,
} from './utilities';
import featureFlagCheckers from './feature-flags';
import { setUserProperties } from './gtag';

type SimplifiedFirebaseUser = { readonly displayName: string; readonly email: string };

Expand Down Expand Up @@ -161,45 +162,53 @@ const store: TypedVuexStore = new TypedVuexStore({
});

const autoRecomputeDerivedData = (): (() => void) =>
store.subscribe((payload, state) => {
if (payload.type === 'setOrderByNewest') {
store.commit('setSemesters', sortedSemesters(state.semesters, state.orderByNewest));
}
// Recompute courses
if (payload.type === 'setSemesters') {
const allCourseSet = new Set<string>();
const duplicatedCourseCodeSet = new Set<string>();
const courseMap: Record<number, FirestoreSemesterCourse> = {};
const courseToSemesterMap: Record<number, FirestoreSemester> = {};
state.semesters.forEach(semester => {
semester.courses.forEach(course => {
if (isPlaceholderCourse(course)) {
return;
}
store.subscribe((mutation, state) => {
switch (mutation.type) {
case 'setOnboardingData': {
setUserProperties(mutation.payload);
break;
}
case 'setOrderByNewest': {
store.commit('setSemesters', sortedSemesters(state.semesters, state.orderByNewest));
break;
}
case 'setSemesters': {
const allCourseSet = new Set<string>();
const duplicatedCourseCodeSet = new Set<string>();
const courseMap: Record<number, FirestoreSemesterCourse> = {};
const courseToSemesterMap: Record<number, FirestoreSemester> = {};
state.semesters.forEach(semester => {
semester.courses.forEach(course => {
if (isPlaceholderCourse(course)) {
return;
}

const { code } = course;
if (allCourseSet.has(code)) {
duplicatedCourseCodeSet.add(code);
} else {
allCourseSet.add(code);
}
courseMap[course.uniqueID] = course;
courseToSemesterMap[course.uniqueID] = semester;
const { code } = course;
if (allCourseSet.has(code)) {
duplicatedCourseCodeSet.add(code);
} else {
allCourseSet.add(code);
}
courseMap[course.uniqueID] = course;
courseToSemesterMap[course.uniqueID] = semester;
});
});
});
const derivedCourseData: DerivedCoursesData = {
duplicatedCourseCodeSet,
courseMap,
courseToSemesterMap,
};
store.commit('setDerivedCourseData', derivedCourseData);
const derivedCourseData: DerivedCoursesData = {
duplicatedCourseCodeSet,
courseMap,
courseToSemesterMap,
};
store.commit('setDerivedCourseData', derivedCourseData);
break;
}
default:
}
// Recompute requirements
if (
payload.type === 'setOnboardingData' ||
payload.type === 'setSemesters' ||
payload.type === 'setToggleableRequirementChoices' ||
payload.type === 'setOverriddenFulfillmentChoices'
mutation.type === 'setOnboardingData' ||
mutation.type === 'setSemesters' ||
mutation.type === 'setToggleableRequirementChoices' ||
mutation.type === 'setOverriddenFulfillmentChoices'
) {
if (state.onboardingData.college !== '') {
store.commit(
Expand Down
6 changes: 6 additions & 0 deletions src/vue-gtag-next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export {};

declare module 'vue-gtag-next' {
// eslint-disable-next-line import/prefer-default-export
export const query: Gtag.Gtag;
}
10 changes: 6 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"baseUrl": ".",
"types": [
"node",
"jest"
"jest",
"@types/gtag.js"
],
"paths": {
"@/*": [
Expand All @@ -34,9 +35,10 @@
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
, "scripts/population/courses-json-generator.ts" ],
"tests/**/*.tsx",
"scripts/population/courses-json-generator.ts"
],
"exclude": [
"node_modules"
]
}
}