From 374808b1c62d98a2406f14044c01673a1f6acd12 Mon Sep 17 00:00:00 2001 From: Angela Zheng <92692008+AngelaZQ1@users.noreply.github.com> Date: Wed, 8 Nov 2023 15:09:41 -0500 Subject: [PATCH 01/22] UI updates (#636) * decrease font size * italicize directions, add colon * modify neutral.300 to be the "gray" color style in figma * sidebar color updates, remove some colors that arent used * lighten sidebar hover bg color * remove background color from error icon when clicking * remove background color variable, only use blue.light * update year hover and active colors * update button colors * change transfer courses bg + hover * neutral.200 -> gray2 * remove border from transfer courses button * add + icon to add year button * move checkbox to left * move checkbox edit plan modal * change name input fields to md * decrease spacing between label and input * remove extra " * add back open year color * delete plan border width * update year active color * decrease spacing between home page title * neutral.main -> neutral.gray * remove neutral.main * use neutral.gray * fix color * more styling changes, remove GrayButton * fix neutral gray color styles --- .../emailConfirmation.controller.ts | 5 +++-- .../AddCourseModal/AddCourseButton.tsx | 14 +++++++------- .../AddCourseModal/SearchCoursesInput.tsx | 2 +- .../components/AddCourseModal/SearchResult.tsx | 2 +- .../AddCourseModal/SelectedCourse.tsx | 2 +- .../Authentication/AuthPageLayout.tsx | 6 +----- .../components/Button/BlueButton.tsx | 1 + .../components/Button/GrayButton.tsx | 18 ------------------ .../frontend-v2/components/Button/index.ts | 1 - packages/frontend-v2/components/Form/Input.tsx | 8 ++++---- .../frontend-v2/components/Form/Select.tsx | 2 +- .../components/Header/AccountOverview.tsx | 4 ++-- .../components/Plan/AddPlanModal.tsx | 14 +++++++------- .../components/Plan/AddYearButton.tsx | 7 ++++++- .../components/Plan/DeletePlanModal.tsx | 1 + .../components/Plan/EditPlanModal.tsx | 14 +++++++------- .../components/Plan/ReqErrorModal.tsx | 6 +++--- .../components/Plan/ScheduleTerm.tsx | 2 +- .../components/Plan/ScheduleYear.tsx | 10 ++++++---- .../components/Plan/TransferCourses.tsx | 16 ++++++++-------- .../components/Sidebar/SectionRequirement.tsx | 14 +++++++++----- .../frontend-v2/components/Sidebar/Sidebar.tsx | 7 ++++++- .../components/Sidebar/SidebarSection.tsx | 14 ++++++++------ packages/frontend-v2/pages/home.tsx | 12 ++++++++---- packages/frontend-v2/pages/index.tsx | 2 +- packages/frontend-v2/utils/theme/index.ts | 14 ++++---------- 26 files changed, 97 insertions(+), 101 deletions(-) delete mode 100644 packages/frontend-v2/components/Button/GrayButton.tsx diff --git a/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts b/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts index 38012a3cb..6486c7c2a 100644 --- a/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts +++ b/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts @@ -34,8 +34,9 @@ export class EmailConfirmationController { if (email instanceof Error) { throw new BadRequestException(); } - const updateResult = - await this.emailConfirmationService.confirmEmail(email); + const updateResult = await this.emailConfirmationService.confirmEmail( + email + ); if (updateResult instanceof EmailAlreadyConfirmed) { throw new BadRequestException("Email is already confirmed"); } diff --git a/packages/frontend-v2/components/AddCourseModal/AddCourseButton.tsx b/packages/frontend-v2/components/AddCourseModal/AddCourseButton.tsx index 918e121f9..61af22169 100644 --- a/packages/frontend-v2/components/AddCourseModal/AddCourseButton.tsx +++ b/packages/frontend-v2/components/AddCourseModal/AddCourseButton.tsx @@ -10,14 +10,12 @@ export const AddCourseButton: React.FC = ({ ...buttonProps }) => { const hoverStyle = { - backgroundColor: "neutral.700", - borderColor: "primary.blue.dark.300", + borderColor: "neutral.300", }; const activeStyle = { - backgroundColor: "neutral.900", - borderColor: "primary.blue.dark.300", - transform: "scale(0.96)", + backgroundColor: "neutral.200", + borderColor: "neutral.200", }; return ( @@ -27,8 +25,10 @@ export const AddCourseButton: React.FC = ({ size="md" margin="0" borderRadius="10px" - borderColor="neutral.main" - backgroundColor="neutral.main" + border="1px" + borderColor="neutral.50" + backgroundColor="neutral.50" + boxShadow="sm" _hover={hoverStyle} _active={activeStyle} color="primary.blue.light.main" diff --git a/packages/frontend-v2/components/AddCourseModal/SearchCoursesInput.tsx b/packages/frontend-v2/components/AddCourseModal/SearchCoursesInput.tsx index cc2bb528c..8a4b211b6 100644 --- a/packages/frontend-v2/components/AddCourseModal/SearchCoursesInput.tsx +++ b/packages/frontend-v2/components/AddCourseModal/SearchCoursesInput.tsx @@ -36,7 +36,7 @@ export const SearchCoursesInput: React.FC = ({ borderRadius={10} fontSize="sm" color="primary.blue.light.main" - backgroundColor="neutral.main" + backgroundColor="neutral.100" placeholder="SEARCH BY NAME, CRN, ETC." /> diff --git a/packages/frontend-v2/components/AddCourseModal/SearchResult.tsx b/packages/frontend-v2/components/AddCourseModal/SearchResult.tsx index ae49a62f4..476e0d3c7 100644 --- a/packages/frontend-v2/components/AddCourseModal/SearchResult.tsx +++ b/packages/frontend-v2/components/AddCourseModal/SearchResult.tsx @@ -33,7 +33,7 @@ export const SearchResult: React.FC = ({ {searchResult.name} - + {getCourseDisplayString(searchResult)} diff --git a/packages/frontend-v2/components/AddCourseModal/SelectedCourse.tsx b/packages/frontend-v2/components/AddCourseModal/SelectedCourse.tsx index f95f6e8e7..dae03ab5f 100644 --- a/packages/frontend-v2/components/AddCourseModal/SelectedCourse.tsx +++ b/packages/frontend-v2/components/AddCourseModal/SelectedCourse.tsx @@ -16,7 +16,7 @@ export const SelectedCourse: React.FC = ({ diff --git a/packages/frontend-v2/components/Authentication/AuthPageLayout.tsx b/packages/frontend-v2/components/Authentication/AuthPageLayout.tsx index f5c36d9e1..fe9af5b2a 100644 --- a/packages/frontend-v2/components/Authentication/AuthPageLayout.tsx +++ b/packages/frontend-v2/components/Authentication/AuthPageLayout.tsx @@ -13,11 +13,7 @@ export const AuthenticationPageLayout: React.FC< {form} - + GraduateNU app snippet = ({ }) => { return ( - ); -}; diff --git a/packages/frontend-v2/components/Button/index.ts b/packages/frontend-v2/components/Button/index.ts index fcfe0671e..bd82ab49e 100644 --- a/packages/frontend-v2/components/Button/index.ts +++ b/packages/frontend-v2/components/Button/index.ts @@ -1,2 +1 @@ export * from "./BlueButton"; -export * from "./GrayButton"; diff --git a/packages/frontend-v2/components/Form/Input.tsx b/packages/frontend-v2/components/Form/Input.tsx index 011e8e031..8ee19e614 100644 --- a/packages/frontend-v2/components/Form/Input.tsx +++ b/packages/frontend-v2/components/Form/Input.tsx @@ -23,16 +23,16 @@ export const GraduateInput = forwardRef( ({ error, helpMessage, formLabel, ...rest }, ref) => ( {formLabel && ( - + {formLabel} )} ( color="primary.blue.dark.main" size="md" fontWeight="medium" - mb="2xs" + mb="1px" > {label} diff --git a/packages/frontend-v2/components/Form/Select.tsx b/packages/frontend-v2/components/Form/Select.tsx index c14d507a8..d255feb0c 100644 --- a/packages/frontend-v2/components/Form/Select.tsx +++ b/packages/frontend-v2/components/Form/Select.tsx @@ -80,7 +80,7 @@ export const PlanSelect: React.FC = ({ color="primary.blue.dark.main" size="md" fontWeight="medium" - mb="2xs" + mb="4xs" > {label} diff --git a/packages/frontend-v2/components/Header/AccountOverview.tsx b/packages/frontend-v2/components/Header/AccountOverview.tsx index 2f6d14793..699dc9a04 100644 --- a/packages/frontend-v2/components/Header/AccountOverview.tsx +++ b/packages/frontend-v2/components/Header/AccountOverview.tsx @@ -107,7 +107,7 @@ export const AccountOverview: React.FC = ({ /> - + Email = ({ type="email" size="md" variant="outline" - borderColor="neutral.main" + borderColor="neutral.100" borderWidth="2px" borderRadius="md" /> diff --git a/packages/frontend-v2/components/Plan/AddPlanModal.tsx b/packages/frontend-v2/components/Plan/AddPlanModal.tsx index 0bf94a8c2..881973378 100644 --- a/packages/frontend-v2/components/Plan/AddPlanModal.tsx +++ b/packages/frontend-v2/components/Plan/AddPlanModal.tsx @@ -144,6 +144,13 @@ export const AddPlanModal: React.FC = ({ })} /> + setIsNoMajorSelected(!isNoMajorSelected)} + /> = ({ > No Major - setIsNoMajorSelected(!isNoMajorSelected)} - /> {!isNoMajorSelected && ( diff --git a/packages/frontend-v2/components/Plan/AddYearButton.tsx b/packages/frontend-v2/components/Plan/AddYearButton.tsx index 8afde92ac..b8ec65274 100644 --- a/packages/frontend-v2/components/Plan/AddYearButton.tsx +++ b/packages/frontend-v2/components/Plan/AddYearButton.tsx @@ -1,6 +1,7 @@ import { PlanModel } from "@graduate/common"; import { addEmptyDndYearToPlan } from "../../utils"; import { BlueButton } from "../Button"; +import { AddIcon } from "@chakra-ui/icons"; interface AddYearButton { plan: PlanModel; @@ -15,5 +16,9 @@ export const AddYearButton: React.FC = ({ const updatedPlan = addEmptyDndYearToPlan(plan); mutateStudentWithUpdatedPlan(updatedPlan); }; - return Add Year; + return ( + }> + Add Year + + ); }; diff --git a/packages/frontend-v2/components/Plan/DeletePlanModal.tsx b/packages/frontend-v2/components/Plan/DeletePlanModal.tsx index c731503d7..5467d941d 100644 --- a/packages/frontend-v2/components/Plan/DeletePlanModal.tsx +++ b/packages/frontend-v2/components/Plan/DeletePlanModal.tsx @@ -54,6 +54,7 @@ export const DeletePlanModal: React.FC = ({ icon={} aria-label="Delete plan" variant="outline" + border="1px" borderColor="primary.red.main" colorScheme="primary.red" color="primary.red.main" diff --git a/packages/frontend-v2/components/Plan/EditPlanModal.tsx b/packages/frontend-v2/components/Plan/EditPlanModal.tsx index 6ad732175..a15dd5104 100644 --- a/packages/frontend-v2/components/Plan/EditPlanModal.tsx +++ b/packages/frontend-v2/components/Plan/EditPlanModal.tsx @@ -178,6 +178,13 @@ export const EditPlanModal: React.FC = ({ plan }) => { })} /> + setIsNoMajorSelected(!isNoMajorSelected)} + /> = ({ plan }) => { > No Major - setIsNoMajorSelected(!isNoMajorSelected)} - /> {!isNoMajorSelected && ( diff --git a/packages/frontend-v2/components/Plan/ReqErrorModal.tsx b/packages/frontend-v2/components/Plan/ReqErrorModal.tsx index 81aec83fa..96ed299ba 100644 --- a/packages/frontend-v2/components/Plan/ReqErrorModal.tsx +++ b/packages/frontend-v2/components/Plan/ReqErrorModal.tsx @@ -52,7 +52,7 @@ export const ReqErrorModal: React.FC = ({ }} _active={{ background: "primary.red.900" }} onClick={() => { - setHovered(false) + setHovered(false); onOpen(); }} > @@ -70,7 +70,7 @@ export const ReqErrorModal: React.FC = ({ = ({ diff --git a/packages/frontend-v2/components/Plan/ScheduleTerm.tsx b/packages/frontend-v2/components/Plan/ScheduleTerm.tsx index 119e5b35e..8e11ab213 100644 --- a/packages/frontend-v2/components/Plan/ScheduleTerm.tsx +++ b/packages/frontend-v2/components/Plan/ScheduleTerm.tsx @@ -60,7 +60,7 @@ export const ScheduleTerm: React.FC = ({ = ({ const backgroundColor = isExpanded ? "primary.blue.dark" : "primary.blue.light"; - return ( = ({ _hover={{ backgroundColor: "primary.blue.light.600", }} + _active={{ + bg: "primary.blue.dark.700", + }} transition="background-color 0.15s ease" paddingTop="sm" paddingBottom="sm" @@ -180,8 +182,8 @@ const YearHeader: React.FC = ({ variant="ghost" color="primary.red.main" icon={} - _hover={{ bg: 'none', cursor: 'auto' }} - _active={{ bg: `${backgroundColor}.900` }} + _hover={{ bg: "none", cursor: "auto" }} + _active={{ bg: "none" }} onClick={(e) => { if (isExpanded) { e.stopPropagation(); @@ -199,7 +201,7 @@ const YearHeader: React.FC = ({ marginLeft="auto" marginRight="sm" _hover={{ bg: "white", color: "primary.red.main" }} - _active={{ bg: `${backgroundColor}.900` }} + _active={{ bg: "primary.blue.light.900" }} onClick={(e) => { // important to prevent the click from propogating upwards and triggering the toggle e.stopPropagation(); diff --git a/packages/frontend-v2/components/Plan/TransferCourses.tsx b/packages/frontend-v2/components/Plan/TransferCourses.tsx index c75b2ea92..edf293fe2 100644 --- a/packages/frontend-v2/components/Plan/TransferCourses.tsx +++ b/packages/frontend-v2/components/Plan/TransferCourses.tsx @@ -71,7 +71,7 @@ export const TransferCourses: React.FC = ({ }; return ( - + = ({ removeCourse={() => removeTransferCourse(course)} /> ))} - + = ({ = ({ cursor="pointer" userSelect="none" borderBottomWidth={isExpanded ? "2px" : "0px"} - borderBottomColor="neutral.900" + borderBottomColor="neutral.200" paddingX="md" > diff --git a/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx b/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx index e546477ed..75693f490 100644 --- a/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx +++ b/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx @@ -50,8 +50,8 @@ const SectionRequirement: React.FC = ({ const renderXOM = (requirement: IXofManyCourse) => { return (
- - Complete {requirement.numCreditsMin} credits from the following + + Complete {requirement.numCreditsMin} credits from the following: {requirement.courses.map((course, index) => ( = ({ const renderAND = (requirement: IAndCourse2) => { return (
- Complete all of the following + + Complete all of the following: + {requirement.courses.map((course, index) => ( = ({ const renderOR = (requirement: IOrCourse2) => { return (
- Complete one of the following + + Complete one of the following: + {requirement.courses.map((course, index) => ( = ({ const renderRange = (requirement: ICourseRange2) => { return ( - + Complete any course in range {requirement.subject} {requirement.idRangeStart} to {requirement.subject} {requirement.idRangeEnd}{" "} diff --git a/packages/frontend-v2/components/Sidebar/Sidebar.tsx b/packages/frontend-v2/components/Sidebar/Sidebar.tsx index 62f00113b..42048154f 100644 --- a/packages/frontend-v2/components/Sidebar/Sidebar.tsx +++ b/packages/frontend-v2/components/Sidebar/Sidebar.tsx @@ -325,7 +325,12 @@ const SidebarContainer: React.FC> = ({ children, }) => { return ( - + diff --git a/packages/frontend-v2/components/Sidebar/SidebarSection.tsx b/packages/frontend-v2/components/Sidebar/SidebarSection.tsx index 2eafef705..33b63ffd7 100644 --- a/packages/frontend-v2/components/Sidebar/SidebarSection.tsx +++ b/packages/frontend-v2/components/Sidebar/SidebarSection.tsx @@ -49,7 +49,7 @@ const SidebarSection: React.FC = ({ return ( @@ -65,10 +65,10 @@ const SidebarSection: React.FC = ({ py="md" px="md" margin="0" - backgroundColor="neutral.main" + backgroundColor="neutral.50" transition="background-color 0.25s ease" _hover={{ - backgroundColor: "neutral.900", + backgroundColor: "neutral.100", }} _active={{ backgroundColor: "neutral.200", @@ -160,7 +160,9 @@ const SidebarSection: React.FC = ({ @@ -173,8 +175,8 @@ const SidebarSection: React.FC = ({ {opened && !loading && ( <> {section.minRequirementCount < section.requirements.length && ( - - Complete {section.minRequirementCount} of the following + + Complete {section.minRequirementCount} of the following: )} {section.requirements.map((requirement, index) => ( diff --git a/packages/frontend-v2/pages/home.tsx b/packages/frontend-v2/pages/home.tsx index edfe71ec0..9b66fa0a9 100644 --- a/packages/frontend-v2/pages/home.tsx +++ b/packages/frontend-v2/pages/home.tsx @@ -101,7 +101,9 @@ const HomePage: NextPage = () => { if (student) { const plan = student.plans.find((plan) => plan.id === selectedPlanId); if (plan) { - setPreReqWarnings(getPreReqWarnings(plan.schedule, student.coursesTransfered)); + setPreReqWarnings( + getPreReqWarnings(plan.schedule, student.coursesTransfered) + ); setCoReqWarnings(getCoReqWarnings(plan.schedule)); } } @@ -170,7 +172,9 @@ const HomePage: NextPage = () => { return; } - setPreReqWarnings(getPreReqWarnings(updatedPlan.schedule, student.coursesTransfered)); + setPreReqWarnings( + getPreReqWarnings(updatedPlan.schedule, student.coursesTransfered) + ); setCoReqWarnings(getCoReqWarnings(updatedPlan.schedule)); mutateStudentWithUpdatedPlan(updatedPlan); }; @@ -222,7 +226,7 @@ const HomePage: NextPage = () => { > { mutateStudentWithUpdatedPlan={mutateStudentWithUpdatedPlan} setIsRemove={setIsRemove} /> - + )} { color="primary.red.main" fontWeight="normal" lineHeight="1" - mb="0" + mb="-12px" > Graduate diff --git a/packages/frontend-v2/utils/theme/index.ts b/packages/frontend-v2/utils/theme/index.ts index eabe0159c..892027c04 100644 --- a/packages/frontend-v2/utils/theme/index.ts +++ b/packages/frontend-v2/utils/theme/index.ts @@ -48,17 +48,11 @@ const colors = { }, }, neutral: { - main: "#e7ebf1", - 50: "#eff2f6", - 100: "#d2d7de", - 200: "#b3bcc8", - 300: "#f1f5fa", + 50: "#f4f6f9", + 100: "#e7ebf1", + 200: "#d2d8e3", + 300: "#b4bbc8", 400: "#7586a0", - 500: "#e7ebf1", - 600: "#485569", - 700: "#e2e6ec", - 800: "#1f242c", - 900: "#d2d8e2", }, states: { success: { From afb1615ec2620c6c171a4a4090b0f153bf5ea952 Mon Sep 17 00:00:00 2001 From: Daisy Kucharski <83257720+daisykucharski@users.noreply.github.com> Date: Sun, 12 Nov 2023 14:08:16 -0500 Subject: [PATCH 02/22] Implement rate limiting (#648) * Implement rate limiting * Remove default in app module --- package.json | 1 + packages/api-v2/src/app.module.ts | 13 +++++- packages/api-v2/src/auth/auth.controller.ts | 2 + yarn.lock | 46 +++++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cde392aaa..b855887a1 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "dependencies": { "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/plugin-proposal-decorators": "^7.17.8", + "@nestjs/throttler": "^5.0.1", "cross-env": "^7.0.3", "nodemailer": "^6.9.1" }, diff --git a/packages/api-v2/src/app.module.ts b/packages/api-v2/src/app.module.ts index 6b8c20b91..69b3118d4 100644 --- a/packages/api-v2/src/app.module.ts +++ b/packages/api-v2/src/app.module.ts @@ -5,10 +5,11 @@ import ormconfig from "../ormconfig"; import { StudentModule } from "./student/student.module"; import { AuthModule } from "./auth/auth.module"; import { PlanModule } from "./plan/plan.module"; -import { APP_INTERCEPTOR } from "@nestjs/core"; +import { APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core"; import { LoggingInterceptor } from "./interceptors/logging.interceptor"; import { MajorModule } from "./major/major.module"; import { EmailModule } from "./email/email.module"; +import { ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler"; @Module({ imports: [ @@ -17,6 +18,12 @@ import { EmailModule } from "./email/email.module"; envFilePath: [`.env.${process.env.NODE_ENV}.local`], isGlobal: true, }), + ThrottlerModule.forRoot([ + { + ttl: 60000, // no more than 100 requests in a minute + limit: 100, + }, + ]), StudentModule, AuthModule, PlanModule, @@ -28,6 +35,10 @@ import { EmailModule } from "./email/email.module"; provide: APP_INTERCEPTOR, useClass: LoggingInterceptor, }, + { + provide: APP_GUARD, + useClass: ThrottlerGuard, + }, ], }) export class AppModule {} diff --git a/packages/api-v2/src/auth/auth.controller.ts b/packages/api-v2/src/auth/auth.controller.ts index fbc8f6825..4bdcdb161 100644 --- a/packages/api-v2/src/auth/auth.controller.ts +++ b/packages/api-v2/src/auth/auth.controller.ts @@ -30,6 +30,7 @@ import { WeakPassword, } from "src/student/student.errors"; import { BadToken, InvalidPayload, TokenExpiredError } from "./auth.errors"; +import { Throttle } from "@nestjs/throttler"; @Controller("auth") export class AuthController { @@ -74,6 +75,7 @@ export class AuthController { return student; } + @Throttle({ default: { limit: 20, ttl: 60000 } }) // restrict to no more than 20 requests per minute @Post("login") public async login( @Res({ passthrough: true }) response: Response, diff --git a/yarn.lock b/yarn.lock index 60d975fc0..827960548 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3782,6 +3782,19 @@ __metadata: languageName: node linkType: hard +"@nestjs/throttler@npm:^5.0.1": + version: 5.0.1 + resolution: "@nestjs/throttler@npm:5.0.1" + dependencies: + md5: ^2.2.1 + peerDependencies: + "@nestjs/common": ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + "@nestjs/core": ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + reflect-metadata: ^0.1.13 + checksum: 9649fb7ea54ed97d552745b477e06bcbcc4f2ee1464af2e54c149ec8c1dab76226786013c75844589992bf2cd566d21bad11b3fbb0cd0c63ad10525361f2fae5 + languageName: node + linkType: hard + "@nestjs/typeorm@npm:^8.0.2": version: 8.1.4 resolution: "@nestjs/typeorm@npm:8.1.4" @@ -5848,6 +5861,13 @@ __metadata: languageName: node linkType: hard +"charenc@npm:0.0.2": + version: 0.0.2 + resolution: "charenc@npm:0.0.2" + checksum: 81dcadbe57e861d527faf6dd3855dc857395a1c4d6781f4847288ab23cffb7b3ee80d57c15bba7252ffe3e5e8019db767757ee7975663ad2ca0939bb8fcaf2e5 + languageName: node + linkType: hard + "chokidar@npm:3.5.3, chokidar@npm:^3.4.0, chokidar@npm:^3.5.3": version: 3.5.3 resolution: "chokidar@npm:3.5.3" @@ -6317,6 +6337,13 @@ __metadata: languageName: node linkType: hard +"crypt@npm:0.0.2": + version: 0.0.2 + resolution: "crypt@npm:0.0.2" + checksum: baf4c7bbe05df656ec230018af8cf7dbe8c14b36b98726939cef008d473f6fe7a4fad906cfea4062c93af516f1550a3f43ceb4d6615329612c6511378ed9fe34 + languageName: node + linkType: hard + "css-box-model@npm:1.2.1": version: 1.2.1 resolution: "css-box-model@npm:1.2.1" @@ -8011,6 +8038,7 @@ __metadata: "@babel/plugin-proposal-decorators": ^7.17.8 "@babel/preset-env": ^7.16.11 "@babel/preset-typescript": ^7.16.7 + "@nestjs/throttler": ^5.0.1 "@types/nodemailer": ^6.4.7 "@typescript-eslint/eslint-plugin": ^5.15.0 "@typescript-eslint/parser": ^5.15.0 @@ -8501,6 +8529,13 @@ __metadata: languageName: node linkType: hard +"is-buffer@npm:~1.1.6": + version: 1.1.6 + resolution: "is-buffer@npm:1.1.6" + checksum: 4a186d995d8bbf9153b4bd9ff9fd04ae75068fe695d29025d25e592d9488911eeece84eefbd8fa41b8ddcc0711058a71d4c466dcf6f1f6e1d83830052d8ca707 + languageName: node + linkType: hard + "is-callable@npm:^1.1.4, is-callable@npm:^1.2.6": version: 1.2.7 resolution: "is-callable@npm:1.2.7" @@ -9749,6 +9784,17 @@ __metadata: languageName: node linkType: hard +"md5@npm:^2.2.1": + version: 2.3.0 + resolution: "md5@npm:2.3.0" + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: ~1.1.6 + checksum: a63cacf4018dc9dee08c36e6f924a64ced735b37826116c905717c41cebeb41a522f7a526ba6ad578f9c80f02cb365033ccd67fe186ffbcc1a1faeb75daa9b6e + languageName: node + linkType: hard + "mdast-util-from-markdown@npm:^1.2.0": version: 1.2.0 resolution: "mdast-util-from-markdown@npm:1.2.0" From 1ac462b21a11ba111f1846cb2b74f978bd65c843 Mon Sep 17 00:00:00 2001 From: Daisy Kucharski <83257720+daisykucharski@users.noreply.github.com> Date: Sun, 12 Nov 2023 15:13:43 -0500 Subject: [PATCH 03/22] standardize requirement rendering (#657) --- packages/frontend-v2/components/Sidebar/SectionRequirement.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx b/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx index 75693f490..3657d5240 100644 --- a/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx +++ b/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx @@ -87,7 +87,7 @@ const SectionRequirement: React.FC = ({ return (
- Complete one of the following: + Complete 1 of the following: {requirement.courses.map((course, index) => ( Date: Fri, 17 Nov 2023 20:06:40 -0500 Subject: [PATCH 04/22] feat: allow temp vercel URL as origin (CORS) --- packages/api-v2/src/main.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/api-v2/src/main.ts b/packages/api-v2/src/main.ts index 86120b93f..a5f64f2a9 100644 --- a/packages/api-v2/src/main.ts +++ b/packages/api-v2/src/main.ts @@ -19,6 +19,10 @@ async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: graduateLogger, + cors: { + origin: + "https://graduatenu-frontend-v2-git-christina-move-fro-b625a5-sandboxneu.vercel.app", + }, }); /** From 2a0e02469e091a6d12dd90328bcad8990b6e630d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 14:50:38 -0500 Subject: [PATCH 05/22] Bump axios from 0.26.1 to 1.6.0 (#655) Bumps [axios](https://github.com/axios/axios) from 0.26.1 to 1.6.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v0.26.1...v1.6.0) --- updated-dependencies: - dependency-name: axios dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/common/package.json | 2 +- yarn.lock | 33 ++++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/common/package.json b/packages/common/package.json index 26a638637..e5326c87a 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -23,7 +23,7 @@ "typescript": "^4.6.2" }, "dependencies": { - "axios": "^0.26.1", + "axios": "^1.6.0", "class-validator": "^0.13.2" }, "jest": { diff --git a/yarn.lock b/yarn.lock index 827960548..e739a47b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3139,7 +3139,7 @@ __metadata: version: 0.0.0-use.local resolution: "@graduate/common@workspace:packages/common" dependencies: - axios: ^0.26.1 + axios: ^1.6.0 class-validator: ^0.13.2 jest: ^27.5.1 ts-jest: ^27.1.4 @@ -5356,12 +5356,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^0.26.1": - version: 0.26.1 - resolution: "axios@npm:0.26.1" +"axios@npm:^1.6.0": + version: 1.6.1 + resolution: "axios@npm:1.6.1" dependencies: - follow-redirects: ^1.14.8 - checksum: d9eb58ff4bc0b36a04783fc9ff760e9245c829a5a1052ee7ca6013410d427036b1d10d04e7380c02f3508c5eaf3485b1ae67bd2adbfec3683704745c8d7a6e1a + follow-redirects: ^1.15.0 + form-data: ^4.0.0 + proxy-from-env: ^1.1.0 + checksum: 573f03f59b7487d54551b16f5e155d1d130ad4864ed32d1da93d522b78a57123b34e3bde37f822a65ee297e79f1db840f9ad6514addff50d3cbf5caeed39e8dc languageName: node linkType: hard @@ -7603,7 +7605,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.8": +"follow-redirects@npm:^1.0.0": version: 1.15.2 resolution: "follow-redirects@npm:1.15.2" peerDependenciesMeta: @@ -7613,6 +7615,16 @@ __metadata: languageName: node linkType: hard +"follow-redirects@npm:^1.15.0": + version: 1.15.3 + resolution: "follow-redirects@npm:1.15.3" + peerDependenciesMeta: + debug: + optional: true + checksum: 584da22ec5420c837bd096559ebfb8fe69d82512d5585004e36a3b4a6ef6d5905780e0c74508c7b72f907d1fa2b7bd339e613859e9c304d0dc96af2027fd0231 + languageName: node + linkType: hard + "fork-ts-checker-webpack-plugin@npm:7.2.11": version: 7.2.11 resolution: "fork-ts-checker-webpack-plugin@npm:7.2.11" @@ -11355,6 +11367,13 @@ __metadata: languageName: node linkType: hard +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4 + languageName: node + linkType: hard + "psl@npm:^1.1.33": version: 1.9.0 resolution: "psl@npm:1.9.0" From e06a0e27f1edf14e7a26cd8c2b9f95d03a6f71df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 15:03:52 -0500 Subject: [PATCH 06/22] Bump next from 12.3.1 to 13.5.0 (#642) Bumps [next](https://github.com/vercel/next.js) from 12.3.1 to 13.5.0. - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](https://github.com/vercel/next.js/compare/v12.3.1...v13.5.0) --- updated-dependencies: - dependency-name: next dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/frontend-v2/package.json | 2 +- yarn.lock | 212 ++++++++++++------------------ 2 files changed, 86 insertions(+), 128 deletions(-) diff --git a/packages/frontend-v2/package.json b/packages/frontend-v2/package.json index d30d0d3c5..c2a623dce 100644 --- a/packages/frontend-v2/package.json +++ b/packages/frontend-v2/package.json @@ -19,7 +19,7 @@ "@graduate/common": "workspace:*", "framer-motion": "^6", "immer": "^9.0.15", - "next": "^12.0.0", + "next": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", diff --git a/yarn.lock b/yarn.lock index e739a47b0..cbdfe4cd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3166,7 +3166,7 @@ __metadata: eslint-config-next: 12.1.4 framer-motion: ^6 immer: ^9.0.15 - next: ^12.0.0 + next: ^13.5.0 react: ^18.2.0 react-dom: ^18.2.0 react-error-boundary: ^3.1.4 @@ -3810,10 +3810,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:12.3.1": - version: 12.3.1 - resolution: "@next/env@npm:12.3.1" - checksum: ea7f2ad9080bdec91dd9e7d84db063793717fb1e6c668ff99cdd9103b9a7f2dd0afd153f04882944d24124965f2f78cdf24dc71da3dcd5afad3a078816abc528 +"@next/env@npm:13.5.6": + version: 13.5.6 + resolution: "@next/env@npm:13.5.6" + checksum: 5e8f3f6f987a15dad3cd7b2bcac64a6382c2ec372d95d0ce6ab295eb59c9731222017eebf71ff3005932de2571f7543bce7e5c6a8c90030207fb819404138dc2 languageName: node linkType: hard @@ -3826,93 +3826,65 @@ __metadata: languageName: node linkType: hard -"@next/swc-android-arm-eabi@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-android-arm-eabi@npm:12.3.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@next/swc-android-arm64@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-android-arm64@npm:12.3.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@next/swc-darwin-arm64@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-darwin-arm64@npm:12.3.1" +"@next/swc-darwin-arm64@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-darwin-arm64@npm:13.5.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-darwin-x64@npm:12.3.1" +"@next/swc-darwin-x64@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-darwin-x64@npm:13.5.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-freebsd-x64@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-freebsd-x64@npm:12.3.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@next/swc-linux-arm-gnueabihf@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-linux-arm-gnueabihf@npm:12.3.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@next/swc-linux-arm64-gnu@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-linux-arm64-gnu@npm:12.3.1" +"@next/swc-linux-arm64-gnu@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-linux-arm64-gnu@npm:13.5.6" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-linux-arm64-musl@npm:12.3.1" +"@next/swc-linux-arm64-musl@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-linux-arm64-musl@npm:13.5.6" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-linux-x64-gnu@npm:12.3.1" +"@next/swc-linux-x64-gnu@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-linux-x64-gnu@npm:13.5.6" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-linux-x64-musl@npm:12.3.1" +"@next/swc-linux-x64-musl@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-linux-x64-musl@npm:13.5.6" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-win32-arm64-msvc@npm:12.3.1" +"@next/swc-win32-arm64-msvc@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-win32-arm64-msvc@npm:13.5.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-win32-ia32-msvc@npm:12.3.1" +"@next/swc-win32-ia32-msvc@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-win32-ia32-msvc@npm:13.5.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:12.3.1": - version: 12.3.1 - resolution: "@next/swc-win32-x64-msvc@npm:12.3.1" +"@next/swc-win32-x64-msvc@npm:13.5.6": + version: 13.5.6 + resolution: "@next/swc-win32-x64-msvc@npm:13.5.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -4023,12 +3995,12 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.4.11": - version: 0.4.11 - resolution: "@swc/helpers@npm:0.4.11" +"@swc/helpers@npm:0.5.2": + version: 0.5.2 + resolution: "@swc/helpers@npm:0.5.2" dependencies: tslib: ^2.4.0 - checksum: 736857d524b41a8a4db81094e9b027f554004e0fa3e86325d85bdb38f7e6459ce022db079edb6c61ba0f46fe8583b3e663e95f7acbd13e51b8da6c34e45bba2e + checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 languageName: node linkType: hard @@ -5724,7 +5696,7 @@ __metadata: languageName: node linkType: hard -"busboy@npm:^1.0.0": +"busboy@npm:1.6.0, busboy@npm:^1.0.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" dependencies: @@ -6000,6 +5972,13 @@ __metadata: languageName: node linkType: hard +"client-only@npm:0.0.1": + version: 0.0.1 + resolution: "client-only@npm:0.0.1" + checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8 + languageName: node + linkType: hard + "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -10381,12 +10360,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.4": - version: 3.3.4 - resolution: "nanoid@npm:3.3.4" +"nanoid@npm:^3.3.6": + version: 3.3.6 + resolution: "nanoid@npm:3.3.6" bin: nanoid: bin/nanoid.cjs - checksum: 2fddd6dee994b7676f008d3ffa4ab16035a754f4bb586c61df5a22cf8c8c94017aadd360368f47d653829e0569a92b129979152ff97af23a558331e47e37cd9c + checksum: 7d0eda657002738aa5206107bd0580aead6c95c460ef1bdd0b1a87a9c7ae6277ac2e9b945306aaa5b32c6dcb7feaf462d0f552e7f8b5718abfc6ead5c94a71b3 languageName: node linkType: hard @@ -10424,48 +10403,36 @@ __metadata: languageName: node linkType: hard -"next@npm:^12.0.0": - version: 12.3.1 - resolution: "next@npm:12.3.1" - dependencies: - "@next/env": 12.3.1 - "@next/swc-android-arm-eabi": 12.3.1 - "@next/swc-android-arm64": 12.3.1 - "@next/swc-darwin-arm64": 12.3.1 - "@next/swc-darwin-x64": 12.3.1 - "@next/swc-freebsd-x64": 12.3.1 - "@next/swc-linux-arm-gnueabihf": 12.3.1 - "@next/swc-linux-arm64-gnu": 12.3.1 - "@next/swc-linux-arm64-musl": 12.3.1 - "@next/swc-linux-x64-gnu": 12.3.1 - "@next/swc-linux-x64-musl": 12.3.1 - "@next/swc-win32-arm64-msvc": 12.3.1 - "@next/swc-win32-ia32-msvc": 12.3.1 - "@next/swc-win32-x64-msvc": 12.3.1 - "@swc/helpers": 0.4.11 +"next@npm:^13.5.0": + version: 13.5.6 + resolution: "next@npm:13.5.6" + dependencies: + "@next/env": 13.5.6 + "@next/swc-darwin-arm64": 13.5.6 + "@next/swc-darwin-x64": 13.5.6 + "@next/swc-linux-arm64-gnu": 13.5.6 + "@next/swc-linux-arm64-musl": 13.5.6 + "@next/swc-linux-x64-gnu": 13.5.6 + "@next/swc-linux-x64-musl": 13.5.6 + "@next/swc-win32-arm64-msvc": 13.5.6 + "@next/swc-win32-ia32-msvc": 13.5.6 + "@next/swc-win32-x64-msvc": 13.5.6 + "@swc/helpers": 0.5.2 + busboy: 1.6.0 caniuse-lite: ^1.0.30001406 - postcss: 8.4.14 - styled-jsx: 5.0.7 - use-sync-external-store: 1.2.0 - peerDependencies: - fibers: ">= 3.1.0" - node-sass: ^6.0.0 || ^7.0.0 - react: ^17.0.2 || ^18.0.0-0 - react-dom: ^17.0.2 || ^18.0.0-0 + postcss: 8.4.31 + styled-jsx: 5.1.1 + watchpack: 2.4.0 + peerDependencies: + "@opentelemetry/api": ^1.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 sass: ^1.3.0 dependenciesMeta: - "@next/swc-android-arm-eabi": - optional: true - "@next/swc-android-arm64": - optional: true "@next/swc-darwin-arm64": optional: true "@next/swc-darwin-x64": optional: true - "@next/swc-freebsd-x64": - optional: true - "@next/swc-linux-arm-gnueabihf": - optional: true "@next/swc-linux-arm64-gnu": optional: true "@next/swc-linux-arm64-musl": @@ -10481,15 +10448,13 @@ __metadata: "@next/swc-win32-x64-msvc": optional: true peerDependenciesMeta: - fibers: - optional: true - node-sass: + "@opentelemetry/api": optional: true sass: optional: true bin: next: dist/bin/next - checksum: ac78592379999650f596a945019b14827818879e792ab37876bc71443bd697510d9ea00881787918f1543e6c6c5588111aeecb10342c2166a344e10ccd6bbc3e + checksum: c869b0014ae921ada3bf22301985027ec320aebcd6aa9c16e8afbded68bb8def5874cca034c680e8c351a79578f1e514971d02777f6f0a5a1d7290f25970ac0d languageName: node linkType: hard @@ -11206,14 +11171,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.14": - version: 8.4.14 - resolution: "postcss@npm:8.4.14" +"postcss@npm:8.4.31": + version: 8.4.31 + resolution: "postcss@npm:8.4.31" dependencies: - nanoid: ^3.3.4 + nanoid: ^3.3.6 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816 + checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea languageName: node linkType: hard @@ -12603,9 +12568,11 @@ __metadata: languageName: node linkType: hard -"styled-jsx@npm:5.0.7": - version: 5.0.7 - resolution: "styled-jsx@npm:5.0.7" +"styled-jsx@npm:5.1.1": + version: 5.1.1 + resolution: "styled-jsx@npm:5.1.1" + dependencies: + client-only: 0.0.1 peerDependencies: react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" peerDependenciesMeta: @@ -12613,7 +12580,7 @@ __metadata: optional: true babel-plugin-macros: optional: true - checksum: 61959993915f4b1662a682dbbefb3512de9399cf6901969bcadd26ba5441d2b5ca5c1021b233bbd573da2541b41efb45d56c6f618dbc8d88a381ebc62461fefe + checksum: 523a33b38603492547e861b98e29c873939b04e15fbe5ef16132c6f1e15958126647983c7d4675325038b428a5e91183d996e90141b18bdd1bbadf6e2c45b2fa languageName: node linkType: hard @@ -13479,15 +13446,6 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:1.2.0": - version: 1.2.0 - resolution: "use-sync-external-store@npm:1.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -13601,7 +13559,7 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.3.1": +"watchpack@npm:2.4.0, watchpack@npm:^2.3.1": version: 2.4.0 resolution: "watchpack@npm:2.4.0" dependencies: From 74a0340c262fc478a3ccb25bd72dd4f4ba3b88d2 Mon Sep 17 00:00:00 2001 From: Daisy Kucharski <83257720+daisykucharski@users.noreply.github.com> Date: Sun, 19 Nov 2023 16:14:49 -0500 Subject: [PATCH 07/22] Add support for NUPath (#656) * rename nupaths * add nupath types and to fetch course * use searchneu's terms for nupath * Remove print * fix search stuff --- packages/api-client/index.ts | 8 +++++++- packages/common/src/types.ts | 34 +++++++++++++++++----------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/packages/api-client/index.ts b/packages/api-client/index.ts index 6dd100bc9..bd3bb8ed8 100644 --- a/packages/api-client/index.ts +++ b/packages/api-client/index.ts @@ -20,6 +20,7 @@ import { ForgotPasswordDto, ResetPasswordDto, courseToString, + NUPathEnum, } from "@graduate/common"; import { ClassConstructor, plainToInstance } from "class-transformer"; @@ -131,6 +132,7 @@ interface SearchClass { subject: string; prereqs?: INEUAndReq | INEUOrReq; coreqs?: INEUAndReq | INEUOrReq; + nupath?: NUPathEnum[]; maxCredits: number; minCredits: number; termId: string; @@ -188,6 +190,7 @@ function occurrenceToCourse(occurrence: SearchClass): ScheduleCourse2 { numCreditsMin: occurrence.minCredits, prereqs: occurrence.prereqs, coreqs: occurrence.coreqs, + nupaths: occurrence.nupath, id: null, }; } @@ -228,6 +231,7 @@ class SearchAPIClient { minCredits prereqs coreqs + nupath } } }`, @@ -268,6 +272,7 @@ class SearchAPIClient { maxCredits prereqs coreqs + nupath termId } } @@ -352,7 +357,7 @@ class SearchAPIClient { search(termId:"${termId}", query: "${searchQuery}", classIdRange: {min: ${minIndex}, max: ${maxIndex}}) { totalCount pageInfo { hasNextPage } - nodes { ... on ClassOccurrence { name subject maxCredits minCredits prereqs coreqs classId + nodes { ... on ClassOccurrence { name subject maxCredits minCredits prereqs coreqs nupath classId } } } @@ -370,6 +375,7 @@ class SearchAPIClient { subject: result.subject, prereqs: result.prereqs, coreqs: result.coreqs, + nupaths: result.nupath, numCreditsMin: result.minCredits, numCreditsMax: result.maxCredits, }; diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index 0ca2d54a4..87dc173fa 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -1,22 +1,21 @@ /** - * Describes an abbreviation for one of Northeastern's NUPath academic breadth - * requirements. Each two-character NUPath directly corresponds to - * Northeastern's abbreviation of the requirement. + * Describes the term SearchNEU uses for each of Northeastern's NUPath academic + * breadth requirements. */ export enum NUPathEnum { - ND = "ND", - EI = "EI", - IC = "IC", - FQ = "FQ", - SI = "SI", - AD = "AD", - DD = "DD", - ER = "ER", - WF = "WF", - WD = "WD", - WI = "WI", - EX = "EX", - CE = "CE", + ND = "Natural and Designed World", + EI = "Creative Expression/Innovation", + IC = "Interpreting Culture", + FQ = "Formal and Quantitative Reasoning", + SI = "Societies and Institutions", + AD = "Analyzing/Using Data", + DD = "Difference and Diversity", + ER = "Ethical Reasoning", + WF = "1st Yr Writing", + WD = "Adv Writ Dscpl", + WI = "Writing Intensive", + EX = "Integration Experience", + CE = "Capstone Experience", } /** @@ -40,7 +39,6 @@ export enum StatusEnum { HOVERCOOP = "HOVERCOOP", } -export type NUPath = keyof typeof NUPathEnum; export type Status = keyof typeof StatusEnum; export type Season = keyof typeof SeasonEnum; @@ -319,6 +317,7 @@ export interface ScheduleTerm2 { * @param subject The subject of this course (CS, DS, etc) * @param prereqs The prerequisites for this course * @param coreqs The corequisites for this course + * @param nupaths The nupaths this course fulfills * @param numCreditsMin The minimum number of credits this course gives * @param numCreditsMax The maximum number of credits this course gives * @param id Unique id used as a book keeping field for dnd. @@ -329,6 +328,7 @@ export interface ScheduleCourse2 { subject: string; prereqs?: INEUAndReq | INEUOrReq; coreqs?: INEUAndReq | INEUOrReq; + nupaths?: NUPathEnum[]; numCreditsMin: number; numCreditsMax: number; id: T; From 96fe9fb135bab65c072140753a66715a53420d11 Mon Sep 17 00:00:00 2001 From: Tze Zhe Brandon Lim Date: Sun, 19 Nov 2023 17:15:16 -0500 Subject: [PATCH 08/22] Remove transfer course cursor styling (#669) * add design change * remove unused prop --- .../frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx b/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx index e652f85d1..6ab888415 100644 --- a/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx +++ b/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx @@ -114,6 +114,7 @@ export const NonDraggableScheduleCourse: React.FC< isDisabled={false} isEditable={true} removeCourse={removeCourse} + isDraggable={false} /> ); }; @@ -218,7 +219,7 @@ const ScheduleCourse = forwardRef( flex: scheduleCourse.classId === COOP_BLOCK.classId ? 1 : 0, marginBottom: "6px", transition: "transform 0.15s ease, opacity 0.25s ease", - transform: hovered ? "scale(1.04)" : "scale(1)", + transform: hovered && isDraggable ? "scale(1.04)" : "scale(1)", opacity: isValidRemove ? 0.5 : 1, justifyContent: "space-between", width: "100%", @@ -321,7 +322,7 @@ const ScheduleCourseDraggedContents: React.FC<
Date: Thu, 23 Nov 2023 02:11:10 -0500 Subject: [PATCH 09/22] Revert "Bump next from 12.3.1 to 13.5.0 (#642)" (#671) Fix for staging --- packages/frontend-v2/package.json | 2 +- yarn.lock | 212 ++++++++++++++++++------------ 2 files changed, 128 insertions(+), 86 deletions(-) diff --git a/packages/frontend-v2/package.json b/packages/frontend-v2/package.json index c2a623dce..d30d0d3c5 100644 --- a/packages/frontend-v2/package.json +++ b/packages/frontend-v2/package.json @@ -19,7 +19,7 @@ "@graduate/common": "workspace:*", "framer-motion": "^6", "immer": "^9.0.15", - "next": "^13.5.0", + "next": "^12.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", diff --git a/yarn.lock b/yarn.lock index cbdfe4cd8..e739a47b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3166,7 +3166,7 @@ __metadata: eslint-config-next: 12.1.4 framer-motion: ^6 immer: ^9.0.15 - next: ^13.5.0 + next: ^12.0.0 react: ^18.2.0 react-dom: ^18.2.0 react-error-boundary: ^3.1.4 @@ -3810,10 +3810,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.5.6": - version: 13.5.6 - resolution: "@next/env@npm:13.5.6" - checksum: 5e8f3f6f987a15dad3cd7b2bcac64a6382c2ec372d95d0ce6ab295eb59c9731222017eebf71ff3005932de2571f7543bce7e5c6a8c90030207fb819404138dc2 +"@next/env@npm:12.3.1": + version: 12.3.1 + resolution: "@next/env@npm:12.3.1" + checksum: ea7f2ad9080bdec91dd9e7d84db063793717fb1e6c668ff99cdd9103b9a7f2dd0afd153f04882944d24124965f2f78cdf24dc71da3dcd5afad3a078816abc528 languageName: node linkType: hard @@ -3826,65 +3826,93 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-darwin-arm64@npm:13.5.6" +"@next/swc-android-arm-eabi@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-android-arm-eabi@npm:12.3.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@next/swc-android-arm64@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-android-arm64@npm:12.3.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@next/swc-darwin-arm64@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-darwin-arm64@npm:12.3.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-darwin-x64@npm:13.5.6" +"@next/swc-darwin-x64@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-darwin-x64@npm:12.3.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-linux-arm64-gnu@npm:13.5.6" +"@next/swc-freebsd-x64@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-freebsd-x64@npm:12.3.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@next/swc-linux-arm-gnueabihf@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-linux-arm-gnueabihf@npm:12.3.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@next/swc-linux-arm64-gnu@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-linux-arm64-gnu@npm:12.3.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-linux-arm64-musl@npm:13.5.6" +"@next/swc-linux-arm64-musl@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-linux-arm64-musl@npm:12.3.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-linux-x64-gnu@npm:13.5.6" +"@next/swc-linux-x64-gnu@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-linux-x64-gnu@npm:12.3.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-linux-x64-musl@npm:13.5.6" +"@next/swc-linux-x64-musl@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-linux-x64-musl@npm:12.3.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-win32-arm64-msvc@npm:13.5.6" +"@next/swc-win32-arm64-msvc@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-win32-arm64-msvc@npm:12.3.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-win32-ia32-msvc@npm:13.5.6" +"@next/swc-win32-ia32-msvc@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-win32-ia32-msvc@npm:12.3.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:13.5.6": - version: 13.5.6 - resolution: "@next/swc-win32-x64-msvc@npm:13.5.6" +"@next/swc-win32-x64-msvc@npm:12.3.1": + version: 12.3.1 + resolution: "@next/swc-win32-x64-msvc@npm:12.3.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -3995,12 +4023,12 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.5.2": - version: 0.5.2 - resolution: "@swc/helpers@npm:0.5.2" +"@swc/helpers@npm:0.4.11": + version: 0.4.11 + resolution: "@swc/helpers@npm:0.4.11" dependencies: tslib: ^2.4.0 - checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 + checksum: 736857d524b41a8a4db81094e9b027f554004e0fa3e86325d85bdb38f7e6459ce022db079edb6c61ba0f46fe8583b3e663e95f7acbd13e51b8da6c34e45bba2e languageName: node linkType: hard @@ -5696,7 +5724,7 @@ __metadata: languageName: node linkType: hard -"busboy@npm:1.6.0, busboy@npm:^1.0.0": +"busboy@npm:^1.0.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" dependencies: @@ -5972,13 +6000,6 @@ __metadata: languageName: node linkType: hard -"client-only@npm:0.0.1": - version: 0.0.1 - resolution: "client-only@npm:0.0.1" - checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8 - languageName: node - linkType: hard - "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -10360,12 +10381,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" +"nanoid@npm:^3.3.4": + version: 3.3.4 + resolution: "nanoid@npm:3.3.4" bin: nanoid: bin/nanoid.cjs - checksum: 7d0eda657002738aa5206107bd0580aead6c95c460ef1bdd0b1a87a9c7ae6277ac2e9b945306aaa5b32c6dcb7feaf462d0f552e7f8b5718abfc6ead5c94a71b3 + checksum: 2fddd6dee994b7676f008d3ffa4ab16035a754f4bb586c61df5a22cf8c8c94017aadd360368f47d653829e0569a92b129979152ff97af23a558331e47e37cd9c languageName: node linkType: hard @@ -10403,36 +10424,48 @@ __metadata: languageName: node linkType: hard -"next@npm:^13.5.0": - version: 13.5.6 - resolution: "next@npm:13.5.6" - dependencies: - "@next/env": 13.5.6 - "@next/swc-darwin-arm64": 13.5.6 - "@next/swc-darwin-x64": 13.5.6 - "@next/swc-linux-arm64-gnu": 13.5.6 - "@next/swc-linux-arm64-musl": 13.5.6 - "@next/swc-linux-x64-gnu": 13.5.6 - "@next/swc-linux-x64-musl": 13.5.6 - "@next/swc-win32-arm64-msvc": 13.5.6 - "@next/swc-win32-ia32-msvc": 13.5.6 - "@next/swc-win32-x64-msvc": 13.5.6 - "@swc/helpers": 0.5.2 - busboy: 1.6.0 +"next@npm:^12.0.0": + version: 12.3.1 + resolution: "next@npm:12.3.1" + dependencies: + "@next/env": 12.3.1 + "@next/swc-android-arm-eabi": 12.3.1 + "@next/swc-android-arm64": 12.3.1 + "@next/swc-darwin-arm64": 12.3.1 + "@next/swc-darwin-x64": 12.3.1 + "@next/swc-freebsd-x64": 12.3.1 + "@next/swc-linux-arm-gnueabihf": 12.3.1 + "@next/swc-linux-arm64-gnu": 12.3.1 + "@next/swc-linux-arm64-musl": 12.3.1 + "@next/swc-linux-x64-gnu": 12.3.1 + "@next/swc-linux-x64-musl": 12.3.1 + "@next/swc-win32-arm64-msvc": 12.3.1 + "@next/swc-win32-ia32-msvc": 12.3.1 + "@next/swc-win32-x64-msvc": 12.3.1 + "@swc/helpers": 0.4.11 caniuse-lite: ^1.0.30001406 - postcss: 8.4.31 - styled-jsx: 5.1.1 - watchpack: 2.4.0 - peerDependencies: - "@opentelemetry/api": ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 + postcss: 8.4.14 + styled-jsx: 5.0.7 + use-sync-external-store: 1.2.0 + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^6.0.0 || ^7.0.0 + react: ^17.0.2 || ^18.0.0-0 + react-dom: ^17.0.2 || ^18.0.0-0 sass: ^1.3.0 dependenciesMeta: + "@next/swc-android-arm-eabi": + optional: true + "@next/swc-android-arm64": + optional: true "@next/swc-darwin-arm64": optional: true "@next/swc-darwin-x64": optional: true + "@next/swc-freebsd-x64": + optional: true + "@next/swc-linux-arm-gnueabihf": + optional: true "@next/swc-linux-arm64-gnu": optional: true "@next/swc-linux-arm64-musl": @@ -10448,13 +10481,15 @@ __metadata: "@next/swc-win32-x64-msvc": optional: true peerDependenciesMeta: - "@opentelemetry/api": + fibers: + optional: true + node-sass: optional: true sass: optional: true bin: next: dist/bin/next - checksum: c869b0014ae921ada3bf22301985027ec320aebcd6aa9c16e8afbded68bb8def5874cca034c680e8c351a79578f1e514971d02777f6f0a5a1d7290f25970ac0d + checksum: ac78592379999650f596a945019b14827818879e792ab37876bc71443bd697510d9ea00881787918f1543e6c6c5588111aeecb10342c2166a344e10ccd6bbc3e languageName: node linkType: hard @@ -11171,14 +11206,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.31": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" +"postcss@npm:8.4.14": + version: 8.4.14 + resolution: "postcss@npm:8.4.14" dependencies: - nanoid: ^3.3.6 + nanoid: ^3.3.4 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea + checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816 languageName: node linkType: hard @@ -12568,11 +12603,9 @@ __metadata: languageName: node linkType: hard -"styled-jsx@npm:5.1.1": - version: 5.1.1 - resolution: "styled-jsx@npm:5.1.1" - dependencies: - client-only: 0.0.1 +"styled-jsx@npm:5.0.7": + version: 5.0.7 + resolution: "styled-jsx@npm:5.0.7" peerDependencies: react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" peerDependenciesMeta: @@ -12580,7 +12613,7 @@ __metadata: optional: true babel-plugin-macros: optional: true - checksum: 523a33b38603492547e861b98e29c873939b04e15fbe5ef16132c6f1e15958126647983c7d4675325038b428a5e91183d996e90141b18bdd1bbadf6e2c45b2fa + checksum: 61959993915f4b1662a682dbbefb3512de9399cf6901969bcadd26ba5441d2b5ca5c1021b233bbd573da2541b41efb45d56c6f618dbc8d88a381ebc62461fefe languageName: node linkType: hard @@ -13446,6 +13479,15 @@ __metadata: languageName: node linkType: hard +"use-sync-external-store@npm:1.2.0": + version: 1.2.0 + resolution: "use-sync-external-store@npm:1.2.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -13559,7 +13601,7 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:2.4.0, watchpack@npm:^2.3.1": +"watchpack@npm:^2.3.1": version: 2.4.0 resolution: "watchpack@npm:2.4.0" dependencies: From a769198969e42475edb58f530b42a298cdcfe0bb Mon Sep 17 00:00:00 2001 From: Angela Zheng <92692008+AngelaZQ1@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:55:44 -0500 Subject: [PATCH 10/22] text fixes (#658) --- packages/frontend-v2/components/Header/ChangePassword.tsx | 2 +- packages/frontend-v2/components/Header/GraduateHeaders.tsx | 2 +- packages/frontend-v2/components/Header/UserDropdown.tsx | 2 +- packages/frontend-v2/components/Plan/DeletePlanModal.tsx | 2 +- packages/frontend-v2/components/Sidebar/Sidebar.tsx | 2 +- packages/frontend-v2/pages/index.tsx | 2 +- packages/frontend-v2/pages/login.tsx | 2 +- packages/frontend-v2/pages/signup.tsx | 3 ++- 8 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/frontend-v2/components/Header/ChangePassword.tsx b/packages/frontend-v2/components/Header/ChangePassword.tsx index 2c6c4ef07..9d10e10a3 100644 --- a/packages/frontend-v2/components/Header/ChangePassword.tsx +++ b/packages/frontend-v2/components/Header/ChangePassword.tsx @@ -75,7 +75,7 @@ export const ChangePassword: React.FC = () => { return ( <> - Change password + Change Password diff --git a/packages/frontend-v2/components/Header/GraduateHeaders.tsx b/packages/frontend-v2/components/Header/GraduateHeaders.tsx index 37f887207..a5aef3d4f 100644 --- a/packages/frontend-v2/components/Header/GraduateHeaders.tsx +++ b/packages/frontend-v2/components/Header/GraduateHeaders.tsx @@ -8,7 +8,7 @@ export const GraduatePreAuthHeader: React.FC = () => { return ( Sign In + Log In } /> ); diff --git a/packages/frontend-v2/components/Header/UserDropdown.tsx b/packages/frontend-v2/components/Header/UserDropdown.tsx index 50521fd5b..71ee27046 100644 --- a/packages/frontend-v2/components/Header/UserDropdown.tsx +++ b/packages/frontend-v2/components/Header/UserDropdown.tsx @@ -50,7 +50,7 @@ export const UserDropdown: React.FC = () => { logout(router)}> - Logout + Log Out diff --git a/packages/frontend-v2/components/Plan/DeletePlanModal.tsx b/packages/frontend-v2/components/Plan/DeletePlanModal.tsx index 5467d941d..4360ba60b 100644 --- a/packages/frontend-v2/components/Plan/DeletePlanModal.tsx +++ b/packages/frontend-v2/components/Plan/DeletePlanModal.tsx @@ -81,7 +81,7 @@ export const DeletePlanModal: React.FC = ({ borderRadius="lg" onClick={onClose} > - Nevermind + Cancel - Already have an account? + Already have an account?{" "} + } From 00ef0b12bbe5ae2e9f68ad7c8466b80d03a44213 Mon Sep 17 00:00:00 2001 From: Tze Zhe Brandon Lim Date: Sat, 25 Nov 2023 01:02:18 -0500 Subject: [PATCH 11/22] Fix sorting of plan dropdown (#674) --- packages/frontend-v2/pages/home.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend-v2/pages/home.tsx b/packages/frontend-v2/pages/home.tsx index 9b66fa0a9..7f7c425bd 100644 --- a/packages/frontend-v2/pages/home.tsx +++ b/packages/frontend-v2/pages/home.tsx @@ -93,7 +93,7 @@ const HomePage: NextPage = () => { if (student.plans.length > 0) { const sortedPlans = student.plans.sort( (p1, p2) => - new Date(p1.updatedAt).getTime() - new Date(p2.updatedAt).getTime() + new Date(p2.updatedAt).getTime() - new Date(p1.updatedAt).getTime() ); setSelectedPlanId(sortedPlans[0].id); } From 67c3f3a1e9bfe81c08db688ca78a1d347d774c35 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Sun, 26 Nov 2023 22:17:02 -0500 Subject: [PATCH 12/22] A Bundle of Docker Deploy Improvements (#676) * feat: build github workflow images with metadata * feat cors + cookie changes for vercel * feat: Improve deploy script CLI APIs * docs: added documentation for deploy scripts + component --- .github/workflows/aws-cd.yml | 6 +- infrastructure/prod/Dockerfile.app | 8 + infrastructure/prod/Dockerfile.server | 7 + infrastructure/prod/README.md | 36 ++++ infrastructure/prod/entrypoint.server.sh | 1 + infrastructure/prod/get-ecr-image-name.sh | 34 +++ infrastructure/prod/redeploy.sh | 46 +++- package.json | 7 + packages/api-client/index.ts | 6 + packages/api-v2/src/app.module.ts | 2 + packages/api-v2/src/auth/auth.controller.ts | 11 +- packages/api-v2/src/auth/auth.module.ts | 2 +- packages/api-v2/src/auth/auth.service.ts | 6 +- .../auth/interfaces/authenticated-request.ts | 2 +- packages/api-v2/src/constants.ts | 9 + packages/api-v2/src/email/email.module.ts | 4 +- packages/api-v2/src/email/email.service.ts | 2 +- .../emailConfirmation.controller.ts | 4 +- .../emailConfirmation.service.ts | 4 +- packages/api-v2/src/graduate-logger.ts | 2 +- .../src/guards/emailConfirmation.guard.ts | 4 +- packages/api-v2/src/main.ts | 7 +- packages/api-v2/src/meta/meta.controller.ts | 13 ++ packages/api-v2/src/meta/meta.module.ts | 10 + packages/api-v2/src/meta/meta.service.ts | 17 ++ packages/common/src/api-response-types.ts | 9 + packages/common/src/types.ts | 9 + .../components/Header/GraduateHeaders.tsx | 2 + .../components/MetaInfo/MetaInfo.tsx | 203 ++++++++++++++++++ 29 files changed, 442 insertions(+), 31 deletions(-) create mode 100644 infrastructure/prod/README.md create mode 100755 infrastructure/prod/get-ecr-image-name.sh create mode 100644 packages/api-v2/src/constants.ts create mode 100644 packages/api-v2/src/meta/meta.controller.ts create mode 100644 packages/api-v2/src/meta/meta.module.ts create mode 100644 packages/api-v2/src/meta/meta.service.ts create mode 100644 packages/frontend-v2/components/MetaInfo/MetaInfo.tsx diff --git a/.github/workflows/aws-cd.yml b/.github/workflows/aws-cd.yml index 9f992a6ac..c6104d2a1 100644 --- a/.github/workflows/aws-cd.yml +++ b/.github/workflows/aws-cd.yml @@ -35,7 +35,7 @@ jobs: # Build a docker container and # push it to ECR so that it can # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f infrastructure/prod/Dockerfile.server . + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --build-arg=\"COMMIT=$IMAGE_TAG\" --build-arg=\"BUILD_TIMESTAMP=$(date +%s)\" --build-arg=\"COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)\" -f infrastructure/prod/Dockerfile.server . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT @@ -49,7 +49,7 @@ jobs: # Build a docker container and # push it to ECR so that it can # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f infrastructure/prod/Dockerfile.app . + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --build-arg=\"COMMIT=$IMAGE_TAG\" --build-arg=\"BUILD_TIMESTAMP=$(date +%s)\" --build-arg=\"COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)\" -f infrastructure/prod/Dockerfile.app . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT @@ -57,7 +57,7 @@ jobs: run: | # - create new revision for task definition with latest image. # - redeploy ECS services with the latest revision. - ./infrastructure/prod/redeploy.sh staging + ./infrastructure/prod/redeploy.sh staging latest-main both - name: Logout of Amazon ECR if: always() diff --git a/infrastructure/prod/Dockerfile.app b/infrastructure/prod/Dockerfile.app index 48deb0d53..82e2c6a08 100644 --- a/infrastructure/prod/Dockerfile.app +++ b/infrastructure/prod/Dockerfile.app @@ -22,6 +22,14 @@ COPY packages/frontend-v2 packages/frontend-v2 COPY packages/api-client packages/api-client COPY packages/common packages/common +ARG COMMIT +ARG BUILD_TIMESTAMP +ARG COMMIT_MESSAGE + +ENV NEXT_PUBLIC_COMMIT_HASH $COMMIT +ENV NEXT_PUBLIC_COMMIT_MESSAGE $COMMIT_MESSAGE +ENV NEXT_PUBLIC_BUILD_TIMESTAMP $BUILD_TIMESTAMP + RUN yarn packages/api-client build RUN yarn packages/common build RUN yarn packages/frontend-v2 build diff --git a/infrastructure/prod/Dockerfile.server b/infrastructure/prod/Dockerfile.server index 325d54ffc..2e77d6c50 100644 --- a/infrastructure/prod/Dockerfile.server +++ b/infrastructure/prod/Dockerfile.server @@ -22,7 +22,14 @@ RUN yarn packages/api-v2 build FROM node:16-alpine AS runner WORKDIR /server +ARG COMMIT +ARG COMMIT_MESSAGE +ARG BUILD_TIMESTAMP + ENV NODE_ENV production +ENV COMMIT_HASH $COMMIT +ENV COMMIT_MESSAGE $COMMIT_MESSAGE +ENV BUILD_TIMESTAMP $BUILD_TIMESTAMP RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nestjs diff --git a/infrastructure/prod/README.md b/infrastructure/prod/README.md new file mode 100644 index 000000000..248e309f8 --- /dev/null +++ b/infrastructure/prod/README.md @@ -0,0 +1,36 @@ +# How to do a Manual Deploy (to staging or prod). + +Note: All of the `yarn` scripts in this guide are in the root `package.json`. + +**This will deploy the current files as they are in your local repo**. They will be tagged with the local HEAD commit. + +If you don't want this, you'll need to run modified calls rather than the package.json scripts directly. + +## Prereqs: + +- Install Docker +- Install the AWS CLI +- Have an AWS Access Key ID and AWS Secret Access Key pair. +- Run `aws configure`, and input those keys along with us-east-1 as the region. You can set the Default Output Format to json. + +## Steps: + +1. Run `yarn frontend:build` and/or `yarn backend:build` depending on what you want to build. +2. Run `yarn frontend:run` and/or `yarn backend:run` to test that the image runs (the backend won't be able to connect to the database which is expected, and the frontend will not connect to the backend). +3. You may have to run `yarn ecr:docker:auth` to reauthenticate Docker with AWS ECR. (There is no harm in running this command unnecessarily, so if you're unsure you can just run it). +4. If the images run successfully, run `yarn frontend:push` and/or `yarn backend:push` to push the built images to AWS ECR. +5. Run `./infrastructure/prod/redeploy.sh local-head ` + + `` is either `prod` or `staging`. + `` is one of `frontend`, `backend`, or `both`. + +# How to Manually Redeploy a Previously Deployed Commit + +If you know that a commit already has an image pushed to ECR (ex. the commit is in main, or you already pushed the image using the above steps) and you want to deploy that particular image to staging or prod, you can use the redeploy.sh script. + +1. Find the commit's hash (looks like this: 1445f9533c4ec9a7324c721f09fc5ccec1542d8d). +2. Run `./infrastructure/prod/redeploy.sh ` + + `` is either `prod` or `staging`. + `` is the hash of the commit you just found. + `` is one of `frontend`, `backend`, or `both`. diff --git a/infrastructure/prod/entrypoint.server.sh b/infrastructure/prod/entrypoint.server.sh index a2d9d4b22..0b36af281 100644 --- a/infrastructure/prod/entrypoint.server.sh +++ b/infrastructure/prod/entrypoint.server.sh @@ -1,6 +1,7 @@ #!/bin/sh cd packages/api-v2 +echo "Running on commit: $COMMIT_HASH" yarn typeorm migration:run exec "$@" diff --git a/infrastructure/prod/get-ecr-image-name.sh b/infrastructure/prod/get-ecr-image-name.sh new file mode 100755 index 000000000..a8f946ff7 --- /dev/null +++ b/infrastructure/prod/get-ecr-image-name.sh @@ -0,0 +1,34 @@ +if [[ $# != 2 ]]; then + echo "Usage: get-ecr-image-name.sh " + exit 1 +fi + +# Accept a few different formats for the commit hash. +if [[ ${#1} = 40 ]]; then + ECR_IMAGE_COMMIT_HASH=$1 +elif [[ $1 = "latest-main" ]]; then + ECR_IMAGE_COMMIT_HASH=$(git ls-remote https://github.com/sandboxnu/graduatenu.git main | awk '{ print $1 }') +elif [[ $1 = "local-head" ]]; then + ECR_IMAGE_COMMIT_HASH=$(git rev-parse HEAD) +else + echo "ERROR: Invalid commit '$1'" + exit 1 +fi + +if [[ $2 = "frontend" ]]; then + REPO="graduatenu-node" +elif [[ $2 = "backend" ]]; then + REPO="graduatenu-rails" +else + echo "Please choose a service to create an image name for: 'frontend' or 'backend'" + exit 1 +fi + +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +AWS_DEFAULT_REGION="us-east-1" + +ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com" + +ECR_IMAGE_NAME="${ECR_REGISTRY}/${REPO}:${ECR_IMAGE_COMMIT_HASH}" + +echo $ECR_IMAGE_NAME diff --git a/infrastructure/prod/redeploy.sh b/infrastructure/prod/redeploy.sh index e0932d44f..e3c135af7 100755 --- a/infrastructure/prod/redeploy.sh +++ b/infrastructure/prod/redeploy.sh @@ -1,35 +1,65 @@ #!/bin/bash +if [[ $# != 3 ]]; then + echo "Usage: redeploy.sh " + exit 1 +fi + if [[ ! " prod staging " =~ " $1 " ]]; then echo "Please provide environment to use: prod or staging" exit 1 fi +# Accept a few different formats for the commit hash. +if [[ ${#2} = 40 ]]; then + ECR_IMAGE_COMMIT_HASH=$2 +elif [[ $2 = "latest-main" ]]; then + ECR_IMAGE_COMMIT_HASH=$(git ls-remote https://github.com/sandboxnu/graduatenu.git main | awk '{ print $1 }') +elif [[ $2 = "local-head" ]]; then + ECR_IMAGE_COMMIT_HASH=$(git rev-parse HEAD) +else + echo "ERROR: Invalid commit '$2'" + exit 1 +fi + +# Only deploy the service specified. +if [[ $3 = "frontend" ]]; then + DEPLOY_INDEXES=(1) +elif [[ $3 = "backend" ]]; then + DEPLOY_INDEXES=(0) +elif [[ $3 = "both" ]]; then + DEPLOY_INDEXES=(0 1) +else + echo "Please choose a service to deploy: 'frontend', 'backend', or 'both'" + exit 1 +fi + +echo "Deploying $3 repo(s) to $1 with commit "$2" ($ECR_IMAGE_COMMIT_HASH)" + AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) AWS_DEFAULT_REGION="us-east-1" REPOS=( "graduatenu-rails" "graduatenu-node" ) -LATEST_HASH=$(git ls-remote https://github.com/sandboxnu/graduatenu.git main | awk '{ print $1 }') ECS_CLUSTER="$1-graduatenu" TASK_FAMILIES=( "${ECS_CLUSTER}-api" "${ECS_CLUSTER}-web" ) SERVICES=( "${ECS_CLUSTER}-api" "${ECS_CLUSTER}-web" ) + # Disable aws from sending stdout to less export AWS_PAGER="" -echo "Redeploying services for cluster: ${ECS_CLUSTER} with last pushed image" - - -for i in "${!REPOS[@]}"; do +for service_index in "${!DEPLOY_INDEXES[@]}"; do + echo "Deploying ${REPOS[DEPLOY_INDEXES[service_index]]}..." + i=${DEPLOY_INDEXES[service_index]} # Last pushed image should always be tagged with the latest commit hash on main - ECR_IMAGE="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${REPOS[$i]}:${LATEST_HASH}" + ECR_IMAGE="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${REPOS[$i]}:${ECR_IMAGE_COMMIT_HASH}" TASK_FAMILY="${TASK_FAMILIES[$i]}" SERVICE="${SERVICES[$i]}" # fetch template for task definition TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_FAMILY" --region "$AWS_DEFAULT_REGION") # update the template's image to use the latest ECR_IMAGE - NEW_TASK_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$ECR_IMAGE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)') + NEW_TASK_DEFINITION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$ECR_IMAGE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)') # register the new revision for the task definition - NEW_TASK_INFO=$(aws ecs register-task-definition --region "$AWS_DEFAULT_REGION" --cli-input-json "$NEW_TASK_DEFINTIION") + NEW_TASK_INFO=$(aws ecs register-task-definition --region "$AWS_DEFAULT_REGION" --cli-input-json "$NEW_TASK_DEFINITION") NEW_REVISION=$(echo $NEW_TASK_INFO | jq '.taskDefinition.revision') # update the service to replace tasks with the latest revision using the latest image aws ecs update-service --cluster ${ECS_CLUSTER} \ diff --git a/package.json b/package.json index b855887a1..f65242b5d 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,13 @@ "backend:docker:build": "docker compose -f infrastructure/develop/docker-compose.api.yml build", "backend:docker:run": "docker compose -f infrastructure/develop/docker-compose.api.yml up -d", "backend:docker:down": "docker compose -f infrastructure/develop/docker-compose.api.yml down", + "frontend:build": "docker build --platform linux/amd64 --build-arg=\"COMMIT=$(git rev-parse HEAD)\" --build-arg=\"BUILD_TIMESTAMP=$(date +%s)\" --build-arg=\"COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)\" -t $(sh ./infrastructure/prod/get-ecr-image-name.sh local-head frontend) -f ./infrastructure/prod/Dockerfile.app .", + "frontend:run": "docker run -p 4000:3000 $(sh ./infrastructure/prod/get-ecr-image-name.sh local-head frontend)", + "frontend:push": "docker push $(sh ./infrastructure/prod/get-ecr-image-name.sh local-head frontend)", + "backend:build": "docker build --platform linux/amd64 --build-arg=\"COMMIT=$(git rev-parse HEAD)\" --build-arg=\"BUILD_TIMESTAMP=$(date +%s)\" --build-arg=\"COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)\" -t $(sh ./infrastructure/prod/get-ecr-image-name.sh local-head backend) -f ./infrastructure/prod/Dockerfile.server .", + "backend:run": "docker run -p 4001:3001 $(sh ./infrastructure/prod/get-ecr-image-name.sh local-head backend)", + "backend:push": "docker push $(sh ./infrastructure/prod/get-ecr-image-name.sh local-head backend)", + "ecr:docker:auth": "aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-east-1.amazonaws.com", "lint": "eslint packages/ --ext .ts,.tsx .", "tsc": "yarn workspaces foreach -v --exclude . run tsc", "g:babel": "cd $INIT_CWD && babel", diff --git a/packages/api-client/index.ts b/packages/api-client/index.ts index bd3bb8ed8..239ac3088 100644 --- a/packages/api-client/index.ts +++ b/packages/api-client/index.ts @@ -21,6 +21,7 @@ import { ResetPasswordDto, courseToString, NUPathEnum, + GetMetaInfoResponse, } from "@graduate/common"; import { ClassConstructor, plainToInstance } from "class-transformer"; @@ -103,6 +104,11 @@ class APIClient { getSupportedMajors: (): Promise => this.req("GET", `/majors/supportedMajors`, GetSupportedMajorsResponse), }; + + meta = { + getInfo: (): Promise => + this.req("GET", "/meta/info", GetMetaInfoResponse), + }; } /** diff --git a/packages/api-v2/src/app.module.ts b/packages/api-v2/src/app.module.ts index 69b3118d4..6ca2109b1 100644 --- a/packages/api-v2/src/app.module.ts +++ b/packages/api-v2/src/app.module.ts @@ -10,6 +10,7 @@ import { LoggingInterceptor } from "./interceptors/logging.interceptor"; import { MajorModule } from "./major/major.module"; import { EmailModule } from "./email/email.module"; import { ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler"; +import { MetaModule } from "./meta/meta.module"; @Module({ imports: [ @@ -29,6 +30,7 @@ import { ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler"; PlanModule, MajorModule, EmailModule, + MetaModule, ], providers: [ { diff --git a/packages/api-v2/src/auth/auth.controller.ts b/packages/api-v2/src/auth/auth.controller.ts index 4bdcdb161..56720b7ca 100644 --- a/packages/api-v2/src/auth/auth.controller.ts +++ b/packages/api-v2/src/auth/auth.controller.ts @@ -22,15 +22,16 @@ import { weakPasswordError, } from "@graduate/common"; import { Response } from "express"; -import EmailConfirmationService from "src/emailConfirmation/emailConfirmation.service"; +import EmailConfirmationService from "../../src/emailConfirmation/emailConfirmation.service"; import { EmailAlreadyExists, EmailNotConfirmed, NoSuchEmail, WeakPassword, -} from "src/student/student.errors"; +} from "../../src/student/student.errors"; import { BadToken, InvalidPayload, TokenExpiredError } from "./auth.errors"; import { Throttle } from "@nestjs/throttler"; +import { COOKIE_DOMAIN } from "../../src/constants"; @Controller("auth") export class AuthController { @@ -61,11 +62,13 @@ export class AuthController { const { accessToken } = student; const isSecure = process.env.NODE_ENV !== "development"; + // Store JWT token in a cookie response.cookie("auth_cookie", accessToken, { httpOnly: true, sameSite: "strict", secure: isSecure, + domain: COOKIE_DOMAIN, }); if (process.env.NODE_ENV !== "testing") { await this.emailConfirmationService.sendVerificationLink( @@ -90,11 +93,13 @@ export class AuthController { const { accessToken } = student; const isSecure = process.env.NODE_ENV !== "development"; + // Store JWT token in a cookie response.cookie("auth_cookie", accessToken, { httpOnly: true, sameSite: "strict", secure: isSecure, + domain: COOKIE_DOMAIN, }); return student; @@ -152,10 +157,12 @@ export class AuthController { @Res({ passthrough: true }) response: Response ): Promise { const isSecure = process.env.NODE_ENV !== "development"; + response.clearCookie("auth_cookie", { httpOnly: true, sameSite: "strict", secure: isSecure, + domain: COOKIE_DOMAIN, }); } } diff --git a/packages/api-v2/src/auth/auth.module.ts b/packages/api-v2/src/auth/auth.module.ts index 74bfc207a..069b98758 100644 --- a/packages/api-v2/src/auth/auth.module.ts +++ b/packages/api-v2/src/auth/auth.module.ts @@ -5,7 +5,7 @@ import { StudentModule } from "../student/student.module"; import { AuthController } from "./auth.controller"; import { AuthService } from "./auth.service"; import { JwtStrategy } from "./jwt.strategy"; -import { EmailModule } from "src/email/email.module"; +import { EmailModule } from "../../src/email/email.module"; @Module({ imports: [ diff --git a/packages/api-v2/src/auth/auth.service.ts b/packages/api-v2/src/auth/auth.service.ts index e53113ed0..73d58dd6e 100644 --- a/packages/api-v2/src/auth/auth.service.ts +++ b/packages/api-v2/src/auth/auth.service.ts @@ -15,10 +15,10 @@ import { EmailNotConfirmed, NoSuchEmail, WeakPassword, -} from "src/student/student.errors"; +} from "../../src/student/student.errors"; import { ConfigService } from "@nestjs/config"; -import { EnvironmentVariables } from "src/environment-variables"; -import EmailService from "src/email/email.service"; +import { EnvironmentVariables } from "../../src/environment-variables"; +import EmailService from "../../src/email/email.service"; import { BadToken, InvalidPayload, TokenExpiredError } from "./auth.errors"; @Injectable() diff --git a/packages/api-v2/src/auth/interfaces/authenticated-request.ts b/packages/api-v2/src/auth/interfaces/authenticated-request.ts index 76b7c3b20..8c95bffde 100644 --- a/packages/api-v2/src/auth/interfaces/authenticated-request.ts +++ b/packages/api-v2/src/auth/interfaces/authenticated-request.ts @@ -1,4 +1,4 @@ -import { Student } from "src/student/entities/student.entity"; +import { Student } from "../../../src/student/entities/student.entity"; /** Represents an authenticated request using the JwtAuthGuard. */ export interface AuthenticatedRequest extends Request { diff --git a/packages/api-v2/src/constants.ts b/packages/api-v2/src/constants.ts new file mode 100644 index 000000000..4af358ff8 --- /dev/null +++ b/packages/api-v2/src/constants.ts @@ -0,0 +1,9 @@ +/** + * The root Domain on which all cookies should be set. (See: + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent) + * + * In production, this should be set to "graduatenu.com" which allows + * api.graduatenu.com to set cookies on every other *.graduatenu.com domain. + */ +export const COOKIE_DOMAIN = + process.env.NODE_ENV === "production" ? "graduatenu.com" : "localhost"; diff --git a/packages/api-v2/src/email/email.module.ts b/packages/api-v2/src/email/email.module.ts index 29317a561..20d0fc188 100644 --- a/packages/api-v2/src/email/email.module.ts +++ b/packages/api-v2/src/email/email.module.ts @@ -3,8 +3,8 @@ import { ConfigModule } from "@nestjs/config"; import EmailService from "./email.service"; import { JwtModule } from "@nestjs/jwt"; import EmailConfirmationService from "../emailConfirmation/emailConfirmation.service"; -import { StudentModule } from "src/student/student.module"; -import { EmailConfirmationController } from "src/emailConfirmation/emailConfirmation.controller"; +import { StudentModule } from "../../src/student/student.module"; +import { EmailConfirmationController } from "../../src/emailConfirmation/emailConfirmation.controller"; @Module({ imports: [ diff --git a/packages/api-v2/src/email/email.service.ts b/packages/api-v2/src/email/email.service.ts index 25190cf54..fd98e8fc3 100644 --- a/packages/api-v2/src/email/email.service.ts +++ b/packages/api-v2/src/email/email.service.ts @@ -2,7 +2,7 @@ import { Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { createTransport } from "nodemailer"; import Mail from "nodemailer/lib/mailer"; -import { EnvironmentVariables } from "src/environment-variables"; +import { EnvironmentVariables } from "../../src/environment-variables"; @Injectable() export default class EmailService { diff --git a/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts b/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts index 6486c7c2a..612e04de3 100644 --- a/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts +++ b/packages/api-v2/src/emailConfirmation/emailConfirmation.controller.ts @@ -12,8 +12,8 @@ import { emailAlreadyConfirmed, unableToSendEmail, } from "@graduate/common"; -import { AuthenticatedRequest } from "src/auth/interfaces/authenticated-request"; -import { JwtAuthGuard } from "src/guards/jwt-auth.guard"; +import { AuthenticatedRequest } from "../../src/auth/interfaces/authenticated-request"; +import { JwtAuthGuard } from "../../src/guards/jwt-auth.guard"; import EmailConfirmationService from "./emailConfirmation.service"; import { EmailAlreadyConfirmed, diff --git a/packages/api-v2/src/emailConfirmation/emailConfirmation.service.ts b/packages/api-v2/src/emailConfirmation/emailConfirmation.service.ts index af0dec3c0..ddc978f9d 100644 --- a/packages/api-v2/src/emailConfirmation/emailConfirmation.service.ts +++ b/packages/api-v2/src/emailConfirmation/emailConfirmation.service.ts @@ -1,8 +1,8 @@ import { Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; -import { EnvironmentVariables } from "src/environment-variables"; -import { StudentService } from "src/student/student.service"; +import { EnvironmentVariables } from "../../src/environment-variables"; +import { StudentService } from "../../src/student/student.service"; import { UpdateResult } from "typeorm"; import EmailService from "../email/email.service"; import { diff --git a/packages/api-v2/src/graduate-logger.ts b/packages/api-v2/src/graduate-logger.ts index 4b548dad9..cc61cb089 100644 --- a/packages/api-v2/src/graduate-logger.ts +++ b/packages/api-v2/src/graduate-logger.ts @@ -1,5 +1,5 @@ import { ConsoleLogger, LogLevel } from "@nestjs/common"; -import { deepFilter } from "src/utils"; +import { deepFilter } from "../src/utils"; const DENYLIST = ["password", "passwordConfirm"]; diff --git a/packages/api-v2/src/guards/emailConfirmation.guard.ts b/packages/api-v2/src/guards/emailConfirmation.guard.ts index 18c81cbe7..7d59aba06 100644 --- a/packages/api-v2/src/guards/emailConfirmation.guard.ts +++ b/packages/api-v2/src/guards/emailConfirmation.guard.ts @@ -6,8 +6,8 @@ import { UnauthorizedException, Logger, } from "@nestjs/common"; -import { AuthenticatedRequest } from "src/auth/interfaces/authenticated-request"; -import { formatServiceCtx } from "src/utils"; +import { AuthenticatedRequest } from "../../src/auth/interfaces/authenticated-request"; +import { formatServiceCtx } from "../../src/utils"; @Injectable() export class EmailConfirmationGuard implements CanActivate { diff --git a/packages/api-v2/src/main.ts b/packages/api-v2/src/main.ts index a5f64f2a9..d250908c3 100644 --- a/packages/api-v2/src/main.ts +++ b/packages/api-v2/src/main.ts @@ -6,7 +6,7 @@ import { } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { NestFactory, Reflector } from "@nestjs/core"; -import { GraduateLogger } from "src/graduate-logger"; +import { GraduateLogger } from "../src/graduate-logger"; import { AppModule } from "./app.module"; import { EnvironmentVariables } from "./environment-variables"; import * as cookieParser from "cookie-parser"; @@ -20,8 +20,9 @@ async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: graduateLogger, cors: { - origin: - "https://graduatenu-frontend-v2-git-christina-move-fro-b625a5-sandboxneu.vercel.app", + origin: "https://frontend-staging.graduatenu.com", + credentials: true, + methods: ["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"], }, }); diff --git a/packages/api-v2/src/meta/meta.controller.ts b/packages/api-v2/src/meta/meta.controller.ts new file mode 100644 index 000000000..20fec45e3 --- /dev/null +++ b/packages/api-v2/src/meta/meta.controller.ts @@ -0,0 +1,13 @@ +import { Controller, Get } from "@nestjs/common"; +import { MetaService } from "./meta.service"; +import { type MetaInfo } from "@graduate/common"; + +@Controller("meta") +export class MetaController { + constructor(private readonly metaService: MetaService) {} + + @Get("/info") + getMetaInfo(): MetaInfo { + return this.metaService.getMetaInfo(); + } +} diff --git a/packages/api-v2/src/meta/meta.module.ts b/packages/api-v2/src/meta/meta.module.ts new file mode 100644 index 000000000..5d0433160 --- /dev/null +++ b/packages/api-v2/src/meta/meta.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { MetaService } from "./meta.service"; +import { MetaController } from "./meta.controller"; + +@Module({ + controllers: [MetaController], + providers: [MetaService], + exports: [MetaService], +}) +export class MetaModule {} diff --git a/packages/api-v2/src/meta/meta.service.ts b/packages/api-v2/src/meta/meta.service.ts new file mode 100644 index 000000000..b1b0bfe90 --- /dev/null +++ b/packages/api-v2/src/meta/meta.service.ts @@ -0,0 +1,17 @@ +import { type MetaInfo } from "@graduate/common"; +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class MetaService { + getMetaInfo(): MetaInfo { + return { + commit: process.env.COMMIT_HASH ?? false, + commitMessage: process.env.COMMIT_MESSAGE ?? false, + build_timestamp: + process.env.BUILD_TIMESTAMP !== undefined + ? Number(process.env.BUILD_TIMESTAMP) + : false, + environment: process.env.NODE_ENV ?? false, + }; + } +} diff --git a/packages/common/src/api-response-types.ts b/packages/common/src/api-response-types.ts index 859146677..7cb2c1dee 100644 --- a/packages/common/src/api-response-types.ts +++ b/packages/common/src/api-response-types.ts @@ -3,6 +3,8 @@ import { Schedule2, SupportedMajors, ScheduleCourse2, + MetaInfo, + Maybe, } from "./types"; /** Types our API responds with. */ @@ -52,3 +54,10 @@ export class GetSupportedMajorsResponse { // { year => { majorName => {concentrations, minRequiredConcentrations} }} supportedMajors: SupportedMajors; } + +export class GetMetaInfoResponse implements MetaInfo { + commit: Maybe; + commitMessage: Maybe; + build_timestamp: Maybe; + environment: Maybe; +} diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index 87dc173fa..983f5aa3d 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -483,3 +483,12 @@ export const Err = (err: E): Result => ({ err, type: ResultType.Err, }); + +export type Maybe = T | false; + +export interface MetaInfo { + commit: Maybe; + commitMessage: Maybe; + build_timestamp: Maybe; + environment: Maybe; +} diff --git a/packages/frontend-v2/components/Header/GraduateHeaders.tsx b/packages/frontend-v2/components/Header/GraduateHeaders.tsx index a5aef3d4f..c38f5ef2c 100644 --- a/packages/frontend-v2/components/Header/GraduateHeaders.tsx +++ b/packages/frontend-v2/components/Header/GraduateHeaders.tsx @@ -3,6 +3,7 @@ import { Logo } from "./Logo"; import { GraduateButtonLink } from "../Link"; import { UserDropdown } from "./UserDropdown"; import { Flex, Icon, IconProps, Link as ChakraLink } from "@chakra-ui/react"; +import { MetaInfoWidget } from "../MetaInfo/MetaInfo"; export const GraduatePreAuthHeader: React.FC = () => { return ( @@ -31,6 +32,7 @@ const GraduateHeader: React.FC = ({ rightContent }) => { + Feedback diff --git a/packages/frontend-v2/components/MetaInfo/MetaInfo.tsx b/packages/frontend-v2/components/MetaInfo/MetaInfo.tsx new file mode 100644 index 000000000..4dc9a498e --- /dev/null +++ b/packages/frontend-v2/components/MetaInfo/MetaInfo.tsx @@ -0,0 +1,203 @@ +import { Box, Flex, Icon, Link, Text, Tooltip } from "@chakra-ui/react"; +import { API } from "@graduate/api-client"; +import { Maybe } from "@graduate/common"; +import { useState } from "react"; +import useSWR from "swr"; + +// adapted from https://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site +/** + * @param current The current time as a JS timestamp (milliseconds) + * @param previous The previous time as a JS timestamp (milliseconds) + * @returns Textual relative time difference + */ +function timeDifference(current: number, previous: number): string { + const msPerMinute = 60 * 1000; + const msPerHour = msPerMinute * 60; + const msPerDay = msPerHour * 24; + const msPerMonth = msPerDay * 30; + const msPerYear = msPerDay * 365; + + const elapsed = current - previous; + + if (elapsed < msPerMinute) { + return Math.round(elapsed / 1000) + " second(s) ago"; + } else if (elapsed < msPerHour) { + return Math.round(elapsed / msPerMinute) + " minute(s) ago"; + } else if (elapsed < msPerDay) { + return Math.round(elapsed / msPerHour) + " hour(s) ago"; + } else if (elapsed < msPerMonth) { + return "~" + Math.round(elapsed / msPerDay) + " day(s) ago"; + } else if (elapsed < msPerYear) { + return "~" + Math.round(elapsed / msPerMonth) + " month(s) ago"; + } else { + return "~" + Math.round(elapsed / msPerYear) + " year(s) ago"; + } +} + +/** + * @param timestamp A JS timestamp (milliseconds) + * @returns Formats the given timestamp as a string time + */ +function formatBuildTime(timestamp: number): string { + return new Date(timestamp).toLocaleDateString("en-US", { + weekday: "short", + year: "numeric", + month: "short", + day: "numeric", + hour: "numeric", + minute: "numeric", + }); +} + +/** A clickable dev widget for the header at the top of all pages. */ +export const MetaInfoWidget: React.FC = () => { + const [showDevInfo, setShowDevInfo] = useState(false); + + return ( + + setShowDevInfo((state) => !state)} + transition="background 0.15s ease" + userSelect="none" + > + + + + {process.env.NODE_ENV === "development" && Dev} + + { + + + + } + + ); +}; + +/** The contents of the meta info widget which displays docker build info. */ +export const MetaInfo: React.FC = () => { + const { data, error } = useSWR("/meta/info", API.meta.getInfo); + + // When we update Next versions we can use an instrumentation.ts file to create this information + // const relativeRunTime = timeDifference(Date.now(), Number(process.env.NEXT_PUBLIC_NEXT_RUN_TIMESTAMP ?? 0) * 1000) + + return ( + <> + + Docker Build Info + + Frontend + + + + Backend + + {error && Error Reaching Backend} + {data !== undefined ? ( + + ) : ( + !error && Loading Backend Info... + )} + + ); +}; + +/** Display the given optional commit hash and message. */ +const CommitText: React.FC<{ + commitHash: Maybe; + commitMessage: Maybe; +}> = ({ commitHash, commitMessage }) => { + if (commitHash !== false) { + const shortHash = commitHash.slice(0, 7); + const commitLink = `https://github.com/sandboxnu/graduatenu/commit/${commitHash}`; + return ( + + Commit:{" "} + + + {`${ + commitMessage !== false ? commitMessage : "" + } (${shortHash})`} + + + + ); + } else { + return Commit: {""}; + } +}; + +/** Displays the given optional build time timestamp. */ +const BuildTime: React.FC<{ buildTime: Maybe }> = ({ + buildTime, +}) => { + if (buildTime !== false) { + const numericTime = Number(buildTime) * 1000; + return ( + + Image Built: {timeDifference(Date.now(), numericTime)} + + ); + } else { + return Built: {""}; + } +}; + +/** A Docker meta info section. */ +export const MetaInfoSection: React.FC<{ + environment: Maybe; + commitHash: Maybe; + buildTime: Maybe | Maybe; + commitMessage: Maybe; +}> = ({ environment, commitHash, buildTime, commitMessage }) => { + return ( + <> + + Environment: {environment !== false ? environment : ""} + + + + + ); +}; From e411d659d9fb0a96966e5b8866ec7c27cf26720c Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Mon, 27 Nov 2023 12:08:06 -0500 Subject: [PATCH 13/22] Fix AWS-CD Script (#678) --- .github/workflows/aws-cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/aws-cd.yml b/.github/workflows/aws-cd.yml index c6104d2a1..d176b8d9f 100644 --- a/.github/workflows/aws-cd.yml +++ b/.github/workflows/aws-cd.yml @@ -35,7 +35,7 @@ jobs: # Build a docker container and # push it to ECR so that it can # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --build-arg=\"COMMIT=$IMAGE_TAG\" --build-arg=\"BUILD_TIMESTAMP=$(date +%s)\" --build-arg=\"COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)\" -f infrastructure/prod/Dockerfile.server . + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --build-arg="COMMIT=$IMAGE_TAG" --build-arg="BUILD_TIMESTAMP=$(date +%s)" --build-arg="COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)" -f infrastructure/prod/Dockerfile.server . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT @@ -49,7 +49,7 @@ jobs: # Build a docker container and # push it to ECR so that it can # be deployed to ECS. - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --build-arg=\"COMMIT=$IMAGE_TAG\" --build-arg=\"BUILD_TIMESTAMP=$(date +%s)\" --build-arg=\"COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)\" -f infrastructure/prod/Dockerfile.app . + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG --build-arg="COMMIT=$IMAGE_TAG" --build-arg="BUILD_TIMESTAMP=$(date +%s)" --build-arg="COMMIT_MESSAGE=$(git --no-pager show -s --format=%s)" -f infrastructure/prod/Dockerfile.app . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT @@ -57,7 +57,7 @@ jobs: run: | # - create new revision for task definition with latest image. # - redeploy ECS services with the latest revision. - ./infrastructure/prod/redeploy.sh staging latest-main both + ./infrastructure/prod/redeploy.sh staging local-head both - name: Logout of Amazon ECR if: always() From 8306ea495ff6d4e3767ece23f8fed0de93c4368a Mon Sep 17 00:00:00 2001 From: michelle <94196677+yijen-sun@users.noreply.github.com> Date: Thu, 30 Nov 2023 19:28:57 -0500 Subject: [PATCH 14/22] Support for checkmarked courses in sidebar (#672) * Support for checkmarked courses in sidebar * Support for checkmarked courses in sidebar --- .../ScheduleCourse/ScheduleCourse.tsx | 35 +++++++++++++++++-- .../components/Sidebar/SectionRequirement.tsx | 3 ++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx b/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx index 6ab888415..fd5c4656b 100644 --- a/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx +++ b/packages/frontend-v2/components/ScheduleCourse/ScheduleCourse.tsx @@ -1,5 +1,5 @@ -import { DeleteIcon } from "@chakra-ui/icons"; -import { Flex } from "@chakra-ui/react"; +import { DeleteIcon, CheckIcon } from "@chakra-ui/icons"; +import { Box, Flex } from "@chakra-ui/react"; import { useDraggable } from "@dnd-kit/core"; import { CSS } from "@dnd-kit/utilities"; import { @@ -24,6 +24,8 @@ interface DraggableScheduleCourseProps { scheduleCourse: ScheduleCourse2; coReqErr?: INEUReqError; preReqErr?: INEUReqError; + isInSidebar?: boolean; + isChecked?: boolean; /** Function to remove the course from whatever the schedule it is part of. */ removeCourse?: (course: ScheduleCourse2) => void; isEditable?: boolean; @@ -40,6 +42,8 @@ export const DraggableScheduleCourse: React.FC< removeCourse, preReqErr = undefined, coReqErr = undefined, + isInSidebar = false, + isChecked = false, isEditable = false, isDisabled = false, setIsRemove, @@ -64,6 +68,8 @@ export const DraggableScheduleCourse: React.FC< ref={setNodeRef} scheduleCourse={scheduleCourse} removeCourse={removeCourse} + isInSidebar={isInSidebar} + isChecked={isChecked} isEditable={isEditable} isDragging={isDragging} listeners={listeners} @@ -180,6 +186,8 @@ const ScheduleCourse = forwardRef( preReqErr = undefined, scheduleCourse, removeCourse, + isInSidebar = false, + isChecked = false, isEditable = false, isDragging = false, listeners, @@ -239,7 +247,7 @@ const ScheduleCourse = forwardRef( isOverlay={isOverlay} isDraggable={isDraggable} /> - + {isCourseError && ( ( } /> )} + {isInSidebar && isChecked && ( + + + + )} + {isEditable && !hovered && } {isOverlay && !isFromSidebar && ( diff --git a/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx b/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx index 3657d5240..08040e025 100644 --- a/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx +++ b/packages/frontend-v2/components/Sidebar/SectionRequirement.tsx @@ -131,6 +131,9 @@ const SectionRequirement: React.FC = ({ ...scheduleCourse, id: dndIdPrefix + "-" + courseKey, }} + isInSidebar + // TODO: isChecked is for when the requirement is added to the plan and validated. When true, this will render a checkmark. + isChecked={false} isDisabled={false} /> ); From 210e48b78d8243dd0c9a701198809922b6ba00d4 Mon Sep 17 00:00:00 2001 From: Angela Zheng <92692008+AngelaZQ1@users.noreply.github.com> Date: Fri, 1 Dec 2023 09:52:00 -0500 Subject: [PATCH 15/22] Mobile Landing Page (#679) * use mobile header for landing page mobile * add banner * top section * mobile info section * footer * set maxwidth * responsiveness * remove empty space in husky.svg * undo some changes --- .../components/Authentication/AuthForm.tsx | 4 +- .../components/Header/GraduateHeaders.tsx | 85 ++++++++- .../components/Header/HeaderContainer.tsx | 14 +- packages/frontend-v2/pages/_app.tsx | 5 +- packages/frontend-v2/pages/index.tsx | 169 ++++++++++++++---- .../frontend-v2/public/home_simplified.svg | 120 +++++++++++++ packages/frontend-v2/public/husky.svg | 40 ++--- packages/frontend-v2/utils/theme/index.ts | 1 + 8 files changed, 379 insertions(+), 59 deletions(-) create mode 100644 packages/frontend-v2/public/home_simplified.svg diff --git a/packages/frontend-v2/components/Authentication/AuthForm.tsx b/packages/frontend-v2/components/Authentication/AuthForm.tsx index f2195c562..65d1d44e7 100644 --- a/packages/frontend-v2/components/Authentication/AuthForm.tsx +++ b/packages/frontend-v2/components/Authentication/AuthForm.tsx @@ -24,7 +24,9 @@ export const AuthForm: React.FC = ({ height="100%" direction="column" rowGap="2xl" - mx="3xl" + mx="auto" + w="80%" + maxW="450px" > {headingText} diff --git a/packages/frontend-v2/components/Header/GraduateHeaders.tsx b/packages/frontend-v2/components/Header/GraduateHeaders.tsx index c38f5ef2c..cfd4838c3 100644 --- a/packages/frontend-v2/components/Header/GraduateHeaders.tsx +++ b/packages/frontend-v2/components/Header/GraduateHeaders.tsx @@ -2,11 +2,29 @@ import { HeaderContainer } from "./HeaderContainer"; import { Logo } from "./Logo"; import { GraduateButtonLink } from "../Link"; import { UserDropdown } from "./UserDropdown"; -import { Flex, Icon, IconProps, Link as ChakraLink } from "@chakra-ui/react"; +import { + Flex, + Icon, + IconProps, + Link as ChakraLink, + Menu, + MenuButton, + MenuList, + MenuItem, + IconButton, + Text, + Box, + useMediaQuery, +} from "@chakra-ui/react"; import { MetaInfoWidget } from "../MetaInfo/MetaInfo"; +import { HamburgerIcon } from "@chakra-ui/icons"; export const GraduatePreAuthHeader: React.FC = () => { - return ( + const [isMobile] = useMediaQuery("(max-width: 640px)"); + + return isMobile ? ( + + ) : ( Log In @@ -47,6 +65,69 @@ const GraduateHeader: React.FC = ({ rightContent }) => { ); }; +const MobileHeader: React.FC = () => { + return ( +
+ + + + } + variant="ghost" + color="primary.blue.dark.main" + _hover={{ + backgroundColor: "neutral.100", + }} + _active={{ + backgroundColor: "neutral.200", + }} + /> + + } + as="a" + href="https://forms.gle/Tg9yuhR8inkrqHdN6" + target="_blank" + > + Feedback + + } + as="a" + href="https://forms.gle/Sxg3B9js8KQ2zfJS9" + target="_blank" + > + Bug/Feature + + + + + + + + Open our site on desktop to get started! + + +
+ ); +}; + const FeedbackIcon: React.FC = (props) => { return ( = ({ children }) => { +interface HeaderContainerProps { + fixed?: boolean; +} + +export const HeaderContainer: React.FC< + PropsWithChildren +> = ({ fixed, children }) => { return ( {children} diff --git a/packages/frontend-v2/pages/_app.tsx b/packages/frontend-v2/pages/_app.tsx index 73dc36dc3..60655f9ab 100644 --- a/packages/frontend-v2/pages/_app.tsx +++ b/packages/frontend-v2/pages/_app.tsx @@ -1,5 +1,6 @@ import Head from "next/head"; import type { AppProps } from "next/app"; +import { useRouter } from "next/router"; import { ChakraProvider, Flex, Heading, Text, Image } from "@chakra-ui/react"; import { theme } from "../utils"; import "react-toastify/dist/ReactToastify.min.css"; @@ -9,9 +10,11 @@ import "@fontsource/montserrat-alternates"; import { useWindowSize } from "../hooks"; function MyApp({ Component, pageProps }: AppProps) { + const router = useRouter(); const { width } = useWindowSize(); - const disableApp = width && width <= 1100; + const isLandingPage = router.asPath === "/"; + const disableApp = !isLandingPage && width && width <= 1100; return ( <> diff --git a/packages/frontend-v2/pages/index.tsx b/packages/frontend-v2/pages/index.tsx index 906462b17..66bd15c75 100644 --- a/packages/frontend-v2/pages/index.tsx +++ b/packages/frontend-v2/pages/index.tsx @@ -3,11 +3,12 @@ import { Box, Flex, Heading, - HStack, Image, SimpleGrid, Text, VStack, + Link, + useMediaQuery, } from "@chakra-ui/react"; import { GraduateButtonLink, GraduatePreAuthHeader } from "../components"; @@ -24,11 +25,15 @@ interface InfoTextProps { } const LandingPage: NextPage = () => { + const [isMobile] = useMediaQuery("(max-width: 640px)"); + return ( + {isMobile && } +