feat: UTRP v2 migration (#292)
* feat: wip add course by url * chore: update imports * feat: add useCourseFromUrl hook * chore: extract logic into async function * feat: add checkLoginStatus.ts * feat: add useCourseMigration hook * feat: working course migration * fix: active schedule bug * feat: refactor logic and add to onUpdate * feat: update ui style * feat: add changelog functionality to settings * chore: update packages * feat: migration + sentry stuffs * feat: improve migration flow * docs: add sentry jsdocs * chore: fix lint and format * chore: cleanup + fix race condition --------- Co-authored-by: Samuel Gunter <sgunter@utexas.edu> Co-authored-by: Razboy20 <razboy20@gmail.com>
This commit is contained in:
@@ -31,6 +31,22 @@ chrome.runtime.onInstalled.addListener(details => {
|
||||
}
|
||||
});
|
||||
|
||||
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
|
||||
console.log(changeInfo);
|
||||
if (changeInfo.url === 'https://utdirect.utexas.edu/apps/registrar/course_schedule/utrp_login/') {
|
||||
console.log('UTDirect detected');
|
||||
// close the tab, open popup
|
||||
|
||||
function openPopupAction() {
|
||||
chrome.tabs.onActivated.removeListener(openPopupAction);
|
||||
chrome.action.openPopup();
|
||||
}
|
||||
|
||||
chrome.tabs.onActivated.addListener(openPopupAction);
|
||||
await chrome.tabs.remove(tabId);
|
||||
}
|
||||
});
|
||||
|
||||
// initialize the message listener that will listen for messages from the content script
|
||||
const messageListener = new MessageListener<BACKGROUND_MESSAGES>({
|
||||
...browserActionHandler,
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||
import type { UserSchedule } from '@shared/types/UserSchedule';
|
||||
import { generateRandomId } from '@shared/util/random';
|
||||
import type { Serialized } from 'chrome-extension-toolkit';
|
||||
|
||||
/**
|
||||
* Creates a new schedule with the given name
|
||||
* @param scheduleName the name of the schedule to create
|
||||
* @returns undefined if successful, otherwise an error message
|
||||
*/
|
||||
export default async function createSchedule(scheduleName: string): Promise<string | undefined> {
|
||||
export default async function createSchedule(scheduleName: string) {
|
||||
const schedules = await UserScheduleStore.get('schedules');
|
||||
// get the number of schedules that either have the same name or have the same name with a number appended (e.g. "New Schedule (1)")
|
||||
// this way we can prevent duplicate schedule names and increment the number if necessary
|
||||
@@ -22,14 +24,16 @@ export default async function createSchedule(scheduleName: string): Promise<stri
|
||||
if (count > 0) {
|
||||
name = `${scheduleName} (${count})`;
|
||||
}
|
||||
schedules.push({
|
||||
|
||||
const newSchedule: Serialized<UserSchedule> = {
|
||||
id: generateRandomId(),
|
||||
name,
|
||||
courses: [],
|
||||
hours: 0,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
};
|
||||
schedules.push(newSchedule);
|
||||
|
||||
await UserScheduleStore.set('schedules', schedules);
|
||||
return undefined;
|
||||
return newSchedule.id;
|
||||
}
|
||||
|
||||
78
src/pages/background/lib/migrateUTRPv1Courses.ts
Normal file
78
src/pages/background/lib/migrateUTRPv1Courses.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { validateLoginStatus } from '@shared/util/checkLoginStatus';
|
||||
import { getActiveSchedule } from '@views/hooks/useSchedules';
|
||||
import { courseMigration } from '@views/lib/courseMigration';
|
||||
|
||||
import addCourse from './addCourse';
|
||||
import createSchedule from './createSchedule';
|
||||
import switchSchedule from './switchSchedule';
|
||||
|
||||
/**
|
||||
* Retrieves the saved courses from the extension's chrome sync storage (old store) and returns an array of course links.
|
||||
*
|
||||
* @returns A promise that resolves to an array of course links.
|
||||
*/
|
||||
export async function getUTRPv1Courses(): Promise<string[]> {
|
||||
const { savedCourses } = await chrome.storage.sync.get('savedCourses');
|
||||
|
||||
// Check if the savedCourses array is empty
|
||||
if (!savedCourses || savedCourses.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Extract the link property from each course object and return it as an array
|
||||
return savedCourses.map((course: { link: string }) => course.link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the migration of UTRP v1 courses.
|
||||
*
|
||||
* This function checks if the user is logged into the UT course schedule page.
|
||||
* If the user is not logged in, it logs a message and exits. If the user is
|
||||
* logged in, it retrieves the UTRP v1 courses, creates a new schedule for the
|
||||
* migration, switches to the new schedule, and migrates the courses to the
|
||||
* active schedule.
|
||||
*
|
||||
* @returns A promise that resolves when the migration is complete.
|
||||
*/
|
||||
async function migrateUTRPv1Courses() {
|
||||
const loggedInToUT = await validateLoginStatus(
|
||||
'https://utdirect.utexas.edu/apps/registrar/course_schedule/utrp_login/'
|
||||
);
|
||||
|
||||
if (!loggedInToUT) {
|
||||
console.warn('Not logged in to UT Registrar.');
|
||||
return false;
|
||||
}
|
||||
|
||||
const oldCourses = await getUTRPv1Courses();
|
||||
console.log(oldCourses);
|
||||
|
||||
const migratedCourses = await courseMigration(oldCourses);
|
||||
|
||||
if (migratedCourses.length > 0) {
|
||||
console.log(oldCourses, migratedCourses);
|
||||
const migrateSchedule = await createSchedule('Migrated Schedule');
|
||||
await switchSchedule(migrateSchedule);
|
||||
|
||||
const activeSchedule = getActiveSchedule();
|
||||
|
||||
for (const course of migratedCourses) {
|
||||
// Add the course if it doesn't already exist
|
||||
if (activeSchedule.courses.every(c => c.uniqueId !== course.uniqueId)) {
|
||||
// ignore eslint, as we *do* want to spend time on each iteration
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await addCourse(activeSchedule.id, course);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the old courses from storage :>
|
||||
await chrome.storage.sync.remove('savedCourses');
|
||||
console.log('Successfully migrated UTRP v1 courses');
|
||||
} else {
|
||||
console.warn('No courses successfully found to migrate');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default migrateUTRPv1Courses;
|
||||
Reference in New Issue
Block a user