From 19635435c47a92a9e8fa8848b67bd8c6c645b9bf Mon Sep 17 00:00:00 2001 From: Abhinav Chadaga Date: Thu, 22 Feb 2024 17:19:26 -0600 Subject: [PATCH] trying to get the CES stuff to work --- src/manifest.ts | 1 + src/pages/background/background.ts | 2 + src/pages/background/handler/CESHandler.ts | 53 +++++++++++++++++++ src/pages/content/index.tsx | 10 +++- src/shared/messages/CESMessage.ts | 8 +++ src/shared/messages/index.ts | 3 +- .../Description.tsx | 2 + .../HeadingAndActions.tsx | 30 ++++++----- src/views/lib/getSiteSupport.ts | 4 ++ 9 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 src/pages/background/handler/CESHandler.ts create mode 100644 src/shared/messages/CESMessage.ts diff --git a/src/manifest.ts b/src/manifest.ts index 937d25f51..e85dbc544 100644 --- a/src/manifest.ts +++ b/src/manifest.ts @@ -16,6 +16,7 @@ const HOST_PERMISSIONS: string[] = [ '*://*.catalog.utexas.edu/ribbit/', '*://*.registrar.utexas.edu/schedules/*', '*://*.login.utexas.edu/login/*', + 'https://utexas.bluera.com/*', ]; const manifest = defineManifest(async () => ({ diff --git a/src/pages/background/background.ts b/src/pages/background/background.ts index b42599989..e98e12959 100644 --- a/src/pages/background/background.ts +++ b/src/pages/background/background.ts @@ -3,6 +3,7 @@ import { MessageListener } from 'chrome-extension-toolkit'; import onInstall from './events/onInstall'; import onServiceWorkerAlive from './events/onServiceWorkerAlive'; import onUpdate from './events/onUpdate'; +import CESHandler from './handler/CESHandler'; import browserActionHandler from './handler/browserActionHandler'; import tabManagementHandler from './handler/tabManagementHandler'; import userScheduleHandler from './handler/userScheduleHandler'; @@ -31,6 +32,7 @@ const messageListener = new MessageListener({ ...browserActionHandler, ...tabManagementHandler, ...userScheduleHandler, + ...CESHandler, }); messageListener.listen(); diff --git a/src/pages/background/handler/CESHandler.ts b/src/pages/background/handler/CESHandler.ts new file mode 100644 index 000000000..6f1c0a9e4 --- /dev/null +++ b/src/pages/background/handler/CESHandler.ts @@ -0,0 +1,53 @@ +import { MessageHandler } from 'chrome-extension-toolkit'; +import { CESMessage } from 'src/shared/messages/CESMessage'; +import openNewTab from '../util/openNewTab'; + +const CESHandler: MessageHandler = { + openCESPage({ data, sendResponse }) { + const { instructorFirstName, instructorLastName } = data; + console.log('openCESPage', instructorFirstName, instructorLastName); + const CESFall2023Url = + 'https://utexas.bluera.com/utexas/rpvl.aspx?rid=d3db767b-049f-46c5-9a67-29c21c29c580®l=en-US'; + + openNewTab(CESFall2023Url).then(sendResponse); + }, +}; + +export default CESHandler; + +// openNewTab(CESFall2023Url).then(tab => { +// const checkTabUpdatedAndComplete = (tabId: number, changeInfo: chrome.tabs.TabChangeInfo) => { +// if (tabId === tab.id && changeInfo.status === 'complete') { +// chrome.tabs.executeScript( +// tab.id, +// { +// code: ` +// const inputElement = document.getElementById("ctl00_ContentPlaceHolder1_ViewList_tbxValue"); +// if(inputElement) { +// inputElement.value = '${instructorFirstName} ${instructorLastName}'; +// inputElement.focus(); +// const enterKeyEvent = new KeyboardEvent('keydown', {key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true}); +// inputElement.dispatchEvent(enterKeyEvent); +// } +// `, +// }, +// () => { +// if (chrome.runtime.lastError) { +// console.error(chrome.runtime.lastError.message); +// sendResponse(null); +// } else { +// sendResponse(tab); +// } +// } +// ); + +// chrome.tabs.onUpdated.removeListener(checkTabUpdatedAndComplete); +// } +// }; + +// chrome.tabs.onUpdated.addListener(checkTabUpdatedAndComplete); +// }); +// }, +// }; + +// export default CESHandler; diff --git a/src/pages/content/index.tsx b/src/pages/content/index.tsx index 4f5c3ea9e..b6e4d2375 100644 --- a/src/pages/content/index.tsx +++ b/src/pages/content/index.tsx @@ -1,7 +1,7 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; import CourseCatalogMain from '@views/components/CourseCatalogMain'; import getSiteSupport, { SiteSupport } from '@views/lib/getSiteSupport'; +import React from 'react'; +import { createRoot } from 'react-dom/client'; const support = getSiteSupport(window.location.href); @@ -16,3 +16,9 @@ if (support === SiteSupport.COURSE_CATALOG_DETAILS || support === SiteSupport.CO ); } + +if (support === SiteSupport.CES) { + alert('CES'); + const input = document.getElementById('ctl00_ContentPlaceHolder1_ViewList_tbxValue') as HTMLInputElement; + console.log(input.value); +} diff --git a/src/shared/messages/CESMessage.ts b/src/shared/messages/CESMessage.ts new file mode 100644 index 000000000..0c541f32b --- /dev/null +++ b/src/shared/messages/CESMessage.ts @@ -0,0 +1,8 @@ +export interface CESMessage { + /** + * Opens the CES page for the specified instructor + * + * @param data first and last name of the instructor + */ + openCESPage: (data: { instructorFirstName: string; instructorLastName: string }) => chrome.tabs.Tab; +} diff --git a/src/shared/messages/index.ts b/src/shared/messages/index.ts index a7f0227c4..59e142361 100644 --- a/src/shared/messages/index.ts +++ b/src/shared/messages/index.ts @@ -1,5 +1,6 @@ import { createMessenger } from 'chrome-extension-toolkit'; import BrowserActionMessages from './BrowserActionMessages'; +import { CESMessage } from './CESMessage'; import TabManagementMessages from './TabManagementMessages'; import TAB_MESSAGES from './TabMessages'; import { UserScheduleMessages } from './UserScheduleMessages'; @@ -7,7 +8,7 @@ import { UserScheduleMessages } from './UserScheduleMessages'; /** * This is a type with all the message definitions that can be sent TO the background script */ -export type BACKGROUND_MESSAGES = BrowserActionMessages & TabManagementMessages & UserScheduleMessages; +export type BACKGROUND_MESSAGES = BrowserActionMessages & TabManagementMessages & UserScheduleMessages & CESMessage; /** * A utility object that can be used to send type-safe messages to the background script diff --git a/src/views/components/injected/CourseCatalogInjectedPopup/Description.tsx b/src/views/components/injected/CourseCatalogInjectedPopup/Description.tsx index 0d8bb1184..be5be6738 100644 --- a/src/views/components/injected/CourseCatalogInjectedPopup/Description.tsx +++ b/src/views/components/injected/CourseCatalogInjectedPopup/Description.tsx @@ -7,6 +7,8 @@ interface DescriptionProps { } const Description: React.FC = ({ lines }: DescriptionProps) => { + // TODO: This needs to fetch the url and grab the description from the course catalog + // IT WILL NOT ALREADY BE IN THE COURSE OBJECT (lookat CourseDescription.tsx for an example of how to do this) const keywords = ['prerequisite', 'restricted']; return (
    diff --git a/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx b/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx index ea6548a6e..e9e03e3c3 100644 --- a/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx +++ b/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx @@ -3,12 +3,10 @@ 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, { useState } from 'react'; -import addCourse from 'src/pages/background/lib/addCourse'; -import removeCourse from 'src/pages/background/lib/removeCourse'; +import { background } from 'src/shared/messages'; import { Course } from 'src/shared/types/Course'; import Instructor from 'src/shared/types/Instructor'; import { UserSchedule } from 'src/shared/types/UserSchedule'; -import { openTabFromContentScript } from 'src/views/lib/openNewTabFromContentScript'; import Add from '~icons/material-symbols/add'; import CalendarMonth from '~icons/material-symbols/calendar-month'; import CloseIcon from '~icons/material-symbols/close'; @@ -18,6 +16,8 @@ import Mood from '~icons/material-symbols/mood'; import Remove from '~icons/material-symbols/remove'; import Reviews from '~icons/material-symbols/reviews'; +const { openNewTab, addCourse, removeCourse, openCESPage } = background; + interface HeadingAndActionProps { /* The course to display */ course: Course; @@ -30,7 +30,7 @@ interface HeadingAndActionProps { export const handleOpenCalendar = async () => { // Not sure if it's bad practice to export this const url = chrome.runtime.getURL('calendar.html'); - await openTabFromContentScript(url); + openNewTab({ url }); }; /** @@ -42,7 +42,7 @@ export const handleOpenCalendar = async () => { 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) + activeSchedule !== undefined ? activeSchedule.courses.some(course => course.uniqueId === uniqueId) : false ); const capitalizeString = (str: string) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); @@ -62,27 +62,33 @@ const HeadingAndActions: React.FC = ({ course, onClose, a const instructorSearchTerm = getInstructorFullName(instructor); instructorSearchTerm.replace(' ', '+'); const url = `https://www.ratemyprofessors.com/search/professors/1255?q=${instructorSearchTerm}`; - return openTabFromContentScript(url); + return openNewTab({ 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 openTabFromContentScript(cisUrl); + const openTabs = instructors.map(instructor => { + let { firstName, lastName } = instructor; + firstName = capitalizeString(firstName); + lastName = capitalizeString(lastName); + return openCESPage({ instructorFirstName: firstName, instructorLastName: lastName }); + }); + await Promise.all(openTabs); }; 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 openTabFromContentScript(url); + openNewTab({ url }); }; const handleAddOrRemoveCourse = async () => { + if (!activeSchedule) return; if (!courseAdded) { - await addCourse(activeSchedule.name, course); + addCourse({ course, scheduleName: activeSchedule.name }); } else { - await removeCourse(activeSchedule.name, course); + removeCourse({ course, scheduleName: activeSchedule.name }); } - setCourseAdded(!courseAdded); + setCourseAdded(prev => !prev); }; return (
    diff --git a/src/views/lib/getSiteSupport.ts b/src/views/lib/getSiteSupport.ts index 74154a0a5..269e6acbc 100644 --- a/src/views/lib/getSiteSupport.ts +++ b/src/views/lib/getSiteSupport.ts @@ -11,6 +11,7 @@ export enum SiteSupport { WAITLIST = 'WAITLIST', EXTENSION_POPUP = 'EXTENSION_POPUP', MY_CALENDAR = 'MY_CALENDAR', + CES = 'CES', } /** @@ -39,5 +40,8 @@ export default function getSiteSupport(url: string): SiteSupport | null { if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) { return SiteSupport.WAITLIST; } + if (url.includes('utexas.bluera')) { + return SiteSupport.CES; + } return null; }