-
+ {/* Integrate the List component here */}
+ {activeSchedule ?
: null}
+
-
-
-
+
+
+ DATA UPDATED ON: 12:00 AM 02/01/2024
+
-
CANCELLED
-
-
- DATA UPDATED ON: 12:00 AM 02/01/2024
-
-
-
-
-
-);
+
+ );
}
diff --git a/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx b/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx
index ee1313e1..571ea1ae 100644
--- a/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx
+++ b/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx
@@ -1,13 +1,15 @@
+import React, { useState } from 'react';
import { Button } from '@views/components/common/Button/Button';
import { Chip, flagMap } from '@views/components/common/Chip/Chip';
import Divider from '@views/components/common/Divider/Divider';
import Text from '@views/components/common/Text/Text';
-import React from 'react';
import addCourse from 'src/pages/background/lib/addCourse';
-import openNewTab from 'src/pages/background/util/openNewTab';
+import removeCourse from 'src/pages/background/lib/removeCourse';
+import { openTabFromContentScript } from 'src/views/lib/openNewTabFromContentScript';
import { Course } from 'src/shared/types/Course';
import { UserSchedule } from 'src/shared/types/UserSchedule';
import Add from '~icons/material-symbols/add';
+import Minus from '~icons/material-symbols/minus';
import CalendarMonth from '~icons/material-symbols/calendar-month';
import CloseIcon from '~icons/material-symbols/close';
import Copy from '~icons/material-symbols/content-copy';
@@ -24,6 +26,11 @@ interface HeadingAndActionProps {
onClose: () => void;
}
+export const handleOpenCalendar = async () => { // Not sure if it's bad practice to export this
+ const url = chrome.runtime.getURL('calendar.html');
+ await openTabFromContentScript(url);
+};
+
/**
* Renders the heading component for the CoursePopup component.
*
@@ -32,6 +39,10 @@ interface HeadingAndActionProps {
*/
const HeadingAndActions: React.FC
= ({ course, onClose, activeSchedule }) => {
const { courseName, department, number: courseNumber, uniqueId, instructors, flags, schedule } = course;
+ const [courseAdded, setCourseAdded] = useState(
+ activeSchedule.courses.some(course => course.uniqueId === uniqueId)
+ );
+
const instructorString = instructors
.map(instructor => {
const { firstName, lastName } = instructor;
@@ -42,30 +53,32 @@ const HeadingAndActions: React.FC = ({ course, onClose, a
const handleCopy = () => {
navigator.clipboard.writeText(uniqueId.toString());
};
- const handleOpenCalendar = async () => {
- const url = chrome.runtime.getURL('calendar.html');
- await openNewTab(url);
- };
const handleOpenRateMyProf = async () => {
const openTabs = instructors.map(instructor => {
const { fullName } = instructor;
const url = `https://www.ratemyprofessors.com/search/professors/1255?q=${fullName}`;
- return openNewTab(url);
+ return openTabFromContentScript(url);
});
await Promise.all(openTabs);
};
const handleOpenCES = async () => {
// TODO: does not look up the professor just takes you to the page
const cisUrl = 'https://utexas.bluera.com/utexas/rpvl.aspx?rid=d3db767b-049f-46c5-9a67-29c21c29c580®l=en-US';
- await openNewTab(cisUrl);
+ await openTabFromContentScript(cisUrl);
};
const handleOpenPastSyllabi = async () => {
// not specific to professor
const url = `https://utdirect.utexas.edu/apps/student/coursedocs/nlogon/?year=&semester=&department=${department}&course_number=${courseNumber}&course_title=${courseName}&unique=&instructor_first=&instructor_last=&course_type=In+Residence&search=Search`;
- await openNewTab(url);
+ await openTabFromContentScript(url);
};
- const handleAddCourse = async () => {
- await addCourse(activeSchedule.name, course);
+ const handleAddOrRemoveCourse = async () => {
+ if (!courseAdded) {
+ await addCourse(activeSchedule.name, course);
+ }
+ else {
+ await removeCourse(activeSchedule.name, course);
+ }
+ setCourseAdded(!courseAdded);
};
return (
@@ -124,8 +137,8 @@ const HeadingAndActions: React.FC = ({ course, onClose, a
Past Syllabi
-
- Add Course
+
+ {!courseAdded ? 'Add Course' : 'Remove Course'}
diff --git a/src/views/lib/openNewTabFromContentScript.ts b/src/views/lib/openNewTabFromContentScript.ts
new file mode 100644
index 00000000..cf48d447
--- /dev/null
+++ b/src/views/lib/openNewTabFromContentScript.ts
@@ -0,0 +1,25 @@
+import { createMessenger } from "chrome-extension-toolkit";
+
+type MyMessages = {
+ openNewTab: {
+ data: { url: string };
+ };
+ };
+
+const messenger = createMessenger('background');
+
+/**
+ * Content scripts and background scripts are isolated environments.
+ * Content scripts are where our code interacting with the webpage lives,
+ * whereas the background script is where we can open a tab from.
+ * This function allows us to open a new tab from the content script by communicating
+ * with the background script.
+ */
+export async function openTabFromContentScript(url: string) {
+ // @ts-ignore
+ messenger.openNewTab({ url }).then(() => {
+ console.log('New tab opened with URL:', url);
+ }).catch((error) => {
+ console.error('Error opening new tab:', error);
+ });
+}