diff --git a/package-lock.json b/package-lock.json
index 4b2fabbd..c1547496 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"chrome-extension-toolkit": "^0.0.22",
+ "classnames": "^2.3.2",
"clean-webpack-plugin": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -4702,6 +4703,11 @@
"node": ">=6.0"
}
},
+ "node_modules/classnames": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+ "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+ },
"node_modules/clean-css": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",
@@ -20674,6 +20680,11 @@
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
},
+ "classnames": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+ "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+ },
"clean-css": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",
diff --git a/package.json b/package.json
index 1435b782..3a05fe5d 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
},
"dependencies": {
"chrome-extension-toolkit": "^0.0.22",
+ "classnames": "^2.3.2",
"clean-webpack-plugin": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -75,4 +76,4 @@
"webpack-build-notifier": "^2.3.0",
"webpack-dev-server": "^4.11.1"
}
-}
\ No newline at end of file
+}
diff --git a/src/views/reactDevtools.ts b/src/debug/reactDevtools.ts
similarity index 100%
rename from src/views/reactDevtools.ts
rename to src/debug/reactDevtools.ts
diff --git a/src/views/components/CourseCatalogMain.tsx b/src/views/components/CourseCatalogMain.tsx
new file mode 100644
index 00000000..5755c6b2
--- /dev/null
+++ b/src/views/components/CourseCatalogMain.tsx
@@ -0,0 +1,16 @@
+import React, { useEffect, useMemo } from 'react';
+import { bMessenger } from 'src/shared/messages';
+import { SiteSupport } from '../lib/getSiteSupport';
+import { Button } from './common/Button/Button';
+
+interface Props {
+ support: SiteSupport[];
+}
+
+export default function CourseCatalogMain(props: Props) {
+ const openGoogle = () => {
+ bMessenger.openNewTab({ url: 'https://google.com' });
+ };
+
+ return ;
+}
diff --git a/src/views/popup/PopupMain.tsx b/src/views/components/PopupMain.tsx
similarity index 100%
rename from src/views/popup/PopupMain.tsx
rename to src/views/components/PopupMain.tsx
diff --git a/src/views/content/components/Button/Button.module.scss b/src/views/components/common/Button/Button.module.scss
similarity index 100%
rename from src/views/content/components/Button/Button.module.scss
rename to src/views/components/common/Button/Button.module.scss
diff --git a/src/views/components/common/Button/Button.tsx b/src/views/components/common/Button/Button.tsx
new file mode 100644
index 00000000..b3aa96d4
--- /dev/null
+++ b/src/views/components/common/Button/Button.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import styles from './Button.module.scss';
+
+interface Props {
+ onClick?: () => void;
+}
+
+export function Button(props: React.PropsWithChildren): JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/views/content/ContentMain.tsx b/src/views/content/ContentMain.tsx
deleted file mode 100644
index 411a04fe..00000000
--- a/src/views/content/ContentMain.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react';
-
-export default function ContentMain() {
- return content
;
-}
diff --git a/src/views/content/components/Button/Button.tsx b/src/views/content/components/Button/Button.tsx
deleted file mode 100644
index d75c42e9..00000000
--- a/src/views/content/components/Button/Button.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-import { bMessenger } from 'src/shared/messages';
-import styles from './Button.module.scss';
-
-export function Button(): JSX.Element {
- const handleOpenUrl = (url: string) => () => {
- bMessenger.openNewTab({ url });
- };
-
- return (
-
- );
-}
diff --git a/src/views/content/content.module.scss b/src/views/content/content.module.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/views/content/content.tsx b/src/views/content/content.tsx
deleted file mode 100644
index ddf51144..00000000
--- a/src/views/content/content.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import { render } from 'react-dom';
-import { ContextInvalidated, createShadowDOM, onContextInvalidated } from 'chrome-extension-toolkit';
-import ContentMain from './ContentMain';
-import colors from '../styles/colors.module.scss';
-import getPageTypes, { PageType } from './lib/getPageTypes';
-import { populateSearchInputs } from './lib/courseSchedule/populateSearchInputs';
-
-const pageTypes = getPageTypes(window.location.href);
-console.log('pageTypes:', pageTypes);
-
-if (pageTypes.includes(PageType.COURSE_SCHEDULE)) {
- if (pageTypes.includes(PageType.COURSE_SCHEDULE_LIST)) {
- populateSearchInputs();
- }
- const shadowDom = createShadowDOM('ut-registration-plus-dom-container');
- render(, shadowDom.shadowRoot);
- shadowDom.addStyle('static/css/content.css');
-}
-
-onContextInvalidated(() => {
- const div = document.createElement('div');
- div.id = 'context-invalidated-container';
- document.body.appendChild(div);
- render(
- ,
- div
- );
-});
diff --git a/src/views/content/lib/getPageTypes.ts b/src/views/content/lib/getPageTypes.ts
deleted file mode 100644
index f5294aaa..00000000
--- a/src/views/content/lib/getPageTypes.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-export enum PageType {
- EXTENSION_POPUP,
- COURSE_SCHEDULE,
- COURSE_SCHEDULE_LIST,
- COURSE_DETAILS,
- UT_PLANNER,
- WAITLIST,
-}
-
-/**
- * We use this function to determine what page the user is on, and then we can use that information to determine what to do
- * @param url the url of the current page
- * @returns a list of page types that the current page is
- */
-export default function getPageTypes(url: string): PageType[] {
- if (url.includes('chrome-extension://')) {
- return [PageType.EXTENSION_POPUP];
- }
- if (url.includes('utexas.collegescheduler.com')) {
- return [PageType.UT_PLANNER];
- }
- if (url.includes('utdirect.utexas.edu/apps/registrar/course_schedule')) {
- const types = [PageType.COURSE_SCHEDULE];
- if (url.includes('results')) {
- types.push(PageType.COURSE_SCHEDULE_LIST);
- }
- if (document.querySelector('#details')) {
- types.push(PageType.COURSE_DETAILS);
- }
- return types;
- }
- if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) {
- return [PageType.WAITLIST];
- }
- return [];
-}
diff --git a/src/views/index.tsx b/src/views/index.tsx
new file mode 100644
index 00000000..ee88f117
--- /dev/null
+++ b/src/views/index.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { render } from 'react-dom';
+import { ContextInvalidated, createShadowDOM, isExtensionPopup, onContextInvalidated } from 'chrome-extension-toolkit';
+import CourseCatalogMain from './components/CourseCatalogMain';
+import colors from './styles/colors.module.scss';
+import getSiteSupport, { SiteSupport } from './lib/getSiteSupport';
+import PopupMain from './components/PopupMain';
+
+const support = getSiteSupport(window.location.href);
+
+if (isExtensionPopup()) {
+ render(, document.getElementById('root'));
+}
+
+if (support.includes(SiteSupport.COURSE_CATALOG)) {
+ const shadowDom = createShadowDOM('ut-registration-plus-dom-container');
+ render(, shadowDom.shadowRoot);
+ shadowDom.addStyle('static/css/content.css');
+}
+
+if (support.includes(SiteSupport.WAITLIST)) {
+ // TODO: Implement waitlist support
+}
+
+if (support.includes(SiteSupport.UT_PLANNER)) {
+ // TODO: Implement ut planner support
+}
+
+onContextInvalidated(() => {
+ const div = document.createElement('div');
+ div.id = 'context-invalidated-container';
+ document.body.appendChild(div);
+ render(
+ ,
+ div
+ );
+});
diff --git a/src/views/content/lib/courseSchedule/index.ts b/src/views/lib/courseSchedule/index.ts
similarity index 100%
rename from src/views/content/lib/courseSchedule/index.ts
rename to src/views/lib/courseSchedule/index.ts
diff --git a/src/views/content/lib/courseSchedule/populateSearchInputs.ts b/src/views/lib/courseSchedule/populateSearchInputs.ts
similarity index 100%
rename from src/views/content/lib/courseSchedule/populateSearchInputs.ts
rename to src/views/lib/courseSchedule/populateSearchInputs.ts
diff --git a/src/views/lib/getSiteSupport.ts b/src/views/lib/getSiteSupport.ts
new file mode 100644
index 00000000..bafe2ad2
--- /dev/null
+++ b/src/views/lib/getSiteSupport.ts
@@ -0,0 +1,36 @@
+/**
+ * An enum that represents the different types of pages that we support
+ * a given url/page can correspond to many of these enum values
+ */
+export enum SiteSupport {
+ COURSE_CATALOG = 'COURSE_CATALOG',
+ COURSE_CATALOG_LIST = 'COURSE_CATALOG_LIST',
+ COURSE_CATALOG_DETAILS = 'COURSE_CATALOG_DETAILS',
+ UT_PLANNER = 'UT_PLANNER',
+ WAITLIST = 'WAITLIST',
+}
+
+/**
+ * We use this function to determine what page the user is on, and then we can use that information to determine what to do
+ * @param url the url of the current page
+ * @returns a list of page types that the current page is
+ */
+export default function getSiteSupport(url: string): SiteSupport[] {
+ if (url.includes('utexas.collegescheduler.com')) {
+ return [SiteSupport.UT_PLANNER];
+ }
+ if (url.includes('utdirect.utexas.edu/apps/registrar/course_schedule')) {
+ const types = [SiteSupport.COURSE_CATALOG];
+ if (url.includes('results')) {
+ types.push(SiteSupport.COURSE_CATALOG_LIST);
+ }
+ if (document.querySelector('#details')) {
+ types.push(SiteSupport.COURSE_CATALOG_DETAILS);
+ }
+ return types;
+ }
+ if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) {
+ return [SiteSupport.WAITLIST];
+ }
+ return [];
+}
diff --git a/src/views/popup/popup.tsx b/src/views/popup/popup.tsx
deleted file mode 100644
index 55a219cc..00000000
--- a/src/views/popup/popup.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react';
-import { render } from 'react-dom';
-import PopupMain from './PopupMain';
-
-render(, document.getElementById('root'));
diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts
index de1bd25f..e0977718 100644
--- a/webpack/webpack.config.ts
+++ b/webpack/webpack.config.ts
@@ -26,9 +26,9 @@ export default function config(mode: Environment, manifest: chrome.runtime.Manif
// the entry points for the extension (the files that webpack will start bundling from)
const entry: Entries = {
- content: [path.resolve('src', 'views', 'content', 'content')],
+ content: [path.resolve('src', 'views')],
+ popup: [path.resolve('src', 'views')],
background: [path.resolve('src', 'background', 'background')],
- popup: [path.resolve('src', 'views', 'popup', 'popup')],
};
// the entries that need an html file to be generated
@@ -39,8 +39,8 @@ export default function config(mode: Environment, manifest: chrome.runtime.Manif
entry.debug = [path.resolve('src', 'debug')];
// we need to import react-devtools before the react code in development
- entry.content = [path.resolve('src', 'views', 'reactDevtools'), ...entry.content];
- entry.popup = [path.resolve('src', 'views', 'reactDevtools'), ...entry.popup];
+ entry.content = [path.resolve('src', 'debug', 'reactDevtools'), ...entry.content];
+ entry.popup = [path.resolve('src', 'debug', 'reactDevtools'), ...entry.popup];
}
/** @see https://webpack.js.org/configuration for documentation */