refactor: Replace Webpack with Vite (#53)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Course, ScrapedRow } from '@shared/types/Course';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Course, ScrapedRow } from 'src/shared/types/Course';
|
||||
import { useKeyPress } from '../hooks/useKeyPress';
|
||||
import useSchedules from '../hooks/useSchedules';
|
||||
import { CourseCatalogScraper } from '../lib/CourseCatalogScraper';
|
||||
@@ -7,13 +7,12 @@ import getCourseTableRows from '../lib/getCourseTableRows';
|
||||
import { SiteSupport } from '../lib/getSiteSupport';
|
||||
import { populateSearchInputs } from '../lib/populateSearchInputs';
|
||||
import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot';
|
||||
import Icon from './common/Icon/Icon';
|
||||
import Text from './common/Text/Text';
|
||||
import AutoLoad from './injected/AutoLoad/AutoLoad';
|
||||
import CoursePopup from './injected/CoursePopup/CoursePopup';
|
||||
import RecruitmentBanner from './injected/RecruitmentBanner/RecruitmentBanner';
|
||||
import TableHead from './injected/TableHead';
|
||||
import TableRow from './injected/TableRow/TableRow';
|
||||
import TableSubheading from './injected/TableSubheading/TableSubheading';
|
||||
|
||||
interface Props {
|
||||
support: SiteSupport.COURSE_CATALOG_DETAILS | SiteSupport.COURSE_CATALOG_LIST;
|
||||
@@ -33,7 +32,7 @@ export default function CourseCatalogMain({ support }: Props) {
|
||||
useEffect(() => {
|
||||
const tableRows = getCourseTableRows(document);
|
||||
const ccs = new CourseCatalogScraper(support);
|
||||
const scrapedRows = ccs.scrape(tableRows);
|
||||
const scrapedRows = ccs.scrape(tableRows, true);
|
||||
setRows(scrapedRows);
|
||||
}, [support]);
|
||||
|
||||
@@ -64,10 +63,10 @@ export default function CourseCatalogMain({ support }: Props) {
|
||||
<ExtensionRoot>
|
||||
<RecruitmentBanner />
|
||||
<TableHead>Plus</TableHead>
|
||||
{rows.map(row => {
|
||||
{rows.map((row, i) => {
|
||||
if (!row.course) {
|
||||
// TODO: handle the course section headers
|
||||
return null;
|
||||
return <TableSubheading key={row.element.innerText + i.toString()} row={row} />;
|
||||
}
|
||||
return (
|
||||
<TableRow
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import React from 'react';
|
||||
import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot';
|
||||
|
||||
export default function MyCalendarMain() {
|
||||
return <ExtensionRoot>MyCalendarMain</ExtensionRoot>;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { background } from '@shared/messages';
|
||||
import React from 'react';
|
||||
import { background } from 'src/shared/messages';
|
||||
import useSchedules from '../hooks/useSchedules';
|
||||
import { Button } from './common/Button/Button';
|
||||
import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'sass:color';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
.button {
|
||||
background-color: #000;
|
||||
@@ -7,9 +8,8 @@
|
||||
margin: 10px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
box-shadow: rgba(0, 0, 0, 0.4) 2px 2px 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
font-family: 'Inter';
|
||||
|
||||
display: flex;
|
||||
@@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
&:active {
|
||||
animation: click_animation 0.2s ease-in-out;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
@@ -30,20 +30,20 @@
|
||||
opacity: 0.5 !important;
|
||||
|
||||
&:active {
|
||||
animation: none !important;
|
||||
transform: unset;
|
||||
}
|
||||
}
|
||||
|
||||
@each $color,
|
||||
$value
|
||||
in (
|
||||
primary: $burnt_orange,
|
||||
secondary: $charcoal,
|
||||
tertiary: $bluebonnet,
|
||||
danger: $speedway_brick,
|
||||
warning: $tangerine,
|
||||
success: $turtle_pond,
|
||||
info: $turquoise
|
||||
primary: colors.$burnt_orange,
|
||||
secondary: colors.$charcoal,
|
||||
tertiary: colors.$bluebonnet,
|
||||
danger: colors.$speedway_brick,
|
||||
warning: colors.$tangerine,
|
||||
success: colors.$turtle_pond,
|
||||
info: colors.$turquoise
|
||||
)
|
||||
{
|
||||
&.#{$color} {
|
||||
@@ -51,12 +51,12 @@
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background-color: lighten($value, 10%);
|
||||
background-color: color.adjust($value, $lightness: 10%);
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:focus-visible,
|
||||
&:active {
|
||||
background-color: darken($value, 10%);
|
||||
background-color: color.adjust($value, $lightness: -10%);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
@@ -65,15 +65,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes click_animation {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
.card {
|
||||
background: $white;
|
||||
background: colors.$white;
|
||||
border: 0.5px dotted #c3cee0;
|
||||
box-sizing: border-box;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
hr {
|
||||
border: 1px solid $limestone;
|
||||
border: 1px solid colors.$limestone;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { Color } from 'src/views/styles/colors.module.scss';
|
||||
import React from 'react';
|
||||
import { Color } from '@views/styles/colors.module.scss';
|
||||
import styles from './Divider.module.scss';
|
||||
|
||||
export type Props = {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@import 'src/views/styles/fonts.module.scss';
|
||||
@use 'src/views/styles/fonts.module.scss';
|
||||
|
||||
.icon {
|
||||
font-family: 'Material Icons Round';
|
||||
font-weight: $normal_weight;
|
||||
font-weight: fonts.$normal_weight;
|
||||
font-style: normal;
|
||||
font-size: $medium_size;
|
||||
font-size: fonts.$medium_size;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import colors, { Color } from 'src/views/styles/colors.module.scss';
|
||||
import fonts, { Size, Weight } from 'src/views/styles/fonts.module.scss';
|
||||
import colors, { Color } from '@views/styles/colors.module.scss';
|
||||
import fonts, { Size } from '@views/styles/fonts.module.scss';
|
||||
import styles from './Icon.module.scss';
|
||||
import { MaterialIconCode } from './MaterialIcons';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export type Props = {
|
||||
name: MaterialIconCode;
|
||||
className?: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { background } from '@shared/messages';
|
||||
import classNames from 'classnames';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { background } from 'src/shared/messages';
|
||||
import Text, { TextProps } from '../Text/Text';
|
||||
import styles from './Link.module.scss';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
@@ -18,7 +18,7 @@
|
||||
.body {
|
||||
overflow-y: auto;
|
||||
z-index: 2147483647;
|
||||
background-color: $white;
|
||||
background-color: colors.$white;
|
||||
box-shadow: 0px 12px 30px 0px #323e5f29;
|
||||
transition: box-shadow 0.15s;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
$spinner-border-width: 10px;
|
||||
|
||||
.spinner {
|
||||
border: 1px solid $charcoal;
|
||||
border: 1px solid colors.$charcoal;
|
||||
border-width: $spinner-border-width;
|
||||
border-top: $spinner-border-width solid $tangerine;
|
||||
border-top: $spinner-border-width solid colors.$tangerine;
|
||||
margin: 0 auto 15px auto;
|
||||
border-radius: 50%;
|
||||
width: 60px;
|
||||
|
||||
@@ -1,59 +1,60 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
@use 'src/views/styles/fonts.module.scss';
|
||||
|
||||
.text {
|
||||
font-family: 'Inter', sans-serif;
|
||||
color: $charcoal;
|
||||
color: colors.$charcoal;
|
||||
line-height: initial;
|
||||
}
|
||||
|
||||
.light_weight {
|
||||
font-weight: $light_weight;
|
||||
font-weight: fonts.$light_weight;
|
||||
}
|
||||
|
||||
.regular_weight {
|
||||
font-weight: $regular_weight;
|
||||
font-weight: fonts.$regular_weight;
|
||||
}
|
||||
|
||||
.normal_weight {
|
||||
font-weight: $normal_weight;
|
||||
font-weight: fonts.$normal_weight;
|
||||
}
|
||||
|
||||
.semi_bold_weight {
|
||||
font-weight: $semi_bold_weight;
|
||||
font-weight: fonts.$semi_bold_weight;
|
||||
}
|
||||
|
||||
.bold_weight {
|
||||
font-weight: $bold_weight;
|
||||
font-weight: fonts.$bold_weight;
|
||||
}
|
||||
|
||||
.black_weight {
|
||||
font-weight: $black_weight;
|
||||
font-weight: fonts.$black_weight;
|
||||
}
|
||||
|
||||
.x_small_size {
|
||||
font-size: $x_small_size;
|
||||
font-size: fonts.$x_small_size;
|
||||
}
|
||||
|
||||
.xx_small_size {
|
||||
font-size: $xx_small_size;
|
||||
font-size: fonts.$xx_small_size;
|
||||
}
|
||||
|
||||
.small_size {
|
||||
font-size: $small_size;
|
||||
font-size: fonts.$small_size;
|
||||
}
|
||||
|
||||
.medium_size {
|
||||
font-size: $medium_size;
|
||||
font-size: fonts.$medium_size;
|
||||
}
|
||||
|
||||
.large_size {
|
||||
font-size: $large_size;
|
||||
font-size: fonts.$large_size;
|
||||
}
|
||||
|
||||
.x_large_size {
|
||||
font-size: $x_large_size;
|
||||
font-size: fonts.$x_large_size;
|
||||
}
|
||||
|
||||
.xx_large_size {
|
||||
font-size: $xx_large_size;
|
||||
font-size: fonts.$xx_large_size;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import classNames from 'classnames';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import colors, { Color } from 'src/views/styles/colors.module.scss';
|
||||
import fonts, { Size, Weight } from 'src/views/styles/fonts.module.scss';
|
||||
import colors, { Color } from '@views/styles/colors.module.scss';
|
||||
import { Size, Weight } from '@views/styles/fonts.module.scss';
|
||||
import styles from './Text.module.scss';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export type TextProps = {
|
||||
color?: Color;
|
||||
weight?: Weight;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { ScrapedRow } from '@shared/types/Course';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { ScrapedRow } from 'src/shared/types/Course';
|
||||
import useInfiniteScroll from 'src/views/hooks/useInfiniteScroll';
|
||||
import { CourseCatalogScraper } from 'src/views/lib/CourseCatalogScraper';
|
||||
import { SiteSupport } from 'src/views/lib/getSiteSupport';
|
||||
import useInfiniteScroll from '@views/hooks/useInfiniteScroll';
|
||||
import { CourseCatalogScraper } from '@views/lib/CourseCatalogScraper';
|
||||
import { SiteSupport } from '@views/lib/getSiteSupport';
|
||||
import {
|
||||
loadNextCourseCatalogPage,
|
||||
AutoLoadStatus,
|
||||
loadNextCourseCatalogPage,
|
||||
removePaginationButtons,
|
||||
} from 'src/views/lib/loadNextCourseCatalogPage';
|
||||
import Spinner from '../../common/Spinner/Spinner';
|
||||
} from '@views/lib/loadNextCourseCatalogPage';
|
||||
import styles from './AutoLoad.module.scss';
|
||||
|
||||
type Props = {
|
||||
@@ -53,16 +52,21 @@ export default function AutoLoad({ addRows }: Props) {
|
||||
addRows(scrapedRows);
|
||||
}, [addRows]);
|
||||
|
||||
if (!container || status === AutoLoadStatus.IDLE) {
|
||||
if (!container || status === AutoLoadStatus.DONE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createPortal(
|
||||
<div>
|
||||
{status === AutoLoadStatus.LOADING && (
|
||||
<div>
|
||||
<Spinner />
|
||||
<h2>Loading Next Page...</h2>
|
||||
{status !== AutoLoadStatus.ERROR && (
|
||||
<div
|
||||
style={{
|
||||
height: '500px',
|
||||
backgroundColor: '#f4f4f4',
|
||||
}}
|
||||
>
|
||||
{/* <Spinner />
|
||||
<h2>Loading Next Page...</h2> */}
|
||||
</div>
|
||||
)}
|
||||
{status === AutoLoadStatus.ERROR && (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
.container {
|
||||
margin: 20px;
|
||||
@@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
.restriction {
|
||||
color: $speedway_brick;
|
||||
color: colors.$speedway_brick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Course } from '@shared/types/Course';
|
||||
import classNames from 'classnames';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Course } from 'src/shared/types/Course';
|
||||
import Spinner from 'src/views/components/common/Spinner/Spinner';
|
||||
import Text from 'src/views/components/common/Text/Text';
|
||||
import { CourseCatalogScraper } from 'src/views/lib/CourseCatalogScraper';
|
||||
import { SiteSupport } from 'src/views/lib/getSiteSupport';
|
||||
import Spinner from '@views/components/common/Spinner/Spinner';
|
||||
import Text from '@views/components/common/Text/Text';
|
||||
import { CourseCatalogScraper } from '@views/lib/CourseCatalogScraper';
|
||||
import { SiteSupport } from '@views/lib/getSiteSupport';
|
||||
import Card from '../../../common/Card/Card';
|
||||
import styles from './CourseDescription.module.scss';
|
||||
|
||||
@@ -18,6 +18,9 @@ enum LoadStatus {
|
||||
ERROR = 'ERROR',
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export default function CourseDescription({ course }: Props) {
|
||||
const [description, setDescription] = useState<string[]>([]);
|
||||
const [status, setStatus] = useState<LoadStatus>(LoadStatus.LOADING);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { background } from '@shared/messages';
|
||||
import { Course } from '@shared/types/Course';
|
||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||
import React from 'react';
|
||||
import { background } from 'src/shared/messages';
|
||||
import { Course } from 'src/shared/types/Course';
|
||||
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||
import { Button } from 'src/views/components/common/Button/Button';
|
||||
import Card from 'src/views/components/common/Card/Card';
|
||||
import Icon from 'src/views/components/common/Icon/Icon';
|
||||
import Text from 'src/views/components/common/Text/Text';
|
||||
import { Button } from '@views/components/common/Button/Button';
|
||||
import Card from '@views/components/common/Card/Card';
|
||||
import Icon from '@views/components/common/Icon/Icon';
|
||||
import Text from '@views/components/common/Text/Text';
|
||||
import styles from './CourseButtons.module.scss';
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Course } from '@shared/types/Course';
|
||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||
import React from 'react';
|
||||
import { Course } from 'src/shared/types/Course';
|
||||
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||
import Card from 'src/views/components/common/Card/Card';
|
||||
import Icon from 'src/views/components/common/Icon/Icon';
|
||||
import Link from 'src/views/components/common/Link/Link';
|
||||
import Text from 'src/views/components/common/Text/Text';
|
||||
import Card from '@views/components/common/Card/Card';
|
||||
import Icon from '@views/components/common/Icon/Icon';
|
||||
import Link from '@views/components/common/Link/Link';
|
||||
import Text from '@views/components/common/Text/Text';
|
||||
import CourseButtons from './CourseButtons/CourseButtons';
|
||||
import styles from './CourseHeader.module.scss';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Course } from '@shared/types/Course';
|
||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||
import React from 'react';
|
||||
import { Course } from 'src/shared/types/Course';
|
||||
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||
import Popup from '../../common/Popup/Popup';
|
||||
import CourseDescription from './CourseDescription/CourseDescription';
|
||||
import CourseHeader from './CourseHeader/CourseHeader';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
@use 'src/views/styles/elevation.module.scss';
|
||||
|
||||
.chartContainer {
|
||||
height: 250px;
|
||||
@@ -14,11 +15,11 @@
|
||||
justify-content: center;
|
||||
|
||||
select {
|
||||
z-index: $MAX_Z_INDEX;
|
||||
z-index: elevation.$MAX_Z_INDEX;
|
||||
padding: 4px;
|
||||
font-family: 'Inter';
|
||||
border-radius: 8px;
|
||||
border-color: $charcoal;
|
||||
border-color: colors.$charcoal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import HighchartsReact from 'highcharts-react-official';
|
||||
import { Course, Semester } from '@shared/types/Course';
|
||||
import { Distribution, LetterGrade } from '@shared/types/Distribution';
|
||||
import Highcharts from 'highcharts';
|
||||
import Card from 'src/views/components/common/Card/Card';
|
||||
import { Course, Semester } from 'src/shared/types/Course';
|
||||
import colors from 'src/views/styles/colors.module.scss';
|
||||
import Spinner from 'src/views/components/common/Spinner/Spinner';
|
||||
import Text from 'src/views/components/common/Text/Text';
|
||||
import Icon from 'src/views/components/common/Icon/Icon';
|
||||
import { Distribution, LetterGrade } from 'src/shared/types/Distribution';
|
||||
import HighchartsReact from 'highcharts-react-official';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import Card from '@views/components/common/Card/Card';
|
||||
import Icon from '@views/components/common/Icon/Icon';
|
||||
import Spinner from '@views/components/common/Spinner/Spinner';
|
||||
import Text from '@views/components/common/Text/Text';
|
||||
import {
|
||||
NoDataError,
|
||||
queryAggregateDistribution,
|
||||
querySemesterDistribution,
|
||||
} from 'src/views/lib/database/queryDistribution';
|
||||
} from '@views/lib/database/queryDistribution';
|
||||
import colors from '@views/styles/colors.module.scss';
|
||||
import styles from './GradeDistribution.module.scss';
|
||||
|
||||
enum DataStatus {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
.container {
|
||||
background-color: $burnt_orange;
|
||||
background-color: colors.$burnt_orange;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
|
||||
@@ -15,6 +15,9 @@ export default function TableHead({ children }: PropsWithChildren) {
|
||||
const lastTableHeadCell = document.querySelector('table thead th:last-child');
|
||||
lastTableHeadCell!.after(container);
|
||||
setContainer(container);
|
||||
return () => {
|
||||
container.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (!container) {
|
||||
|
||||
@@ -1,33 +1,21 @@
|
||||
@import 'src/views/styles/base.module.scss';
|
||||
|
||||
.rowButton {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.selectedRow {
|
||||
* {
|
||||
background: $burnt_orange !important;
|
||||
color: white !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.inActiveSchedule {
|
||||
* {
|
||||
color: $turtle_pond !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
}
|
||||
|
||||
.isConflict {
|
||||
* {
|
||||
color: $speedway_brick !important;
|
||||
font-weight: normal !important;
|
||||
text-decoration: line-through !important;
|
||||
}
|
||||
}
|
||||
@use 'src/views/styles/colors.module.scss';
|
||||
|
||||
.row {
|
||||
> td:first-child {
|
||||
padding-left: 12px !important;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
> td:last-child {
|
||||
padding-right: 12px !important;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
> * {
|
||||
transition: background-color 0.1s ease-in-out;
|
||||
}
|
||||
.conflictTooltip {
|
||||
position: relative;
|
||||
display: none;
|
||||
@@ -54,4 +42,46 @@
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
|
||||
// :global(ul.flag) li {
|
||||
// transform: scale(1.5); // omg the flags are on ONE LONG GIF FILE AND SHIFTED BY Y COORDINATES
|
||||
// }
|
||||
}
|
||||
|
||||
.rowButton {
|
||||
margin: 0.25rem 0;
|
||||
&:active {
|
||||
transform: scale(0.92);
|
||||
}
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
place-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.selectedRow {
|
||||
> * {
|
||||
background: colors.$burnt_orange !important;
|
||||
color: white !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.rowButton {
|
||||
background: colors.$burnt_orange !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.inActiveSchedule {
|
||||
* {
|
||||
color: colors.$turtle_pond !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
}
|
||||
|
||||
.isConflict {
|
||||
* {
|
||||
color: colors.$speedway_brick !important;
|
||||
font-weight: normal !important;
|
||||
text-decoration: line-through !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Course, ScrapedRow } from '@shared/types/Course';
|
||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Course, ScrapedRow } from 'src/shared/types/Course';
|
||||
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||
import { Button } from '../../common/Button/Button';
|
||||
import Icon from '../../common/Icon/Icon';
|
||||
import Text from '../../common/Text/Text';
|
||||
@@ -29,6 +29,7 @@ export default function TableRow({ row, isSelected, activeSchedule, onClick }: P
|
||||
useEffect(() => {
|
||||
element.classList.add(styles.row);
|
||||
const portalContainer = document.createElement('td');
|
||||
portalContainer.style.textAlign = 'right';
|
||||
const lastTableCell = element.querySelector('td:last-child');
|
||||
lastTableCell!.after(portalContainer);
|
||||
setContainer(portalContainer);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@use 'src/views/styles/fonts.module.scss';
|
||||
|
||||
.subheader {
|
||||
h2 {
|
||||
font-size: fonts.$medium_size;
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ScrapedRow } from '@shared/types/Course';
|
||||
import { useEffect } from 'react';
|
||||
import styles from './TableSubheading.module.scss';
|
||||
|
||||
interface Props {
|
||||
row: ScrapedRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* This component is injected into each row of the course catalog table.
|
||||
* @returns a react portal to the new td in the column or null if the column has not been created yet.
|
||||
*/
|
||||
export default function TableSubheading({ row }: Props) {
|
||||
const { element } = row;
|
||||
|
||||
useEffect(() => {
|
||||
element.classList.add(styles.subheader);
|
||||
|
||||
return () => {
|
||||
element.classList.remove(styles.subheader);
|
||||
};
|
||||
}, [element]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import { useEffect } from 'react';
|
||||
* @returns isLoading boolean to indicate if the callback is currently being executed
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export default function useInfiniteScroll(
|
||||
callback: () => Promise<void> | void,
|
||||
deps?: React.DependencyList | undefined
|
||||
@@ -13,13 +16,15 @@ export default function useInfiniteScroll(
|
||||
const isScrolling = () => {
|
||||
const { innerHeight } = window;
|
||||
const { scrollTop, offsetHeight } = document.documentElement;
|
||||
if (innerHeight + scrollTop >= offsetHeight - 100) {
|
||||
if (innerHeight + scrollTop >= offsetHeight - 650) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', isScrolling);
|
||||
window.addEventListener('scroll', isScrolling, {
|
||||
passive: true,
|
||||
});
|
||||
return () => window.removeEventListener('scroll', isScrolling);
|
||||
}, deps);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Serialized } from 'chrome-extension-toolkit';
|
||||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore';
|
||||
import { UserSchedule } from '@shared/types/UserSchedule';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { UserScheduleStore } from 'src/shared/storage/UserScheduleStore';
|
||||
import { UserSchedule } from 'src/shared/types/UserSchedule';
|
||||
|
||||
export default function useSchedules(): [active: UserSchedule | null, schedules: UserSchedule[]] {
|
||||
const [schedules, setSchedules] = useState<UserSchedule[]>([]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import TAB_MESSAGES from '@shared/messages/TabMessages';
|
||||
import { createUseMessage } from 'chrome-extension-toolkit';
|
||||
import TAB_MESSAGES from 'src/shared/messages/TabMessages';
|
||||
|
||||
export const useTabMessage = createUseMessage<TAB_MESSAGES>();
|
||||
export const useTabMessage = createUseMessage<TAB_MESSAGES>();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Serialized } from 'chrome-extension-toolkit';
|
||||
import { ExtensionStore } from '@shared/storage/ExtensionStore';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ExtensionStore } from 'src/shared/storage/ExtensionStore';
|
||||
|
||||
export default function useVersion(): string {
|
||||
const [version, setVersion] = useState<string>('');
|
||||
@@ -17,4 +16,3 @@ export default function useVersion(): string {
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { ContextInvalidated, createShadowDOM, onContextInvalidated } from 'chrome-extension-toolkit';
|
||||
import React from 'react';
|
||||
import { background } from 'src/shared/messages';
|
||||
import render from './lib/react';
|
||||
|
||||
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';
|
||||
import getSiteSupport, { SiteSupport } from './lib/getSiteSupport';
|
||||
import colors from './styles/colors.module.scss';
|
||||
|
||||
const support = getSiteSupport(window.location.href);
|
||||
console.log('support:', support);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Serialized } from 'chrome-extension-toolkit';
|
||||
import { Course, Status, InstructionMode, ScrapedRow, Semester } from 'src/shared/types/Course';
|
||||
import { CourseSchedule } from 'src/shared/types/CourseSchedule';
|
||||
import Instructor from 'src/shared/types/Instructor';
|
||||
import { SiteSupport } from 'src/views/lib/getSiteSupport';
|
||||
import { Course, InstructionMode, ScrapedRow, Semester, Status } from '@shared/types/Course';
|
||||
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
||||
import Instructor from '@shared/types/Instructor';
|
||||
import { SiteSupport } from '@views/lib/getSiteSupport';
|
||||
|
||||
/**
|
||||
* The selectors that we use to scrape the course catalog list table (https://utdirect.utexas.edu/apps/registrar/course_schedule/20239/results/?fos_fl=C+S&level=U&search_type_main=FIELD)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import initSqlJs from 'sql.js/dist/sql-wasm';
|
||||
|
||||
const WASM_FILE_URL = chrome.runtime.getURL('database/sql-wasm.wasm');
|
||||
const DB_FILE_URL = chrome.runtime.getURL('database/grades.db');
|
||||
import DB_FILE_URL from '@public/database/grades.db?url';
|
||||
import WASM_FILE_URL from 'sql.js/dist/sql-wasm.wasm?url';
|
||||
// import WASM_FILE_URL from '../../../../public/database/sql-wasm.wasm?url';
|
||||
|
||||
/**
|
||||
* A utility type for the SQL.js Database type
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Course, Semester } from 'src/shared/types/Course';
|
||||
import { CourseSQLRow, Distribution } from 'src/shared/types/Distribution';
|
||||
import { Course, Semester } from '@shared/types/Course';
|
||||
import { CourseSQLRow, Distribution } from '@shared/types/Distribution';
|
||||
import { initializeDB } from './initializeDB';
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@ export enum AutoLoadStatus {
|
||||
LOADING = 'LOADING',
|
||||
IDLE = 'IDLE',
|
||||
ERROR = 'ERROR',
|
||||
DONE = 'DONE',
|
||||
}
|
||||
|
||||
let isLoading = false;
|
||||
@@ -24,7 +25,7 @@ let nextPageURL = getNextButton(document)?.href;
|
||||
export async function loadNextCourseCatalogPage(): Promise<[AutoLoadStatus, HTMLTableRowElement[]]> {
|
||||
// if there is no more nextPageURL, then we have reached the end of the course catalog, so we can stop
|
||||
if (!nextPageURL) {
|
||||
return [AutoLoadStatus.IDLE, []];
|
||||
return [AutoLoadStatus.DONE, []];
|
||||
}
|
||||
// remove the next button so that we don't load the same page twice
|
||||
removePaginationButtons(document);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import './colors.module.scss';
|
||||
@import './fonts.module.scss';
|
||||
@import './elevation.module.scss';
|
||||
@import './utils.module.scss';
|
||||
@use 'colors.module.scss';
|
||||
@use 'fonts.module.scss';
|
||||
@use 'elevation.module.scss';
|
||||
@use 'utils.module.scss';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@each $weights in '100' '200' '300' '400' '500' '600' '700' '800' '900' {
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/inter-#{$weights}.woff2') format('woff2');
|
||||
src: url('@public/fonts/inter-#{$weights}.woff2') format('woff2');
|
||||
font-display: auto;
|
||||
font-style: normal;
|
||||
font-weight: #{$weights};
|
||||
@@ -13,7 +13,7 @@
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
font-weight: 400;
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/material-icons.woff2') format('woff2');
|
||||
src: url('@public/fonts/material-icons.woff2') format('woff2');
|
||||
}
|
||||
|
||||
$light_weight: 300;
|
||||
|
||||
Reference in New Issue
Block a user