feat: injected button - add all courses from MyUT AND passing URL to handler (#291)

* feat: first button attempt

* feat: fetching each course code

* feat: adding courses function from there but idk where to get the active schedule from

* docs: todo

* feat: retrieved active schedule

* feat: button tactics

* feat: add support for my.utexas.edu

* feat: inject button into MyUT

* feat: refactor code to render components dynamically based on site

* feat: scrape course ids from MyUT and remove duplicates

* feat: site support links for classlist

* feat: add utility function to add course by URL

* feat: support additional case for course cal

* feat: duplicates

* chore: cleanup

* feat: temporary checkpoint

* feat: reroute to use new add course by url

* feat: linking to new function, cleaning up, adding messaging for course url add

* chore: unused import

* feat: relinking addCourse function to the button fingers crossed

* feat: we did it!

* chore: remove comment

* chore: cleanup cleanup

* feat: tried to handle the async stuff because of that small bug but nothing fixed. doesnt hurt tho

* feat: i have fixed it holy kevinnn

* chore: delete unused file and organization

* chore: removed unused log

* feat: better log for course add

* chore: refactor via data destructuring

* chore: pass component as prop via React.ComponentType

---------

Co-authored-by: Ethan Lanting <ethanlanting@gmail.com>
Co-authored-by: doprz <52579214+doprz@users.noreply.github.com>
This commit is contained in:
2024-11-15 19:07:37 -06:00
committed by GitHub
parent 9ad32390d1
commit c41467c617
9 changed files with 179 additions and 49 deletions

View File

@@ -0,0 +1,68 @@
import { addCourseByURL } from '@pages/background/lib/addCourseByURL';
import { Button } from '@views/components/common/Button';
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
import useSchedules from '@views/hooks/useSchedules';
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
/**
* InjectedButton component renders a button that adds courses to UTRP from official MyUT calendar
* and adds the courses to the active schedule.
*
* @returns The rendered button component or null if the container is not found.
*/
export default function InjectedButton(): JSX.Element | null {
const [container, setContainer] = useState<HTMLDivElement | null>(null);
const [activeSchedule, _] = useSchedules();
const extractCoursesFromCalendar = async () => {
const calendarElement = document.querySelector('#kgoui_Rcontent_I3_Rprimary_I1_Rcontent_I1_Rcontent_I0_Ritems');
if (!calendarElement) {
console.error('Calendar element not found');
return [];
}
const anchorTags = Array.from(calendarElement.querySelectorAll('a')).filter(
anchor => !anchor.href.includes('google.com')
);
// Make sure to remove duplicate anchorTags using set
const uniqueAnchorTags = Array.from(new Set(anchorTags.map(a => a.href)));
for (const a of uniqueAnchorTags) {
// eslint-disable-next-line no-await-in-loop
await addCourseByURL(activeSchedule, a);
}
};
useEffect(() => {
const targetElement = document.getElementById('kgoui_Rcontent_I3_Rsecondary');
if (
targetElement &&
targetElement.classList.contains('kgoui_container_responsive_asymmetric2_column_secondary')
) {
const buttonContainer = document.createElement('div');
targetElement.appendChild(buttonContainer);
setContainer(buttonContainer);
return () => {
buttonContainer.remove();
};
}
}, []);
if (!container) {
return null;
}
return ReactDOM.createPortal(
<ExtensionRoot>
<Button variant='filled' color='ut-burntorange' onClick={extractCoursesFromCalendar}>
Add Courses to UT Registration+
</Button>
</ExtensionRoot>,
container
);
}