Created Injecting code to UT Pages (markdown)
85
Injecting-code-to-UT-Pages.md
Normal file
85
Injecting-code-to-UT-Pages.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Code Injection Guide
|
||||||
|
|
||||||
|
This page documents how we inject code into supported pages across the UT Austin web ecosystem.
|
||||||
|
|
||||||
|
# Choosing a page to inject on
|
||||||
|
Current URL is obtained through `window.location.href`
|
||||||
|
|
||||||
|
## siteSupport
|
||||||
|
Contains enum to determine what page a user is on. For example
|
||||||
|
```ts
|
||||||
|
if (url.includes('my.utexas.edu/student/student/index') || url.includes('my.utexas.edu/student/')) {
|
||||||
|
return SiteSupport.MY_UT;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## renderComponent
|
||||||
|
Found in `index.tsx`, the `renderComponent` function is a utility used by the extension to inject React components into websites (and other supported pages). It creates a new div and appends it to the document body. It then uses React’s createRoot to render the React component inside this container.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const renderComponent = (Component: React.ComponentType) => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.id = 'extension-root';
|
||||||
|
document.body.appendChild(container);
|
||||||
|
|
||||||
|
createRoot(container).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<Component />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
After a site is determined, components are rendered in `index.tsx`. For example
|
||||||
|
|
||||||
|
```ts
|
||||||
|
if (support === SiteSupport.COURSE_CATALOG_DETAILS || support === SiteSupport.COURSE_CATALOG_LIST) {
|
||||||
|
renderComponent(() => <CourseCatalogMain support={support} />);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (support === SiteSupport.MY_UT) {
|
||||||
|
renderComponent(InjectedButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (support === SiteSupport.COURSE_CATALOG_SEARCH) {
|
||||||
|
renderComponent(DaysCheckbox);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
## CourseCatalogMain
|
||||||
|
|
||||||
|
Relevant page:
|
||||||
|

|
||||||
|
|
||||||
|
`<ExtensionRoot>` used to prevent the native page styles from being overridden with our own.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
return (
|
||||||
|
<ExtensionRoot>
|
||||||
|
<NewSearchLink />
|
||||||
|
<RecruitmentBanner />
|
||||||
|
<TableHead>Plus</TableHead>
|
||||||
|
{rows.map(
|
||||||
|
row =>
|
||||||
|
row.course && (
|
||||||
|
<TableRow
|
||||||
|
key={row.course.uniqueId}
|
||||||
|
row={row}
|
||||||
|
isSelected={row.course.uniqueId === selectedCourse?.uniqueId}
|
||||||
|
activeSchedule={activeSchedule}
|
||||||
|
onClick={handleRowButtonClick(row.course)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
<CourseCatalogInjectedPopup
|
||||||
|
course={selectedCourse!} // always defined when showPopup is true
|
||||||
|
show={showPopup}
|
||||||
|
onClose={() => setShowPopup(false)}
|
||||||
|
afterLeave={() => setSelectedCourse(null)}
|
||||||
|
/>
|
||||||
|
{enableScrollToLoad && <AutoLoad addRows={addRows} />}
|
||||||
|
</ExtensionRoot>
|
||||||
|
);
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user