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:
@@ -1,3 +1,4 @@
|
||||
import addCourse from '@pages/background/lib/addCourse';
|
||||
import { deleteAllSchedules } from '@pages/background/lib/deleteSchedule';
|
||||
import { initSettings, OptionsStore } from '@shared/storage/OptionsStore';
|
||||
// import { getCourseColors } from '@shared/util/colors';
|
||||
@@ -9,8 +10,12 @@ import { SmallLogo } from '@views/components/common/LogoIcon';
|
||||
// import PopupCourseBlock from '@views/components/common/PopupCourseBlock';
|
||||
import SwitchButton from '@views/components/common/SwitchButton';
|
||||
import Text from '@views/components/common/Text/Text';
|
||||
import useChangelog from '@views/hooks/useChangelog';
|
||||
import useSchedules from '@views/hooks/useSchedules';
|
||||
import { CourseCatalogScraper } from '@views/lib/CourseCatalogScraper';
|
||||
import getCourseTableRows from '@views/lib/getCourseTableRows';
|
||||
import { GitHubStatsService, LONGHORN_DEVELOPERS_ADMINS } from '@views/lib/getGitHubStats';
|
||||
import { SiteSupport } from '@views/lib/getSiteSupport';
|
||||
import { getUpdatedAtDateTimeString } from '@views/lib/getUpdatedAtDateTimeString';
|
||||
import clsx from 'clsx';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
@@ -19,6 +24,7 @@ import IconoirGitFork from '~icons/iconoir/git-fork';
|
||||
// import { ExampleCourse } from 'src/stories/components/ConflictsWithWarning.stories';
|
||||
import DeleteForeverIcon from '~icons/material-symbols/delete-forever';
|
||||
|
||||
import { useMigrationDialog } from '../common/MigrationDialog';
|
||||
// import RefreshIcon from '~icons/material-symbols/refresh';
|
||||
import DevMode from './DevMode';
|
||||
import Preview from './Preview';
|
||||
@@ -79,6 +85,8 @@ export default function Settings(): JSX.Element {
|
||||
const [loadAllCourses, setLoadAllCourses] = useState<boolean>(false);
|
||||
const [enableDataRefreshing, setEnableDataRefreshing] = useState<boolean>(false);
|
||||
|
||||
const showMigrationDialog = useMigrationDialog();
|
||||
|
||||
// Toggle GitHub stats when the user presses the 'S' key
|
||||
const [showGitHubStats, setShowGitHubStats] = useState<boolean>(false);
|
||||
const [githubStats, setGitHubStats] = useState<Awaited<
|
||||
@@ -89,6 +97,7 @@ export default function Settings(): JSX.Element {
|
||||
// const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
|
||||
|
||||
const showDialog = usePrompt();
|
||||
const handleChangelogOnClick = useChangelog();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchGitHubStats = async () => {
|
||||
@@ -189,6 +198,41 @@ export default function Settings(): JSX.Element {
|
||||
});
|
||||
};
|
||||
|
||||
// todo: move into a util/shared place, rather than specifically in settings
|
||||
const handleAddCourseByUrl = async () => {
|
||||
// todo: Use a proper modal instead of a prompt
|
||||
// eslint-disable-next-line no-alert
|
||||
const link: string | null = prompt('Enter course link');
|
||||
|
||||
// Exit if the user cancels the prompt
|
||||
if (link === null) return;
|
||||
|
||||
const response = await fetch(link);
|
||||
const text = await response.text();
|
||||
const doc = new DOMParser().parseFromString(text, 'text/html');
|
||||
|
||||
const scraper = new CourseCatalogScraper(SiteSupport.COURSE_CATALOG_DETAILS, doc, link);
|
||||
const tableRows = getCourseTableRows(doc);
|
||||
const courses = scraper.scrape(tableRows, false);
|
||||
|
||||
if (courses.length === 1) {
|
||||
const description = scraper.getDescription(doc);
|
||||
const row = courses[0]!;
|
||||
const course = row.course!;
|
||||
course.description = description;
|
||||
// console.log(course);
|
||||
|
||||
if (activeSchedule.courses.every(c => c.uniqueId !== course.uniqueId)) {
|
||||
console.log('adding course');
|
||||
addCourse(activeSchedule.id, course);
|
||||
} else {
|
||||
console.log('course already exists');
|
||||
}
|
||||
} else {
|
||||
console.log(courses);
|
||||
}
|
||||
};
|
||||
|
||||
const [devMode, toggleDevMode] = useDevMode(10);
|
||||
|
||||
if (devMode) {
|
||||
@@ -204,12 +248,12 @@ export default function Settings(): JSX.Element {
|
||||
<h1 className='pl-4 text-xl text-ut-burntorange font-bold'>UTRP SETTINGS & CREDITS PAGE</h1>
|
||||
</div>
|
||||
<div className='flex space-x-4'>
|
||||
<div className='flex items-center'>
|
||||
<Button variant='single' color='theme-black' onClick={handleChangelogOnClick}>
|
||||
<IconoirGitFork className='h-6 w-6 text-ut-gray' />
|
||||
<Text variant='small' className='text-ut-gray font-normal'>
|
||||
v{manifest.version} - {process.env.NODE_ENV}
|
||||
</Text>
|
||||
</div>
|
||||
</Button>
|
||||
<img src={LDIconURL} alt='LD Icon' className='h-10 w-10 rounded-lg' />
|
||||
</div>
|
||||
</header>
|
||||
@@ -382,10 +426,16 @@ export default function Settings(): JSX.Element {
|
||||
|
||||
<Divider size='auto' orientation='horizontal' />
|
||||
|
||||
<section className='my-8'>
|
||||
<section className='my-8 space-y-4'>
|
||||
<h2 className='mb-4 text-xl text-ut-black font-semibold' onClick={toggleDevMode}>
|
||||
Developer Mode
|
||||
</h2>
|
||||
<Button variant='filled' color='ut-black' onClick={handleAddCourseByUrl}>
|
||||
Add course by link
|
||||
</Button>
|
||||
<Button variant='filled' color='ut-burntorange' onClick={showMigrationDialog}>
|
||||
Show Migration Dialog
|
||||
</Button>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user