From 1687bfb0d22f4c4066a2e11597c48c9d070008e8 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Thu, 24 Oct 2024 22:26:06 +0200 Subject: [PATCH 01/28] Use Next.js Image component in the resource drawer --- .../components/EmbedlyCard/EmbedlyCard.tsx | 8 ++-- .../src/components/EmbedlyCard/util.ts | 13 ++---- .../LearningResourceListCard.tsx | 9 ---- .../LearningResourceExpanded.tsx | 42 +++++++++++-------- .../ol-components/src/constants/imgConfigs.ts | 14 +++---- 5 files changed, 37 insertions(+), 49 deletions(-) diff --git a/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx b/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx index b9bee73776..2a7db3b3ca 100644 --- a/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx +++ b/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx @@ -6,9 +6,10 @@ import { embedlyCardHtml, EmbedlyEventTypes, ensureEmbedlyPlatform, - getEmbedlyKey, } from "./util" +const EMBEDLY_KEY = process.env.NEXT_PUBLIC_EMBEDLY_KEY as string + type EmbedlyCardProps = { url: string className?: string @@ -51,7 +52,6 @@ const Container = styled.div<{ aspectRatio?: number }>` const EmbedlyCard: React.FC = ({ className, url, - embedlyKey, aspectRatio, }) => { const [container, setContainer] = useState(null) @@ -85,11 +85,11 @@ const EmbedlyCard: React.FC = ({ const a = document.createElement("a") a.dataset.cardChrome = "0" a.dataset.cardControls = "0" - a.dataset.cardKey = embedlyKey ?? getEmbedlyKey() ?? "" + a.dataset.cardKey = EMBEDLY_KEY a.href = url a.classList.add("embedly-card") container.appendChild(a) - }, [embedlyKey, container, url]) + }, [EMBEDLY_KEY, container, url]) return ( { head.appendChild(style) } -const getEmbedlyKey = (): string | null => { - const key = process.env.NEXT_PUBLIC_EMBEDLY_KEY - if (typeof key === "string") return key - console.warn("process.env.NEXT_PUBLIC_EMBEDLY_KEY should be a string.") - return null -} - const embedlyCardHtml = (url: string) => { - const embedlyKey = getEmbedlyKey() return `` } @@ -101,7 +95,6 @@ const embedlyCardHtml = (url: string) => { export { createStylesheet, ensureEmbedlyPlatform, - getEmbedlyKey, EmbedlyEventTypes, dispatchCardCreated, embedlyCardHtml, diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx index 6778afc08b..74bd00d049 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx @@ -11,7 +11,6 @@ import { ResourceTypeEnum, LearningResource } from "api" import { formatDate, getReadableResourceType, - // embedlyCroppedImage, DEFAULT_RESOURCE_IMG, pluralize, getLearningResourcePrices, @@ -106,14 +105,6 @@ type ResourceIdCallback = ( resourceId: number, ) => void -// TODO confirm use of Next.js image optimizer in place of Embedly -// const getEmbedlyUrl = (url: string, isMobile: boolean) => { -// return embedlyCroppedImage(url, { -// key: process.env.NEXT_PUBLIC_EMBEDLY_KEY!, -// ...IMAGE_SIZES[isMobile ? "mobile" : "desktop"], -// }) -// } - /* This displays a single price for courses with no free option * (price includes the certificate). For free courses with the * option of a paid certificate, the certificate price displayed diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx index fdd3b2802d..85eff0accd 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx @@ -2,18 +2,17 @@ import React, { useEffect, useState } from "react" import styled from "@emotion/styled" import Skeleton from "@mui/material/Skeleton" import Typography from "@mui/material/Typography" +import { default as NextImage } from "next/image" import { ButtonLink } from "../Button/Button" import type { LearningResource, LearningResourceRun } from "api" import { ResourceTypeEnum, PlatformEnum } from "api" import { formatDate, capitalize, - resourceThumbnailSrc, DEFAULT_RESOURCE_IMG, showStartAnytime, } from "ol-utilities" import { RiExternalLinkLine } from "@remixicon/react" -import type { EmbedlyConfig } from "ol-utilities" import { theme } from "../ThemeProvider/ThemeProvider" import { SimpleSelect } from "../SimpleSelect/SimpleSelect" import type { SimpleSelectProps } from "../SimpleSelect/SimpleSelect" @@ -22,6 +21,7 @@ import { PlatformLogo, PLATFORMS } from "../Logo/Logo" import InfoSection from "./InfoSection" import type { User } from "api/hooks/user" import { LearningResourceCardProps } from "../LearningResourceCard/LearningResourceCard" +import type { ImageConfig } from "../../constants/imgConfigs" const Container = styled.div<{ padTop?: boolean }>` display: flex; @@ -76,8 +76,13 @@ const DateLabel = styled.span` margin-right: 16px; ` -const Image = styled.img<{ aspect: number }>` - aspect-ratio: ${({ aspect }) => aspect}; +const ImageContainer = styled.div<{ aspect: number }>` + position: relative; + width: 100%; + padding-bottom: ${({ aspect }) => 100 / aspect}%; +` + +const Image = styled(NextImage)` border-radius: 8px; width: 100%; object-fit: cover; @@ -141,38 +146,41 @@ const OnPlatform = styled.span` type LearningResourceExpandedProps = { resource?: LearningResource user?: User - imgConfig: EmbedlyConfig + imgConfig: ImageConfig onAddToLearningPathClick?: LearningResourceCardProps["onAddToLearningPathClick"] onAddToUserListClick?: LearningResourceCardProps["onAddToUserListClick"] } const ImageSection: React.FC<{ resource?: LearningResource - config: EmbedlyConfig + config: ImageConfig }> = ({ resource, config }) => { if (resource?.resource_type === "video" && resource?.url) { return ( ) } else if (resource?.image) { return ( - {resource?.image.alt + + {resource?.image.alt + ) } else if (resource) { return ( - {resource.image?.alt + + {resource.image?.alt + ) } else { return ( diff --git a/frontends/ol-components/src/constants/imgConfigs.ts b/frontends/ol-components/src/constants/imgConfigs.ts index 43369e85c5..06ff51641a 100644 --- a/frontends/ol-components/src/constants/imgConfigs.ts +++ b/frontends/ol-components/src/constants/imgConfigs.ts @@ -1,33 +1,29 @@ -import type { EmbedlyConfig } from "ol-utilities" - -const EMBEDLY_KEY = process.env.NEXT_PUBLIC_EMBEDLY_KEY as string +export type ImageConfig = { + width: number + height: number +} const imgConfigs = { row: { - key: EMBEDLY_KEY, width: 170, height: 130, }, "row-reverse": { - key: EMBEDLY_KEY, width: 170, height: 130, }, "row-reverse-small": { - key: EMBEDLY_KEY, width: 160, height: 100, }, column: { - key: EMBEDLY_KEY, width: 302, height: 182, }, large: { - key: EMBEDLY_KEY, width: 385, height: 200, }, -} satisfies Record +} satisfies Record export { imgConfigs } From a3be265fc7bc7e72b6432b54345d52dd17c68e40 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Fri, 25 Oct 2024 19:50:51 +0200 Subject: [PATCH 02/28] Differentiate NavItem props from config type --- .../ol-components/src/components/NavDrawer/NavDrawer.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx b/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx index 9ed6fc6af7..074babf125 100644 --- a/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx +++ b/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx @@ -118,20 +118,23 @@ export interface NavData { sections: NavSection[] } -export interface NavSection { +interface NavSection { title: string items: NavItem[] } -export interface NavItem { +interface NavItem { title: string icon?: string | ReactElement description?: string href: string +} + +type NavItemProps = NavItem & { onClick?: () => void } -const NavItem: React.FC = (props) => { +const NavItem: React.FC = (props) => { const { title, icon, description, href, onClick } = props const navItem = ( From 56e3dc566beec394ddfc24be873e04ff74b30cf2 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Fri, 25 Oct 2024 20:14:47 +0200 Subject: [PATCH 03/28] Replace about page image --- .../src/app-pages/AboutPage/AboutPage.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/frontends/main/src/app-pages/AboutPage/AboutPage.tsx b/frontends/main/src/app-pages/AboutPage/AboutPage.tsx index 0c1aecdefb..0b011cc018 100644 --- a/frontends/main/src/app-pages/AboutPage/AboutPage.tsx +++ b/frontends/main/src/app-pages/AboutPage/AboutPage.tsx @@ -10,6 +10,7 @@ import { import * as urls from "@/common/urls" import React from "react" import domeImage from "@/public/mit-dome-2.jpg" +import Image from "next/image" const WHAT_IS_MIT_OPEN_FRAGMENT_IDENTIFIER = "what-is-mit-learn" const NON_DEGREE_LEARNING_FRAGMENT_IDENTIFIER = "non-degree-learning" @@ -81,13 +82,15 @@ const SubHeaderTextContainer = styled.div({ alignSelf: "flex-start", }) -const SubHeaderImage = styled.img({ +const SubHeaderImageContainer = styled.div({ flexGrow: 1, alignSelf: "stretch", + position: "relative", +}) + +const SubHeaderImage = styled(Image)({ borderRadius: "8px", - backgroundSize: "cover", - backgroundPosition: "center", - backgroundImage: `url(${domeImage.src})`, + objectFit: "cover", [theme.breakpoints.down("md")]: { height: "300px", }, @@ -165,7 +168,13 @@ const AboutPage: React.FC = () => {
  • Continue your education at your own pace
  • - + + + From 2f1f01fdb353cf0ec14b1f3c08f98935d9de8a31 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Fri, 25 Oct 2024 21:54:13 +0200 Subject: [PATCH 04/28] Next.js images for channel page logos. Unit image config in Logo component --- .../ChannelPage/UnitChannelTemplate.tsx | 38 +++++++-- .../app-pages/UnitsListingPage/UnitCard.tsx | 20 +++-- .../src/components/Logo/Logo.tsx | 79 +++++++++++-------- 3 files changed, 86 insertions(+), 51 deletions(-) diff --git a/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx index e939d42b29..a30c2d4135 100644 --- a/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx @@ -8,7 +8,9 @@ import { BannerBackground, Typography, VisuallyHidden, + PlatformLogo, } from "ol-components" +import { OfferedByEnum, SourceTypeEnum } from "api" import { SearchSubscriptionToggle } from "@/page-components/SearchSubscriptionToggle/SearchSubscriptionToggle" import { ChannelDetails } from "@/page-components/ChannelDetails/ChannelDetails" import { useChannelDetail } from "api/hooks/channels" @@ -16,7 +18,6 @@ import ChannelMenu from "@/components/ChannelMenu/ChannelMenu" import ResourceCarousel, { ResourceCarouselProps, } from "@/page-components/ResourceCarousel/ResourceCarousel" -import { SourceTypeEnum } from "api" import { getSearchParamMap } from "@/common/utils" import { HOME as HOME_URL, UNITS as UNITS_URL } from "../../common/urls" import { ChannelTypeEnum } from "api/v0" @@ -38,16 +39,24 @@ const FeaturedCoursesCarousel = styled(ResourceCarousel)(({ theme }) => ({ }, })) -const UnitLogo = styled.img(({ theme }) => ({ - filter: "saturate(0%) invert(100%)", - maxWidth: "100%", - width: "auto", - height: "50px", +const MobileOnly = styled.div(({ theme }) => ({ + display: "contents", + [theme.breakpoints.up("md")]: { + display: "none", + }, +})) + +const DesktopOnly = styled.div(({ theme }) => ({ + display: "contents", [theme.breakpoints.down("md")]: { - height: "40px", + display: "none", }, })) +const PlatformLogoInverted = styled(PlatformLogo)({ + filter: "saturate(0%) invert(100%)", +}) + const BannerContent = styled.div(({ theme }) => ({ display: "flex", flexDirection: "row", @@ -126,7 +135,20 @@ const UnitChannelTemplate: React.FC = ({ {channel.data?.title} {channel.data ? ( - + <> + + + + + + + ) : null} diff --git a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx index 224323731c..1cd3f283a2 100644 --- a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx +++ b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx @@ -1,6 +1,13 @@ import React from "react" import { LearningResourceOfferorDetail, OfferedByEnum } from "api" -import { Card, Skeleton, Typography, styled, theme } from "ol-components" +import { + Card, + Skeleton, + Typography, + styled, + theme, + UNIT_LOGOS, +} from "ol-components" import { useChannelDetail } from "api/hooks/channels" const CardStyled = styled(Card)({ @@ -108,15 +115,6 @@ const CountsText = styled(Typography)(({ theme }) => ({ }, })) -const unitLogos = { - [OfferedByEnum.Mitx]: "/images/unit_logos/mitx.svg", - [OfferedByEnum.Ocw]: "/images/unit_logos/ocw.svg", - [OfferedByEnum.Bootcamps]: "/images/unit_logos/bootcamps.svg", - [OfferedByEnum.Xpro]: "/images/unit_logos/xpro.svg", - [OfferedByEnum.Mitpe]: "/images/unit_logos/mitpe.svg", - [OfferedByEnum.See]: "/images/unit_logos/see.svg", -} - interface UnitCardsProps { units: LearningResourceOfferorDetail[] | undefined courseCounts: Record @@ -198,7 +196,7 @@ export const UnitCards: React.FC = (props) => { const courseCount = courseCounts[unit.code] || 0 const programCount = programCounts[unit.code] || 0 const logo = - unitLogos[unit.code as OfferedByEnum] || + UNIT_LOGOS[unit.code as OfferedByEnum]?.image || `/images/unit_logos/${unit.code}.svg` return unit.value_prop ? ( = { - [PlatformEnum.Ocw]: { - name: "MIT OpenCourseWare", - image: "/unit_logos/ocw.svg", - aspect: 6.03, - }, - [PlatformEnum.Edx]: { - name: "edX", - image: "/platform_logos/edx.svg", - aspect: 1.77, - }, - [PlatformEnum.Mitxonline]: { +export const UNIT_LOGOS: Record = { + [OfferedByEnum.Mitx]: { name: "MITx Online", - image: "/unit_logos/mitx.svg", + image: "/images/unit_logos/mitx.svg", aspect: 3.32, }, - [PlatformEnum.Bootcamps]: { + [OfferedByEnum.Ocw]: { + name: "MIT OpenCourseWare", + image: "/images/unit_logos/ocw.svg", + aspect: 6.03, + }, + [OfferedByEnum.Bootcamps]: { name: "Bootcamps", - image: "/platform_logos/bootcamps.svg", + image: "/images/platform_logos/bootcamps.svg", aspect: 5.25, }, - [PlatformEnum.Xpro]: { + [OfferedByEnum.Xpro]: { name: "MIT xPRO", - image: "/unit_logos/xpro.svg", + image: "/images/unit_logos/xpro.svg", aspect: 3.56, }, + [OfferedByEnum.Mitpe]: { + name: "MIT Professional Education", + image: "/images/unit_logos/mitpe.svg", + aspect: 5.23, + }, + [OfferedByEnum.See]: { + name: "MIT Sloan Executive Education", + image: "/images/unit_logos/see.svg", + aspect: 7.61, + }, +} + +export const PLATFORM_LOGOS: Record = { + [PlatformEnum.Ocw]: UNIT_LOGOS[OfferedByEnum.Ocw], + [PlatformEnum.Edx]: { + name: "edX", + image: "/images/platform_logos/edx.svg", + aspect: 1.77, + }, + [PlatformEnum.Mitxonline]: UNIT_LOGOS[OfferedByEnum.Mitx], + [PlatformEnum.Bootcamps]: UNIT_LOGOS[OfferedByEnum.Bootcamps], + [PlatformEnum.Xpro]: UNIT_LOGOS[OfferedByEnum.Xpro], [PlatformEnum.Podcast]: { name: "Podcast", }, [PlatformEnum.Csail]: { name: "CSAIL", - image: "/platform_logos/csail.svg", + image: "/images/platform_logos/csail.svg", aspect: 1.76, }, - [PlatformEnum.Mitpe]: { - name: "MIT Professional Education", - }, - [PlatformEnum.See]: { - name: "MIT Sloan Executive Education", - image: "/unit_logos/see.svg", - aspect: 7.73, - }, + [PlatformEnum.Mitpe]: UNIT_LOGOS[OfferedByEnum.Mitpe], + [PlatformEnum.See]: UNIT_LOGOS[OfferedByEnum.See], [PlatformEnum.Scc]: { name: "Schwarzman College of Computing", }, @@ -80,7 +91,7 @@ export const PLATFORMS: Record = { }, [PlatformEnum.Oll]: { name: "Open Learning Library", - image: "/platform_logos/oll.svg", + image: "/images/platform_logos/oll.svg", aspect: 5.25, }, [PlatformEnum.Youtube]: { @@ -91,12 +102,16 @@ export const PLATFORMS: Record = { const DEFAULT_WIDTH = 200 export const PlatformLogo: React.FC<{ + unitCode?: OfferedByEnum platformCode?: PlatformEnum className?: string width?: number height?: number -}> = ({ platformCode, className, width, height }) => { - const platform = PLATFORMS[platformCode!] +}> = ({ unitCode, platformCode, className, width, height }) => { + const platform = unitCode + ? UNIT_LOGOS[unitCode] + : PLATFORM_LOGOS[platformCode!] + if (!platform?.image) { return null } @@ -121,7 +136,7 @@ export const PlatformLogo: React.FC<{ return ( {platform.name} Date: Mon, 28 Oct 2024 17:38:13 +0100 Subject: [PATCH 05/28] Remove NavDrawer image paths (not used). Fix Storybook page --- .../src/page-components/Header/Header.tsx | 2 +- .../LearningResourceExpanded.tsx | 4 +-- .../src/components/Logo/Logo.stories.tsx | 4 +-- .../NavDrawer/NavDrawer.stories.tsx | 29 ++++++++++++++----- .../components/NavDrawer/NavDrawer.test.tsx | 21 ++++++++++---- .../src/components/NavDrawer/NavDrawer.tsx | 26 +++++------------ 6 files changed, 49 insertions(+), 37 deletions(-) diff --git a/frontends/main/src/page-components/Header/Header.tsx b/frontends/main/src/page-components/Header/Header.tsx index e5cb4b7584..93ef5bcdb9 100644 --- a/frontends/main/src/page-components/Header/Header.tsx +++ b/frontends/main/src/page-components/Header/Header.tsx @@ -295,7 +295,7 @@ const Header: FunctionComponent = () => { desktopTrigger.current, mobileTrigger.current, ]} - navdata={navData} + navData={navData} open={drawerOpen} onClose={toggleDrawer.off} /> diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx index 85eff0accd..bd4e0b6e59 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx @@ -17,7 +17,7 @@ import { theme } from "../ThemeProvider/ThemeProvider" import { SimpleSelect } from "../SimpleSelect/SimpleSelect" import type { SimpleSelectProps } from "../SimpleSelect/SimpleSelect" import { EmbedlyCard } from "../EmbedlyCard/EmbedlyCard" -import { PlatformLogo, PLATFORMS } from "../Logo/Logo" +import { PlatformLogo, PLATFORM_LOGOS } from "../Logo/Logo" import InfoSection from "./InfoSection" import type { User } from "api/hooks/user" import { LearningResourceCardProps } from "../LearningResourceCard/LearningResourceCard" @@ -226,7 +226,7 @@ const CallToActionSection = ({ (offeredBy?.code as PlatformEnum) === PlatformEnum.Xpro ? (offeredBy?.code as PlatformEnum) : (platform?.code as PlatformEnum) - const platformImage = PLATFORMS[platformCode]?.image + const platformImage = PLATFORM_LOGOS[platformCode]?.image const getCallToActionText = (resource: LearningResource): string => { if (resource?.platform?.code === PlatformEnum.Ocw) { diff --git a/frontends/ol-components/src/components/Logo/Logo.stories.tsx b/frontends/ol-components/src/components/Logo/Logo.stories.tsx index 7f210685a6..b08359741d 100644 --- a/frontends/ol-components/src/components/Logo/Logo.stories.tsx +++ b/frontends/ol-components/src/components/Logo/Logo.stories.tsx @@ -1,6 +1,6 @@ import React from "react" import type { Meta, StoryObj } from "@storybook/react" -import { PlatformLogo, PLATFORMS } from "./Logo" +import { PlatformLogo, PLATFORM_LOGOS } from "./Logo" import Grid from "@mui/material/Grid" import styled from "@emotion/styled" import { PlatformEnum } from "api" @@ -27,7 +27,7 @@ const meta: Meta = { iconHeight args are only for this story. Not applicable to the actual component. - {Object.entries(PLATFORMS).map(([platformCode, platform]) => ( + {Object.entries(PLATFORM_LOGOS).map(([platformCode, platform]) => ( {platformCode} diff --git a/frontends/ol-components/src/components/NavDrawer/NavDrawer.stories.tsx b/frontends/ol-components/src/components/NavDrawer/NavDrawer.stories.tsx index 1421e4d897..366876f94f 100644 --- a/frontends/ol-components/src/components/NavDrawer/NavDrawer.stories.tsx +++ b/frontends/ol-components/src/components/NavDrawer/NavDrawer.stories.tsx @@ -1,29 +1,44 @@ -import React from "react" +import React, { MouseEvent } from "react" import type { Meta, StoryObj } from "@storybook/react" import { NavData, NavDrawer } from "./NavDrawer" import MuiButton from "@mui/material/Button" import styled from "@emotion/styled" +import { RiPencilRulerLine } from "@remixicon/react" import { useToggle } from "ol-utilities" const NavDrawerDemo = () => { const [open, setOpen] = useToggle(false) - const handleClickOpen = () => setOpen(!open) + const handleClickOpen = (event: MouseEvent) => { + setOpen(true) + event.stopPropagation() + } const navData: NavData = { sections: [ { - title: "TEST", + title: "Nav Drawer Title", items: [ { - title: "Link and description", - description: "This item has a link and a description", + title: "Link with description", + description: "This link has a description", href: "https://mit.edu", }, { - title: "Link but no description", + title: "Link with no description", href: "https://ocw.mit.edu", }, + { + title: "Link with icon", + icon: , + href: "https://mit.edu", + }, + { + title: "Link with icon and description", + description: "This link has an icon and a description", + icon: , + href: "https://mit.edu", + }, ], }, ], @@ -39,7 +54,7 @@ const NavDrawerDemo = () => { Toggle drawer - + ) } diff --git a/frontends/ol-components/src/components/NavDrawer/NavDrawer.test.tsx b/frontends/ol-components/src/components/NavDrawer/NavDrawer.test.tsx index 3e20d8a100..09f771f012 100644 --- a/frontends/ol-components/src/components/NavDrawer/NavDrawer.test.tsx +++ b/frontends/ol-components/src/components/NavDrawer/NavDrawer.test.tsx @@ -3,6 +3,7 @@ import { render, screen } from "@testing-library/react" import user from "@testing-library/user-event" import React from "react" import { ThemeProvider } from "../ThemeProvider/ThemeProvider" +import Image from "next/image" describe("NavDrawer", () => { it("Renders the expected drawer contents", () => { @@ -13,7 +14,15 @@ describe("NavDrawer", () => { items: [ { title: "Link and description with icon", - icon: "/path/to/image.svg", + icon: ( + + ), description: "This item has a link, description and icon", href: "https://mit.edu", }, @@ -30,7 +39,7 @@ describe("NavDrawer", () => { }, ], } - render(, { + render(, { wrapper: ThemeProvider, }) const links = screen.getAllByTestId("nav-link") @@ -70,7 +79,7 @@ describe("NavDrawer", () => { test("close button calls onClose", async () => { const onClose = jest.fn() - render(, { + render(, { wrapper: ThemeProvider, }) const close = screen.getByRole("button", { name: "Close Navigation" }) @@ -80,7 +89,7 @@ describe("NavDrawer", () => { test("escape calls onClose", async () => { const onClose = jest.fn() - render(, { + render(, { wrapper: ThemeProvider, }) const links = screen.getAllByRole("link") @@ -98,7 +107,7 @@ describe("NavDrawer", () => { [excluded.current]} onClose={onClose} - navdata={NAV_DATA} + navData={NAV_DATA} open={true} /> @@ -121,7 +130,7 @@ describe("NavDrawer", () => { test("clicking a link navigates and closes the drawer", async () => { const onClose = jest.fn() - render(, { + render(, { wrapper: ThemeProvider, }) diff --git a/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx b/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx index 074babf125..f8ed70bb54 100644 --- a/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx +++ b/frontends/ol-components/src/components/NavDrawer/NavDrawer.tsx @@ -83,12 +83,6 @@ const NavIconContainer = styled.div({ alignItems: "flex-start", }) -const NavIcon = styled.img({ - width: "22px", - height: "22px", - opacity: ".7", -}) - const NavTextContainer = styled.div({ display: "flex", flex: "1 0 0", @@ -125,7 +119,7 @@ interface NavSection { interface NavItem { title: string - icon?: string | ReactElement + icon?: ReactElement description?: string href: string } @@ -136,17 +130,11 @@ type NavItemProps = NavItem & { const NavItem: React.FC = (props) => { const { title, icon, description, href, onClick } = props + const navItem = ( - {typeof icon === "string" ? ( - - ) : null} - {typeof icon !== "string" ? icon : null} + {icon} @@ -168,7 +156,7 @@ const NavItem: React.FC = (props) => { } type NavDrawerProps = { - navdata: NavData + navData: NavData onClose: () => void /** * Returns a list of HTMLElements that should not trigger the drawer to close @@ -178,12 +166,12 @@ type NavDrawerProps = { } & DrawerProps const NavDrawer = ({ - navdata, + navData, onClose, getClickAwayExcluded = () => [], ...others }: NavDrawerProps) => { - const navSections = navdata.sections.map((section, i) => { + const navSections = navData.sections.map((section, i) => { const navItemElements = section.items.map((item) => ( Date: Mon, 28 Oct 2024 18:46:57 +0100 Subject: [PATCH 06/28] Upgrade to Next.js v15. Page params are now async --- frontends/main/package.json | 2 +- .../src/app/c/[channelType]/[name]/page.tsx | 10 +- .../main/src/app/dashboard/[tab]/page.tsx | 1 + frontends/main/src/app/page.tsx | 6 +- frontends/main/src/app/search/page.tsx | 6 +- frontends/main/src/common/metadata.ts | 4 +- yarn.lock | 143 +++++++++++++++++- 7 files changed, 159 insertions(+), 13 deletions(-) diff --git a/frontends/main/package.json b/frontends/main/package.json index 7968ffc6d0..9914f1ee6e 100644 --- a/frontends/main/package.json +++ b/frontends/main/package.json @@ -20,7 +20,7 @@ "api": "workspace:*", "formik": "^2.4.6", "lodash": "^4.17.21", - "next": "^14.2.15", + "next": "^15.0.1", "ol-ckeditor": "0.0.0", "ol-components": "0.0.0", "ol-utilities": "0.0.0", diff --git a/frontends/main/src/app/c/[channelType]/[name]/page.tsx b/frontends/main/src/app/c/[channelType]/[name]/page.tsx index 5c33fb3e1a..5cc73220e1 100644 --- a/frontends/main/src/app/c/[channelType]/[name]/page.tsx +++ b/frontends/main/src/app/c/[channelType]/[name]/page.tsx @@ -5,6 +5,10 @@ import { ChannelTypeEnum } from "api/v0" import { getMetadataAsync } from "@/common/metadata" import handleNotFound from "@/common/handleNotFound" +type SearchParams = { + [key: string]: string | string[] | undefined +} + type RouteParams = { channelType: ChannelTypeEnum name: string @@ -14,10 +18,10 @@ export async function generateMetadata({ searchParams, params, }: { - searchParams: { [key: string]: string | string[] | undefined } - params: RouteParams + searchParams: Promise + params: Promise }) { - const { channelType, name } = params + const { channelType, name } = await params const { data } = await handleNotFound( channelsApi.channelsTypeRetrieve({ channel_type: channelType, name: name }), diff --git a/frontends/main/src/app/dashboard/[tab]/page.tsx b/frontends/main/src/app/dashboard/[tab]/page.tsx index 3586bb6208..082710c443 100644 --- a/frontends/main/src/app/dashboard/[tab]/page.tsx +++ b/frontends/main/src/app/dashboard/[tab]/page.tsx @@ -10,6 +10,7 @@ export const metadata: Metadata = standardizeMetadata({ title: "Your MIT Learning Journey", social: false, }) + const Page: React.FC = () => { return ( diff --git a/frontends/main/src/app/page.tsx b/frontends/main/src/app/page.tsx index f6406e519a..34dd27b718 100644 --- a/frontends/main/src/app/page.tsx +++ b/frontends/main/src/app/page.tsx @@ -3,10 +3,14 @@ import type { Metadata } from "next" import HomePage from "@/app-pages/HomePage/HomePage" import { getMetadataAsync } from "@/common/metadata" +type SearchParams = { + [key: string]: string | string[] | undefined +} + export async function generateMetadata({ searchParams, }: { - searchParams: { [key: string]: string | string[] | undefined } + searchParams: Promise }): Promise { return await getMetadataAsync({ title: "Learn with MIT", diff --git a/frontends/main/src/app/search/page.tsx b/frontends/main/src/app/search/page.tsx index adc7151f65..94f7d88c9e 100644 --- a/frontends/main/src/app/search/page.tsx +++ b/frontends/main/src/app/search/page.tsx @@ -2,10 +2,14 @@ import React from "react" import { getMetadataAsync } from "@/common/metadata" import SearchPage from "@/app-pages/SearchPage/SearchPage" +type SearchParams = { + [key: string]: string | string[] | undefined +} + export async function generateMetadata({ searchParams, }: { - searchParams: { [key: string]: string | string[] | undefined } + searchParams: Promise }) { return await getMetadataAsync({ title: "Search", diff --git a/frontends/main/src/common/metadata.ts b/frontends/main/src/common/metadata.ts index c112873175..583e5a6383 100644 --- a/frontends/main/src/common/metadata.ts +++ b/frontends/main/src/common/metadata.ts @@ -10,7 +10,7 @@ type MetadataAsyncProps = { description?: string image?: string imageAlt?: string - searchParams?: { [key: string]: string | string[] | undefined } + searchParams?: Promise<{ [key: string]: string | string[] | undefined }> social?: boolean } & Metadata @@ -28,7 +28,7 @@ export const getMetadataAsync = async ({ ...otherMeta }: MetadataAsyncProps) => { // The learning resource drawer is open - const learningResourceId = searchParams?.[RESOURCE_DRAWER_QUERY_PARAM] + const learningResourceId = (await searchParams)?.[RESOURCE_DRAWER_QUERY_PARAM] if (learningResourceId) { const { data } = await handleNotFound( learningResourcesApi.learningResourcesRetrieve({ diff --git a/yarn.lock b/yarn.lock index 7c74d57ed4..f0339a9320 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3797,6 +3797,13 @@ __metadata: languageName: node linkType: hard +"@next/env@npm:15.0.1": + version: 15.0.1 + resolution: "@next/env@npm:15.0.1" + checksum: 10/0e7eb9600e6b9963de8faee6d044591e9408b106b122e27714db0d3f07812d442ec1352cf70b55ea49ac30ded9de1b03ba401952f2aad4c7e85c441628fc6ce0 + languageName: node + linkType: hard + "@next/eslint-plugin-next@npm:14.2.15, @next/eslint-plugin-next@npm:^14.2.7": version: 14.2.15 resolution: "@next/eslint-plugin-next@npm:14.2.15" @@ -3813,6 +3820,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-darwin-arm64@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-darwin-arm64@npm:15.0.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@next/swc-darwin-x64@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-darwin-x64@npm:14.2.15" @@ -3820,6 +3834,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-darwin-x64@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-darwin-x64@npm:15.0.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@next/swc-linux-arm64-gnu@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-linux-arm64-gnu@npm:14.2.15" @@ -3827,6 +3848,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-arm64-gnu@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-linux-arm64-gnu@npm:15.0.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@next/swc-linux-arm64-musl@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-linux-arm64-musl@npm:14.2.15" @@ -3834,6 +3862,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-arm64-musl@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-linux-arm64-musl@npm:15.0.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@next/swc-linux-x64-gnu@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-linux-x64-gnu@npm:14.2.15" @@ -3841,6 +3876,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-x64-gnu@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-linux-x64-gnu@npm:15.0.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@next/swc-linux-x64-musl@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-linux-x64-musl@npm:14.2.15" @@ -3848,6 +3890,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-x64-musl@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-linux-x64-musl@npm:15.0.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@next/swc-win32-arm64-msvc@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-win32-arm64-msvc@npm:14.2.15" @@ -3855,6 +3904,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-arm64-msvc@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-win32-arm64-msvc@npm:15.0.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@next/swc-win32-ia32-msvc@npm:14.2.15": version: 14.2.15 resolution: "@next/swc-win32-ia32-msvc@npm:14.2.15" @@ -3869,6 +3925,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-x64-msvc@npm:15.0.1": + version: 15.0.1 + resolution: "@next/swc-win32-x64-msvc@npm:15.0.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": version: 5.1.1-v1 resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" @@ -5648,13 +5711,22 @@ __metadata: languageName: node linkType: hard -"@swc/counter@npm:^0.1.3": +"@swc/counter@npm:0.1.3, @swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard +"@swc/helpers@npm:0.5.13": + version: 0.5.13 + resolution: "@swc/helpers@npm:0.5.13" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/6ba2f7e215d32d71fce139e2cfc426b3ed7eaa709febdeb07b97260a4c9eea4784cf047cc1271be273990b08220b576b94a42b5780947c0b3be84973a847a24d + languageName: node + linkType: hard + "@swc/helpers@npm:0.5.5": version: 0.5.5 resolution: "@swc/helpers@npm:0.5.5" @@ -14064,7 +14136,7 @@ __metadata: jest: "npm:^29.7.0" jest-extended: "npm:^4.0.2" lodash: "npm:^4.17.21" - next: "npm:^14.2.15" + next: "npm:^15.0.1" ol-ckeditor: "npm:0.0.0" ol-components: "npm:0.0.0" ol-test-utilities: "npm:0.0.0" @@ -15524,7 +15596,7 @@ __metadata: languageName: node linkType: hard -"next@npm:^14.2.15, next@npm:^14.2.7": +"next@npm:^14.2.7": version: 14.2.15 resolution: "next@npm:14.2.15" dependencies: @@ -15582,6 +15654,67 @@ __metadata: languageName: node linkType: hard +"next@npm:^15.0.1": + version: 15.0.1 + resolution: "next@npm:15.0.1" + dependencies: + "@next/env": "npm:15.0.1" + "@next/swc-darwin-arm64": "npm:15.0.1" + "@next/swc-darwin-x64": "npm:15.0.1" + "@next/swc-linux-arm64-gnu": "npm:15.0.1" + "@next/swc-linux-arm64-musl": "npm:15.0.1" + "@next/swc-linux-x64-gnu": "npm:15.0.1" + "@next/swc-linux-x64-musl": "npm:15.0.1" + "@next/swc-win32-arm64-msvc": "npm:15.0.1" + "@next/swc-win32-x64-msvc": "npm:15.0.1" + "@swc/counter": "npm:0.1.3" + "@swc/helpers": "npm:0.5.13" + busboy: "npm:1.6.0" + caniuse-lite: "npm:^1.0.30001579" + postcss: "npm:8.4.31" + sharp: "npm:^0.33.5" + styled-jsx: "npm:5.1.6" + peerDependencies: + "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.41.2 + babel-plugin-react-compiler: "*" + react: ^18.2.0 || 19.0.0-rc-69d4b800-20241021 + react-dom: ^18.2.0 || 19.0.0-rc-69d4b800-20241021 + sass: ^1.3.0 + dependenciesMeta: + "@next/swc-darwin-arm64": + optional: true + "@next/swc-darwin-x64": + optional: true + "@next/swc-linux-arm64-gnu": + optional: true + "@next/swc-linux-arm64-musl": + optional: true + "@next/swc-linux-x64-gnu": + optional: true + "@next/swc-linux-x64-musl": + optional: true + "@next/swc-win32-arm64-msvc": + optional: true + "@next/swc-win32-x64-msvc": + optional: true + sharp: + optional: true + peerDependenciesMeta: + "@opentelemetry/api": + optional: true + "@playwright/test": + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + bin: + next: dist/bin/next + checksum: 10/2919d98749e3d2f4cb21aa87f258aec947678f4dae6ffcaea0190e06d623a723cbdade995a66e8d5ad5e7b0be295554615feb388162b268f99d9a8cbd544ba76 + languageName: node + linkType: hard + "no-case@npm:^3.0.4": version: 3.0.4 resolution: "no-case@npm:3.0.4" @@ -18568,7 +18701,7 @@ __metadata: languageName: node linkType: hard -"sharp@npm:^0.33.3": +"sharp@npm:^0.33.3, sharp@npm:^0.33.5": version: 0.33.5 resolution: "sharp@npm:0.33.5" dependencies: @@ -19310,7 +19443,7 @@ __metadata: languageName: node linkType: hard -"styled-jsx@npm:^5.1.6": +"styled-jsx@npm:5.1.6, styled-jsx@npm:^5.1.6": version: 5.1.6 resolution: "styled-jsx@npm:5.1.6" dependencies: From 18fee782bc9022e43827fd92a6f2895795f85f1c Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:12:21 +0100 Subject: [PATCH 07/28] Upgrade @mui/material-nextjs for Next.js v15 --- frontends/ol-components/package.json | 4 +- frontends/ol-utilities/package.json | 1 + yarn.lock | 184 +++------------------------ 3 files changed, 23 insertions(+), 166 deletions(-) diff --git a/frontends/ol-components/package.json b/frontends/ol-components/package.json index 909f97a19d..0876024d89 100644 --- a/frontends/ol-components/package.json +++ b/frontends/ol-components/package.json @@ -19,7 +19,7 @@ "@mui/base": "5.0.0-beta.40", "@mui/lab": "^5.0.0-alpha.172", "@mui/material": "^5.16.1", - "@mui/material-nextjs": "^5.16.6", + "@mui/material-nextjs": "^6.1.5", "@mui/system": "^5.16.1", "@remixicon/react": "^4.2.0", "@testing-library/dom": "^10.4.0", @@ -30,7 +30,7 @@ "iso-639-1": "^3.1.2", "lodash": "^4.17.21", "material-ui-popup-state": "^5.1.0", - "next": "^14.2.7", + "next": "^15.0.1", "ol-test-utilities": "0.0.0", "ol-utilities": "0.0.0", "react": "18.3.1", diff --git a/frontends/ol-utilities/package.json b/frontends/ol-utilities/package.json index a81c595f3a..a7bc89106a 100644 --- a/frontends/ol-utilities/package.json +++ b/frontends/ol-utilities/package.json @@ -21,6 +21,7 @@ "iso-639-1": "^3.1.0", "lodash": "^4.17.21", "moment": "^2.29.4", + "next": "^15.0.1", "qs": "^6.11.0", "react-helmet-async": "^2.0.3", "striptags": "^3.2.0" diff --git a/yarn.lock b/yarn.lock index f0339a9320..0fc73e652e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1403,6 +1403,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.25.7": + version: 7.26.0 + resolution: "@babel/runtime@npm:7.26.0" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: 10/9f4ea1c1d566c497c052d505587554e782e021e6ccd302c2ad7ae8291c8e16e3f19d4a7726fb64469e057779ea2081c28b7dbefec6d813a22f08a35712c0f699 + languageName: node + linkType: hard + "@babel/template@npm:^7.25.7, @babel/template@npm:^7.3.3": version: 7.25.7 resolution: "@babel/template@npm:7.25.7" @@ -3627,18 +3636,18 @@ __metadata: languageName: node linkType: hard -"@mui/material-nextjs@npm:^5.16.6": - version: 5.16.6 - resolution: "@mui/material-nextjs@npm:5.16.6" +"@mui/material-nextjs@npm:^6.1.5": + version: 6.1.5 + resolution: "@mui/material-nextjs@npm:6.1.5" dependencies: - "@babel/runtime": "npm:^7.23.9" + "@babel/runtime": "npm:^7.25.7" peerDependencies: "@emotion/cache": ^11.11.0 + "@emotion/react": ^11.11.4 "@emotion/server": ^11.11.0 - "@mui/material": ^5.0.0 - "@types/react": ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 next: ^13.0.0 || ^14.0.0 - react: ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@emotion/cache": optional: true @@ -3646,7 +3655,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 10/bb58bd301944a0e8569ffc06e62f546c0aa89b025cd563030f4e7fba20b668d3b215a8ebf1c12bbf0df0449674414908e708a504c4dfa45345f9b8cd33f10e55 + checksum: 10/80fb5fc21751d872ff0ca669e136d7c1f8a72aa8353ab53fc8a3096a5e6791dd59de87ec1572a62dbe482eaf0f57b948e36a6a7807ad5acfbb1eda3c0ef542b7 languageName: node linkType: hard @@ -3790,13 +3799,6 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.2.15": - version: 14.2.15 - resolution: "@next/env@npm:14.2.15" - checksum: 10/76257d838aa8d6ede9240e4e8fd21847304b4d593fb758ea91c96e38818784e4f059d3b4c154e83b21983ea452fc7f4d1dc257d607ebba97c80db06ca4f9148a - languageName: node - linkType: hard - "@next/env@npm:15.0.1": version: 15.0.1 resolution: "@next/env@npm:15.0.1" @@ -3813,13 +3815,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-darwin-arm64@npm:14.2.15" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - "@next/swc-darwin-arm64@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-darwin-arm64@npm:15.0.1" @@ -3827,13 +3822,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-darwin-x64@npm:14.2.15" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - "@next/swc-darwin-x64@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-darwin-x64@npm:15.0.1" @@ -3841,13 +3829,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-linux-arm64-gnu@npm:14.2.15" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - "@next/swc-linux-arm64-gnu@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-arm64-gnu@npm:15.0.1" @@ -3855,13 +3836,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-linux-arm64-musl@npm:14.2.15" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - "@next/swc-linux-arm64-musl@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-arm64-musl@npm:15.0.1" @@ -3869,13 +3843,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-linux-x64-gnu@npm:14.2.15" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - "@next/swc-linux-x64-gnu@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-x64-gnu@npm:15.0.1" @@ -3883,13 +3850,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-linux-x64-musl@npm:14.2.15" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - "@next/swc-linux-x64-musl@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-x64-musl@npm:15.0.1" @@ -3897,13 +3857,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-win32-arm64-msvc@npm:14.2.15" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "@next/swc-win32-arm64-msvc@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-win32-arm64-msvc@npm:15.0.1" @@ -3911,20 +3864,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-win32-ia32-msvc@npm:14.2.15" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:14.2.15": - version: 14.2.15 - resolution: "@next/swc-win32-x64-msvc@npm:14.2.15" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@next/swc-win32-x64-msvc@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-win32-x64-msvc@npm:15.0.1" @@ -5727,16 +5666,6 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.5.5": - version: 0.5.5 - resolution: "@swc/helpers@npm:0.5.5" - dependencies: - "@swc/counter": "npm:^0.1.3" - tslib: "npm:^2.4.0" - checksum: 10/1c5ef04f642542212df28c669438f3e0f459dcde7b448a5b1fcafb2e9e4f13e76d8428535a270e91ed123dd2a21189dbed34086b88a8cf68baf84984d6d0e39b - languageName: node - linkType: hard - "@swc/jest@npm:^0.2.26": version: 0.2.36 resolution: "@swc/jest@npm:0.2.36" @@ -15596,64 +15525,6 @@ __metadata: languageName: node linkType: hard -"next@npm:^14.2.7": - version: 14.2.15 - resolution: "next@npm:14.2.15" - dependencies: - "@next/env": "npm:14.2.15" - "@next/swc-darwin-arm64": "npm:14.2.15" - "@next/swc-darwin-x64": "npm:14.2.15" - "@next/swc-linux-arm64-gnu": "npm:14.2.15" - "@next/swc-linux-arm64-musl": "npm:14.2.15" - "@next/swc-linux-x64-gnu": "npm:14.2.15" - "@next/swc-linux-x64-musl": "npm:14.2.15" - "@next/swc-win32-arm64-msvc": "npm:14.2.15" - "@next/swc-win32-ia32-msvc": "npm:14.2.15" - "@next/swc-win32-x64-msvc": "npm:14.2.15" - "@swc/helpers": "npm:0.5.5" - busboy: "npm:1.6.0" - caniuse-lite: "npm:^1.0.30001579" - graceful-fs: "npm:^4.2.11" - postcss: "npm:8.4.31" - styled-jsx: "npm:5.1.1" - peerDependencies: - "@opentelemetry/api": ^1.1.0 - "@playwright/test": ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-ia32-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - peerDependenciesMeta: - "@opentelemetry/api": - optional: true - "@playwright/test": - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: 10/5c5ed27888540f3ace732c2645a84b60d9e9c572cb335c5e9ff2a78a2eba704705e92e3c3d22586fd18d1621c70a5fb7ca8c8499550734d243fdec5d2a9c8a93 - languageName: node - linkType: hard - "next@npm:^15.0.1": version: 15.0.1 resolution: "next@npm:15.0.1" @@ -16074,7 +15945,7 @@ __metadata: "@mui/base": "npm:5.0.0-beta.40" "@mui/lab": "npm:^5.0.0-alpha.172" "@mui/material": "npm:^5.16.1" - "@mui/material-nextjs": "npm:^5.16.6" + "@mui/material-nextjs": "npm:^6.1.5" "@mui/system": "npm:^5.16.1" "@remixicon/react": "npm:^4.2.0" "@storybook/addon-actions": "npm:^8.2.9" @@ -16102,7 +15973,7 @@ __metadata: iso-639-1: "npm:^3.1.2" lodash: "npm:^4.17.21" material-ui-popup-state: "npm:^5.1.0" - next: "npm:^14.2.7" + next: "npm:^15.0.1" ol-test-utilities: "npm:0.0.0" ol-utilities: "npm:0.0.0" prop-types: "npm:^15.8.1" @@ -16155,6 +16026,7 @@ __metadata: iso-639-1: "npm:^3.1.0" lodash: "npm:^4.17.21" moment: "npm:^2.29.4" + next: "npm:^15.0.1" qs: "npm:^6.11.0" react-helmet-async: "npm:^2.0.3" striptags: "npm:^3.2.0" @@ -19427,22 +19299,6 @@ __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: "npm:0.0.1" - peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - checksum: 10/4f6a5d0010770fdeea1183d919d528fd46c484e23c0535ef3e1dd49488116f639c594f3bd4440e3bc8a8686c9f8d53c5761599870ff039ede11a5c3bfe08a4be - languageName: node - linkType: hard - "styled-jsx@npm:5.1.6, styled-jsx@npm:^5.1.6": version: 5.1.6 resolution: "styled-jsx@npm:5.1.6" From 3164d750ec7b1bbf75dced3b8f563d259fceb425 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:23:08 +0100 Subject: [PATCH 08/28] Utility for CSS background image-set() strings. Apply to homepage personalize section --- .../app-pages/HomePage/PersonalizeSection.tsx | 7 +++-- .../src/images/backgroundImages.ts | 27 +++++++++++++++++++ frontends/ol-utilities/src/index.ts | 1 + 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 frontends/ol-utilities/src/images/backgroundImages.ts diff --git a/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx b/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx index 93bd620af7..e20e788483 100644 --- a/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx +++ b/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx @@ -1,11 +1,14 @@ import React from "react" import { Typography, styled, Container, ButtonLink } from "ol-components" +import { backgroundSrcSetCSS } from "ol-utilities" import { useUserMe } from "api/hooks/user" import * as urls from "@/common/urls" +import personalizeImage from "@/public/images/homepage/personalize-image.png" +import personalizeBgImage from "@/public/images/homepage/personalize-bg.png" const FullWidthBackground = styled.div(({ theme }) => ({ padding: "80px 0", - background: 'url("/images/homepage/personalize-bg.png") center top no-repeat', + background: `${backgroundSrcSetCSS(personalizeBgImage)} center top no-repeat`, backgroundSize: "cover", [theme.breakpoints.down("md")]: { padding: "40px 0", @@ -108,7 +111,7 @@ const PersonalizeSection = () => { return ( - + diff --git a/frontends/ol-utilities/src/images/backgroundImages.ts b/frontends/ol-utilities/src/images/backgroundImages.ts new file mode 100644 index 0000000000..96e031ff76 --- /dev/null +++ b/frontends/ol-utilities/src/images/backgroundImages.ts @@ -0,0 +1,27 @@ +import { getImageProps } from "next/image" +import type { ImageProps } from "next/image" + +/* Generates a CSS `image-set()` declaration for a statically imported image. + * The Next.js server optimizes the image at resolutions requested, allowing the + * browser to select the best-suited image size based on the device's pixel density. + * + * https://nextjs.org/docs/app/api-reference/components/image#background-css + */ + +export const backgroundSrcSetCSS = (image: ImageProps["src"]) => { + const { props } = getImageProps({ + alt: "", + quality: 100, + src: image, + }) + + const imageSet = props.srcSet + ?.split(", ") + .map((str) => { + const [url, dpi] = str.split(" ") + return `url("${url}") ${dpi}` + }) + .join(", ") + + return imageSet ? `image-set(${imageSet})` : "" +} diff --git a/frontends/ol-utilities/src/index.ts b/frontends/ol-utilities/src/index.ts index 428a646c59..eefe535703 100644 --- a/frontends/ol-utilities/src/index.ts +++ b/frontends/ol-utilities/src/index.ts @@ -13,3 +13,4 @@ export * from "./predicates" export * from "./hooks" export * from "./querystrings" export * from "./lib" +export * from "./images/backgroundImages" From 8dc2db9be3ae3c5a2642ec1250964a10d90c723b Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:28:46 +0100 Subject: [PATCH 09/28] Pass background static import src to banner --- .../src/app-pages/ChannelPage/DefaultChannelTemplate.tsx | 6 +++++- .../main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx | 5 +++-- .../DepartmentListingPage/DepartmentListingPage.tsx | 4 ++-- .../LearningPathListingPage/LearningPathListingPage.tsx | 5 ----- frontends/main/src/app-pages/TermsPage/TermsPage.tsx | 2 +- .../src/app-pages/TopicsListingPage/TopicsListingPage.tsx | 3 ++- .../src/app-pages/UnitsListingPage/UnitsListingPage.tsx | 3 ++- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx index cc9cdbb121..c2d27998d3 100644 --- a/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx @@ -10,6 +10,7 @@ import { CHANNEL_TYPE_BREADCRUMB_TARGETS, ChannelControls, } from "./ChannelPageTemplate" +import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" const ChildrenContainer = styled.div(({ theme }) => ({ paddingTop: "40px", @@ -57,6 +58,7 @@ const DefaultChannelTemplate: React.FC = ({ const channel = useChannelDetail(String(channelType), String(name)) const urlParams = new URLSearchParams(channel.data?.search_filter) const displayConfiguration = channel.data?.configuration + return ( <> = ({ title={channel.data?.title} header={displayConfiguration?.heading} subHeader={displayConfiguration?.sub_heading} - backgroundUrl={displayConfiguration?.banner_background} + backgroundUrl={ + displayConfiguration?.banner_background ?? backgroundSteps + } extraActions={ diff --git a/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx index 412a25c23a..73f1a3b379 100644 --- a/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx @@ -25,6 +25,7 @@ import { } from "api/hooks/learningResources" import { propsNotNil } from "ol-utilities" import invariant from "tiny-invariant" +import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" const ChildrenContainer = styled.div(({ theme }) => ({ paddingTop: "40px", @@ -222,6 +223,7 @@ const TopicChannelTemplateInternal: React.FC< ) : ( ) + return ( <> } backgroundUrl={ - displayConfiguration?.banner_background ?? - "/images/backgrounds/background_steps.jpg" + displayConfiguration?.banner_background ?? backgroundSteps.src } extraActions={ diff --git a/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx b/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx index 32e308a1ea..cbdda18e8e 100644 --- a/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx +++ b/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx @@ -27,7 +27,7 @@ import { RiTerminalBoxLine, } from "@remixicon/react" import { HOME } from "@/common/urls" - +import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" import { aggregateProgramCounts, aggregateCourseCounts } from "@/common/utils" import { useChannelCounts } from "api/hooks/channels" @@ -201,7 +201,6 @@ const DepartmentListingPage: React.FC = () => { return ( <> { current="Departments" /> } + backgroundUrl={backgroundSteps.src} /> diff --git a/frontends/main/src/app-pages/LearningPathListingPage/LearningPathListingPage.tsx b/frontends/main/src/app-pages/LearningPathListingPage/LearningPathListingPage.tsx index 94502ce32a..8c0066287d 100644 --- a/frontends/main/src/app-pages/LearningPathListingPage/LearningPathListingPage.tsx +++ b/frontends/main/src/app-pages/LearningPathListingPage/LearningPathListingPage.tsx @@ -84,11 +84,6 @@ const LearningPathListingPage: React.FC = () => { src="/images/backgrounds/course_search_banner.png" className="learningpaths-page" > - {/* TODO - - - - */} diff --git a/frontends/main/src/app-pages/TermsPage/TermsPage.tsx b/frontends/main/src/app-pages/TermsPage/TermsPage.tsx index 73e2bc2b21..d44e161d91 100644 --- a/frontends/main/src/app-pages/TermsPage/TermsPage.tsx +++ b/frontends/main/src/app-pages/TermsPage/TermsPage.tsx @@ -1,7 +1,7 @@ "use client" import React from "react" -// Not urrently linked to. See https://github.com/mitodl/hq/issues/4639 +// Not currently linked to. See https://github.com/mitodl/hq/issues/4639 import { Breadcrumbs, Container, diff --git a/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx b/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx index 922cb42f3f..e01672d355 100644 --- a/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx +++ b/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx @@ -15,13 +15,13 @@ import { } from "ol-components" import Link from "next/link" import { propsNotNil } from "ol-utilities" - import { useLearningResourceTopics } from "api/hooks/learningResources" import { LearningResourceTopic } from "api" import RootTopicIcon from "@/components/RootTopicIcon/RootTopicIcon" import { HOME } from "@/common/urls" import { aggregateProgramCounts, aggregateCourseCounts } from "@/common/utils" import { useChannelCounts } from "api/hooks/channels" +import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" type ChannelSummary = { id: number | string @@ -275,6 +275,7 @@ const TopicsListingPage: React.FC = () => { } title="Browse by Topic" header="Select a topic below to explore relevant learning resources across all Academic and Professional units." + backgroundUrl={backgroundSteps.src} /> diff --git a/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx b/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx index 574ccb3b42..5494f33f03 100644 --- a/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx +++ b/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx @@ -11,7 +11,7 @@ import { theme, Breadcrumbs, } from "ol-components" - +import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" import { RiBookOpenLine, RiSuitcaseLine } from "@remixicon/react" import { LearningResourceOfferorDetail } from "api" import { HOME } from "@/common/urls" @@ -248,6 +248,7 @@ const UnitsListingPage: React.FC = () => { } title="Academic & Professional Learning" header="Non-degree learning resources tailored to the needs of students and working professionals." + backgroundUrl={backgroundSteps.src} /> From 92e8cd4490b0c7f3a6198073dbd5c93252dfe065 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:06:37 +0100 Subject: [PATCH 10/28] Use Logo component for unit cards --- .../{[id]/view => }/ProgramLetter.test.tsx | 0 .../{[id]/view => }/ProgramLetterPage.tsx | 0 .../app-pages/UnitsListingPage/UnitCard.tsx | 29 +++++++++---------- .../src/app/program_letter/[id]/view/page.tsx | 2 +- .../components/EmbedlyCard/EmbedlyCard.tsx | 2 +- .../LearningResourceExpanded.test.tsx | 5 ++-- 6 files changed, 17 insertions(+), 21 deletions(-) rename frontends/main/src/app-pages/ProgramLetterPage/{[id]/view => }/ProgramLetter.test.tsx (100%) rename frontends/main/src/app-pages/ProgramLetterPage/{[id]/view => }/ProgramLetterPage.tsx (100%) diff --git a/frontends/main/src/app-pages/ProgramLetterPage/[id]/view/ProgramLetter.test.tsx b/frontends/main/src/app-pages/ProgramLetterPage/ProgramLetter.test.tsx similarity index 100% rename from frontends/main/src/app-pages/ProgramLetterPage/[id]/view/ProgramLetter.test.tsx rename to frontends/main/src/app-pages/ProgramLetterPage/ProgramLetter.test.tsx diff --git a/frontends/main/src/app-pages/ProgramLetterPage/[id]/view/ProgramLetterPage.tsx b/frontends/main/src/app-pages/ProgramLetterPage/ProgramLetterPage.tsx similarity index 100% rename from frontends/main/src/app-pages/ProgramLetterPage/[id]/view/ProgramLetterPage.tsx rename to frontends/main/src/app-pages/ProgramLetterPage/ProgramLetterPage.tsx diff --git a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx index 1cd3f283a2..bb6abce574 100644 --- a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx +++ b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx @@ -6,7 +6,7 @@ import { Typography, styled, theme, - UNIT_LOGOS, + PlatformLogo, } from "ol-components" import { useChannelDetail } from "api/hooks/channels" @@ -41,14 +41,12 @@ const LogoContainer = styled.div({ margin: "0 auto", }, }, -}) - -const UnitLogo = styled.img({ - height: "50px", - display: "block", - [theme.breakpoints.down("md")]: { - height: "40px", - margin: "0 auto", + img: { + display: "block", + [theme.breakpoints.down("md")]: { + height: "40px", + margin: "0 auto", + }, }, }) @@ -123,13 +121,12 @@ interface UnitCardsProps { interface UnitCardProps { unit: LearningResourceOfferorDetail - logo: string courseCount: number programCount: number } const UnitCard: React.FC = (props) => { - const { unit, logo, courseCount, programCount } = props + const { unit, courseCount, programCount } = props const channelDetailQuery = useChannelDetail("unit", unit.code) const channelDetail = channelDetailQuery.data const unitUrl = channelDetail?.channel_url @@ -142,7 +139,7 @@ const UnitCard: React.FC = (props) => { - + @@ -195,14 +192,14 @@ export const UnitCards: React.FC = (props) => { {units?.map((unit) => { const courseCount = courseCounts[unit.code] || 0 const programCount = programCounts[unit.code] || 0 - const logo = - UNIT_LOGOS[unit.code as OfferedByEnum]?.image || - `/images/unit_logos/${unit.code}.svg` + // const logo = + // UNIT_LOGOS[unit.code as OfferedByEnum]?.image || + // `/images/unit_logos/${unit.code}.svg` return unit.value_prop ? ( diff --git a/frontends/main/src/app/program_letter/[id]/view/page.tsx b/frontends/main/src/app/program_letter/[id]/view/page.tsx index faa058688c..849a6050e5 100644 --- a/frontends/main/src/app/program_letter/[id]/view/page.tsx +++ b/frontends/main/src/app/program_letter/[id]/view/page.tsx @@ -1,5 +1,5 @@ import React from "react" -import ProgramLetterPage from "@/app-pages/ProgramLetterPage/[id]/view/ProgramLetterPage" +import ProgramLetterPage from "@/app-pages/ProgramLetterPage/ProgramLetterPage" const Page: React.FC = () => { return diff --git a/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx b/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx index 2a7db3b3ca..9f7e00395f 100644 --- a/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx +++ b/frontends/ol-components/src/components/EmbedlyCard/EmbedlyCard.tsx @@ -89,7 +89,7 @@ const EmbedlyCard: React.FC = ({ a.href = url a.classList.add("embedly-card") container.appendChild(a) - }, [EMBEDLY_KEY, container, url]) + }, [container, url]) return ( { .find((img) => img.getAttribute("alt")?.includes("xPRO")) expect(xproImage).toBeInTheDocument() - expect(xproImage).toHaveAttribute("alt", PLATFORMS["xpro"].name) + expect(xproImage).toHaveAttribute("alt", PLATFORM_LOGOS["xpro"].name) }, ) From b96fb61dda988f114abed671b46bf1692eb95a34 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:07:25 +0100 Subject: [PATCH 11/28] Suspense boundaries needed around carousels (useSearchParams() should be wrapped error) --- .../main/src/app-pages/HomePage/HomePage.tsx | 28 +++++++++++-------- frontends/main/src/app/search/page.tsx | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/frontends/main/src/app-pages/HomePage/HomePage.tsx b/frontends/main/src/app-pages/HomePage/HomePage.tsx index 553c797d70..62280da59d 100644 --- a/frontends/main/src/app-pages/HomePage/HomePage.tsx +++ b/frontends/main/src/app-pages/HomePage/HomePage.tsx @@ -1,6 +1,6 @@ "use client" -import React from "react" +import React, { Suspense } from "react" import { Container, styled, theme } from "ol-components" import HeroSearch from "@/page-components/HeroSearch/HeroSearch" import BrowseTopicsSection from "./BrowseTopicsSection" @@ -41,26 +41,30 @@ const MediaCarousel = styled(ResourceCarousel)(({ theme }) => ({ const HomePage: React.FC = () => { return ( <> - + + + - - -
    + +
    + -
    - + +
    - + + + diff --git a/frontends/main/src/app/search/page.tsx b/frontends/main/src/app/search/page.tsx index 94f7d88c9e..71c7723373 100644 --- a/frontends/main/src/app/search/page.tsx +++ b/frontends/main/src/app/search/page.tsx @@ -22,7 +22,7 @@ export async function generateMetadata({ * 1. wrap the in Suspense * 2. or force-dynamic. * - * (1) caused a hydration error for authenticated users. We haven not found + * (1) caused a hydration error for authenticated users. We have not found * the root cause of the hydration error. * * (2) seems to work well. From f4d80569f5d24c8378915acdfde45a324f1d1af7 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:22:58 +0100 Subject: [PATCH 12/28] Type fix --- .../LearningResourceExpanded.stories.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.stories.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.stories.tsx index 33271da082..ceeaf7ddcf 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.stories.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.stories.tsx @@ -21,7 +21,6 @@ const meta: Meta = { component: LearningResourceExpanded, args: { imgConfig: { - key: "", width: 385, height: 200, }, From 4e4af0a5ba5834933a46f87e7236027afd7fe897 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:59:46 +0100 Subject: [PATCH 13/28] Display YouTube videos with simple iframe --- .../main/src/app-pages/HomePage/HomePage.tsx | 26 +++++++------- .../LearningResourceExpanded.tsx | 34 ++++++++++++++----- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/frontends/main/src/app-pages/HomePage/HomePage.tsx b/frontends/main/src/app-pages/HomePage/HomePage.tsx index 62280da59d..f70ef07188 100644 --- a/frontends/main/src/app-pages/HomePage/HomePage.tsx +++ b/frontends/main/src/app-pages/HomePage/HomePage.tsx @@ -41,20 +41,20 @@ const MediaCarousel = styled(ResourceCarousel)(({ theme }) => ({ const HomePage: React.FC = () => { return ( <> - - - + - -
    - - - -
    + + +
    + + + +
    +
    diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx index bd4e0b6e59..be7f573269 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx @@ -143,6 +143,13 @@ const OnPlatform = styled.span` color: ${theme.custom.colors.black}; ` +const VideoFrame = styled.iframe<{ aspectRatio: string }>` + border-radius: 8px; + border: none; + width: 100%; + aspect-ratio: ${({ aspectRatio }) => aspectRatio}%; +` + type LearningResourceExpandedProps = { resource?: LearningResource user?: User @@ -155,16 +162,27 @@ const ImageSection: React.FC<{ resource?: LearningResource config: ImageConfig }> = ({ resource, config }) => { + const aspect = config.width / config.height if (resource?.resource_type === "video" && resource?.url) { - return ( - - ) + if (resource?.url?.startsWith("https://www.youtube.com/watch?v=")) { + const videoId = resource?.url?.split("v=")[1] + return ( + + ) + } + return } else if (resource?.image) { return ( - + + {resource.image?.alt Date: Tue, 29 Oct 2024 20:05:29 +0100 Subject: [PATCH 14/28] 16:9 aspect ratio for videos --- .../LearningResourceExpanded/LearningResourceExpanded.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx index be7f573269..19fc19164e 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpanded.tsx @@ -143,11 +143,11 @@ const OnPlatform = styled.span` color: ${theme.custom.colors.black}; ` -const VideoFrame = styled.iframe<{ aspectRatio: string }>` +const VideoFrame = styled.iframe` border-radius: 8px; border: none; width: 100%; - aspect-ratio: ${({ aspectRatio }) => aspectRatio}%; + aspect-ratio: 16 / 9; ` type LearningResourceExpandedProps = { @@ -168,9 +168,8 @@ const ImageSection: React.FC<{ const videoId = resource?.url?.split("v=")[1] return ( Date: Tue, 29 Oct 2024 20:10:31 +0100 Subject: [PATCH 15/28] Revert "Suspense boundaries needed around carousels (useSearchParams() should be wrapped error)" This reverts commit b96fb61dda988f114abed671b46bf1692eb95a34. --- .../main/src/app-pages/HomePage/HomePage.tsx | 26 ++++++++----------- frontends/main/src/app/search/page.tsx | 2 +- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/frontends/main/src/app-pages/HomePage/HomePage.tsx b/frontends/main/src/app-pages/HomePage/HomePage.tsx index f70ef07188..44d9739913 100644 --- a/frontends/main/src/app-pages/HomePage/HomePage.tsx +++ b/frontends/main/src/app-pages/HomePage/HomePage.tsx @@ -1,6 +1,6 @@ "use client" -import React, { Suspense } from "react" +import React from "react" import { Container, styled, theme } from "ol-components" import HeroSearch from "@/page-components/HeroSearch/HeroSearch" import BrowseTopicsSection from "./BrowseTopicsSection" @@ -46,25 +46,21 @@ const HomePage: React.FC = () => {
    - - - +
    - - - + diff --git a/frontends/main/src/app/search/page.tsx b/frontends/main/src/app/search/page.tsx index 71c7723373..94f7d88c9e 100644 --- a/frontends/main/src/app/search/page.tsx +++ b/frontends/main/src/app/search/page.tsx @@ -22,7 +22,7 @@ export async function generateMetadata({ * 1. wrap the in Suspense * 2. or force-dynamic. * - * (1) caused a hydration error for authenticated users. We have not found + * (1) caused a hydration error for authenticated users. We haven not found * the root cause of the hydration error. * * (2) seems to work well. From f97d90f049ea1dc9d233d7398721c2e1c3b038f3 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:12:13 +0100 Subject: [PATCH 16/28] Revert "Upgrade @mui/material-nextjs for Next.js v15" This reverts commit 18fee782bc9022e43827fd92a6f2895795f85f1c. --- frontends/ol-components/package.json | 4 +- frontends/ol-utilities/package.json | 1 - yarn.lock | 175 +++++++++++++++++++++++++-- 3 files changed, 166 insertions(+), 14 deletions(-) diff --git a/frontends/ol-components/package.json b/frontends/ol-components/package.json index 42329012c9..3cdaeab6f4 100644 --- a/frontends/ol-components/package.json +++ b/frontends/ol-components/package.json @@ -19,7 +19,7 @@ "@mui/base": "5.0.0-beta.60", "@mui/lab": "^5.0.0-alpha.172", "@mui/material": "^5.16.1", - "@mui/material-nextjs": "^6.1.5", + "@mui/material-nextjs": "^5.16.6", "@mui/system": "^5.16.1", "@remixicon/react": "^4.2.0", "@testing-library/dom": "^10.4.0", @@ -30,7 +30,7 @@ "iso-639-1": "^3.1.2", "lodash": "^4.17.21", "material-ui-popup-state": "^5.1.0", - "next": "^15.0.1", + "next": "^14.2.7", "ol-test-utilities": "0.0.0", "ol-utilities": "0.0.0", "react": "18.3.1", diff --git a/frontends/ol-utilities/package.json b/frontends/ol-utilities/package.json index a7bc89106a..a81c595f3a 100644 --- a/frontends/ol-utilities/package.json +++ b/frontends/ol-utilities/package.json @@ -21,7 +21,6 @@ "iso-639-1": "^3.1.0", "lodash": "^4.17.21", "moment": "^2.29.4", - "next": "^15.0.1", "qs": "^6.11.0", "react-helmet-async": "^2.0.3", "striptags": "^3.2.0" diff --git a/yarn.lock b/yarn.lock index ddf783011a..2a0b462ed5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3658,18 +3658,18 @@ __metadata: languageName: node linkType: hard -"@mui/material-nextjs@npm:^6.1.5": - version: 6.1.5 - resolution: "@mui/material-nextjs@npm:6.1.5" +"@mui/material-nextjs@npm:^5.16.6": + version: 5.16.6 + resolution: "@mui/material-nextjs@npm:5.16.6" dependencies: - "@babel/runtime": "npm:^7.25.7" + "@babel/runtime": "npm:^7.23.9" peerDependencies: "@emotion/cache": ^11.11.0 - "@emotion/react": ^11.11.4 "@emotion/server": ^11.11.0 - "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + "@mui/material": ^5.0.0 + "@types/react": ^17.0.0 || ^18.0.0 next: ^13.0.0 || ^14.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 peerDependenciesMeta: "@emotion/cache": optional: true @@ -3677,7 +3677,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 10/80fb5fc21751d872ff0ca669e136d7c1f8a72aa8353ab53fc8a3096a5e6791dd59de87ec1572a62dbe482eaf0f57b948e36a6a7807ad5acfbb1eda3c0ef542b7 + checksum: 10/bb58bd301944a0e8569ffc06e62f546c0aa89b025cd563030f4e7fba20b668d3b215a8ebf1c12bbf0df0449674414908e708a504c4dfa45345f9b8cd33f10e55 languageName: node linkType: hard @@ -3841,6 +3841,13 @@ __metadata: languageName: node linkType: hard +"@next/env@npm:14.2.16": + version: 14.2.16 + resolution: "@next/env@npm:14.2.16" + checksum: 10/b544711fafc04bcc5c6334885e6683398ee4ab3e2de5bfa3e34fca402f2882a1ca9b8a45d307204a218206b531e18de46b6705ed1f62e774f09fc214a94905cd + languageName: node + linkType: hard + "@next/env@npm:15.0.1": version: 15.0.1 resolution: "@next/env@npm:15.0.1" @@ -3857,6 +3864,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-darwin-arm64@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-darwin-arm64@npm:14.2.16" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@next/swc-darwin-arm64@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-darwin-arm64@npm:15.0.1" @@ -3864,6 +3878,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-darwin-x64@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-darwin-x64@npm:14.2.16" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@next/swc-darwin-x64@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-darwin-x64@npm:15.0.1" @@ -3871,6 +3892,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-arm64-gnu@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-linux-arm64-gnu@npm:14.2.16" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@next/swc-linux-arm64-gnu@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-arm64-gnu@npm:15.0.1" @@ -3878,6 +3906,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-arm64-musl@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-linux-arm64-musl@npm:14.2.16" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@next/swc-linux-arm64-musl@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-arm64-musl@npm:15.0.1" @@ -3885,6 +3920,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-x64-gnu@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-linux-x64-gnu@npm:14.2.16" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@next/swc-linux-x64-gnu@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-x64-gnu@npm:15.0.1" @@ -3892,6 +3934,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-linux-x64-musl@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-linux-x64-musl@npm:14.2.16" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@next/swc-linux-x64-musl@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-linux-x64-musl@npm:15.0.1" @@ -3899,6 +3948,13 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-arm64-msvc@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-win32-arm64-msvc@npm:14.2.16" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@next/swc-win32-arm64-msvc@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-win32-arm64-msvc@npm:15.0.1" @@ -3906,6 +3962,20 @@ __metadata: languageName: node linkType: hard +"@next/swc-win32-ia32-msvc@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-win32-ia32-msvc@npm:14.2.16" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@next/swc-win32-x64-msvc@npm:14.2.16": + version: 14.2.16 + resolution: "@next/swc-win32-x64-msvc@npm:14.2.16" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@next/swc-win32-x64-msvc@npm:15.0.1": version: 15.0.1 resolution: "@next/swc-win32-x64-msvc@npm:15.0.1" @@ -5708,6 +5778,16 @@ __metadata: languageName: node linkType: hard +"@swc/helpers@npm:0.5.5": + version: 0.5.5 + resolution: "@swc/helpers@npm:0.5.5" + dependencies: + "@swc/counter": "npm:^0.1.3" + tslib: "npm:^2.4.0" + checksum: 10/1c5ef04f642542212df28c669438f3e0f459dcde7b448a5b1fcafb2e9e4f13e76d8428535a270e91ed123dd2a21189dbed34086b88a8cf68baf84984d6d0e39b + languageName: node + linkType: hard + "@swc/jest@npm:^0.2.26": version: 0.2.36 resolution: "@swc/jest@npm:0.2.36" @@ -15567,6 +15647,64 @@ __metadata: languageName: node linkType: hard +"next@npm:^14.2.7": + version: 14.2.16 + resolution: "next@npm:14.2.16" + dependencies: + "@next/env": "npm:14.2.16" + "@next/swc-darwin-arm64": "npm:14.2.16" + "@next/swc-darwin-x64": "npm:14.2.16" + "@next/swc-linux-arm64-gnu": "npm:14.2.16" + "@next/swc-linux-arm64-musl": "npm:14.2.16" + "@next/swc-linux-x64-gnu": "npm:14.2.16" + "@next/swc-linux-x64-musl": "npm:14.2.16" + "@next/swc-win32-arm64-msvc": "npm:14.2.16" + "@next/swc-win32-ia32-msvc": "npm:14.2.16" + "@next/swc-win32-x64-msvc": "npm:14.2.16" + "@swc/helpers": "npm:0.5.5" + busboy: "npm:1.6.0" + caniuse-lite: "npm:^1.0.30001579" + graceful-fs: "npm:^4.2.11" + postcss: "npm:8.4.31" + styled-jsx: "npm:5.1.1" + peerDependencies: + "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.41.2 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + dependenciesMeta: + "@next/swc-darwin-arm64": + optional: true + "@next/swc-darwin-x64": + optional: true + "@next/swc-linux-arm64-gnu": + optional: true + "@next/swc-linux-arm64-musl": + optional: true + "@next/swc-linux-x64-gnu": + optional: true + "@next/swc-linux-x64-musl": + optional: true + "@next/swc-win32-arm64-msvc": + optional: true + "@next/swc-win32-ia32-msvc": + optional: true + "@next/swc-win32-x64-msvc": + optional: true + peerDependenciesMeta: + "@opentelemetry/api": + optional: true + "@playwright/test": + optional: true + sass: + optional: true + bin: + next: dist/bin/next + checksum: 10/819e28509649ad290647f16b02b5a051c568892a4255a7606bed0b253466529bd9caf6947233c3b3643c3c6d14b95e8e7a74f793baeb223c3519e8eaa36aaa2a + languageName: node + linkType: hard + "next@npm:^15.0.1": version: 15.0.1 resolution: "next@npm:15.0.1" @@ -15987,7 +16125,7 @@ __metadata: "@mui/base": "npm:5.0.0-beta.60" "@mui/lab": "npm:^5.0.0-alpha.172" "@mui/material": "npm:^5.16.1" - "@mui/material-nextjs": "npm:^6.1.5" + "@mui/material-nextjs": "npm:^5.16.6" "@mui/system": "npm:^5.16.1" "@remixicon/react": "npm:^4.2.0" "@storybook/addon-actions": "npm:^8.2.9" @@ -16015,7 +16153,7 @@ __metadata: iso-639-1: "npm:^3.1.2" lodash: "npm:^4.17.21" material-ui-popup-state: "npm:^5.1.0" - next: "npm:^15.0.1" + next: "npm:^14.2.7" ol-test-utilities: "npm:0.0.0" ol-utilities: "npm:0.0.0" prop-types: "npm:^15.8.1" @@ -16068,7 +16206,6 @@ __metadata: iso-639-1: "npm:^3.1.0" lodash: "npm:^4.17.21" moment: "npm:^2.29.4" - next: "npm:^15.0.1" qs: "npm:^6.11.0" react-helmet-async: "npm:^2.0.3" striptags: "npm:^3.2.0" @@ -19341,6 +19478,22 @@ __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: "npm:0.0.1" + peerDependencies: + react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" + peerDependenciesMeta: + "@babel/core": + optional: true + babel-plugin-macros: + optional: true + checksum: 10/4f6a5d0010770fdeea1183d919d528fd46c484e23c0535ef3e1dd49488116f639c594f3bd4440e3bc8a8686c9f8d53c5761599870ff039ede11a5c3bfe08a4be + languageName: node + linkType: hard + "styled-jsx@npm:5.1.6, styled-jsx@npm:^5.1.6": version: 5.1.6 resolution: "styled-jsx@npm:5.1.6" From eb5b317cf05817c2680f188db29ae452129f6497 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:14:13 +0100 Subject: [PATCH 17/28] Revert "Upgrade to Next.js v15. Page params are now async" This reverts commit 20f0f054ff4ad3464911fc31b857967f24e503fd. --- frontends/main/package.json | 2 +- .../src/app/c/[channelType]/[name]/page.tsx | 10 +- .../main/src/app/dashboard/[tab]/page.tsx | 1 - frontends/main/src/app/page.tsx | 6 +- frontends/main/src/app/search/page.tsx | 6 +- frontends/main/src/common/metadata.ts | 4 +- yarn.lock | 143 +----------------- 7 files changed, 13 insertions(+), 159 deletions(-) diff --git a/frontends/main/package.json b/frontends/main/package.json index a69f910e22..dec56e6013 100644 --- a/frontends/main/package.json +++ b/frontends/main/package.json @@ -20,7 +20,7 @@ "api": "workspace:*", "formik": "^2.4.6", "lodash": "^4.17.21", - "next": "^15.0.1", + "next": "^14.2.15", "ol-ckeditor": "0.0.0", "ol-components": "0.0.0", "ol-utilities": "0.0.0", diff --git a/frontends/main/src/app/c/[channelType]/[name]/page.tsx b/frontends/main/src/app/c/[channelType]/[name]/page.tsx index 5cc73220e1..5c33fb3e1a 100644 --- a/frontends/main/src/app/c/[channelType]/[name]/page.tsx +++ b/frontends/main/src/app/c/[channelType]/[name]/page.tsx @@ -5,10 +5,6 @@ import { ChannelTypeEnum } from "api/v0" import { getMetadataAsync } from "@/common/metadata" import handleNotFound from "@/common/handleNotFound" -type SearchParams = { - [key: string]: string | string[] | undefined -} - type RouteParams = { channelType: ChannelTypeEnum name: string @@ -18,10 +14,10 @@ export async function generateMetadata({ searchParams, params, }: { - searchParams: Promise - params: Promise + searchParams: { [key: string]: string | string[] | undefined } + params: RouteParams }) { - const { channelType, name } = await params + const { channelType, name } = params const { data } = await handleNotFound( channelsApi.channelsTypeRetrieve({ channel_type: channelType, name: name }), diff --git a/frontends/main/src/app/dashboard/[tab]/page.tsx b/frontends/main/src/app/dashboard/[tab]/page.tsx index 082710c443..3586bb6208 100644 --- a/frontends/main/src/app/dashboard/[tab]/page.tsx +++ b/frontends/main/src/app/dashboard/[tab]/page.tsx @@ -10,7 +10,6 @@ export const metadata: Metadata = standardizeMetadata({ title: "Your MIT Learning Journey", social: false, }) - const Page: React.FC = () => { return ( diff --git a/frontends/main/src/app/page.tsx b/frontends/main/src/app/page.tsx index 34dd27b718..f6406e519a 100644 --- a/frontends/main/src/app/page.tsx +++ b/frontends/main/src/app/page.tsx @@ -3,14 +3,10 @@ import type { Metadata } from "next" import HomePage from "@/app-pages/HomePage/HomePage" import { getMetadataAsync } from "@/common/metadata" -type SearchParams = { - [key: string]: string | string[] | undefined -} - export async function generateMetadata({ searchParams, }: { - searchParams: Promise + searchParams: { [key: string]: string | string[] | undefined } }): Promise { return await getMetadataAsync({ title: "Learn with MIT", diff --git a/frontends/main/src/app/search/page.tsx b/frontends/main/src/app/search/page.tsx index 94f7d88c9e..adc7151f65 100644 --- a/frontends/main/src/app/search/page.tsx +++ b/frontends/main/src/app/search/page.tsx @@ -2,14 +2,10 @@ import React from "react" import { getMetadataAsync } from "@/common/metadata" import SearchPage from "@/app-pages/SearchPage/SearchPage" -type SearchParams = { - [key: string]: string | string[] | undefined -} - export async function generateMetadata({ searchParams, }: { - searchParams: Promise + searchParams: { [key: string]: string | string[] | undefined } }) { return await getMetadataAsync({ title: "Search", diff --git a/frontends/main/src/common/metadata.ts b/frontends/main/src/common/metadata.ts index 583e5a6383..c112873175 100644 --- a/frontends/main/src/common/metadata.ts +++ b/frontends/main/src/common/metadata.ts @@ -10,7 +10,7 @@ type MetadataAsyncProps = { description?: string image?: string imageAlt?: string - searchParams?: Promise<{ [key: string]: string | string[] | undefined }> + searchParams?: { [key: string]: string | string[] | undefined } social?: boolean } & Metadata @@ -28,7 +28,7 @@ export const getMetadataAsync = async ({ ...otherMeta }: MetadataAsyncProps) => { // The learning resource drawer is open - const learningResourceId = (await searchParams)?.[RESOURCE_DRAWER_QUERY_PARAM] + const learningResourceId = searchParams?.[RESOURCE_DRAWER_QUERY_PARAM] if (learningResourceId) { const { data } = await handleNotFound( learningResourcesApi.learningResourcesRetrieve({ diff --git a/yarn.lock b/yarn.lock index 2a0b462ed5..4a4c843e36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3848,13 +3848,6 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:15.0.1": - version: 15.0.1 - resolution: "@next/env@npm:15.0.1" - checksum: 10/0e7eb9600e6b9963de8faee6d044591e9408b106b122e27714db0d3f07812d442ec1352cf70b55ea49ac30ded9de1b03ba401952f2aad4c7e85c441628fc6ce0 - languageName: node - linkType: hard - "@next/eslint-plugin-next@npm:14.2.15, @next/eslint-plugin-next@npm:^14.2.7": version: 14.2.15 resolution: "@next/eslint-plugin-next@npm:14.2.15" @@ -3871,13 +3864,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-darwin-arm64@npm:15.0.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - "@next/swc-darwin-x64@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-darwin-x64@npm:14.2.16" @@ -3885,13 +3871,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-x64@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-darwin-x64@npm:15.0.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - "@next/swc-linux-arm64-gnu@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-linux-arm64-gnu@npm:14.2.16" @@ -3899,13 +3878,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-linux-arm64-gnu@npm:15.0.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - "@next/swc-linux-arm64-musl@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-linux-arm64-musl@npm:14.2.16" @@ -3913,13 +3885,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-linux-arm64-musl@npm:15.0.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - "@next/swc-linux-x64-gnu@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-linux-x64-gnu@npm:14.2.16" @@ -3927,13 +3892,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-linux-x64-gnu@npm:15.0.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - "@next/swc-linux-x64-musl@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-linux-x64-musl@npm:14.2.16" @@ -3941,13 +3899,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-linux-x64-musl@npm:15.0.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - "@next/swc-win32-arm64-msvc@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-win32-arm64-msvc@npm:14.2.16" @@ -3955,13 +3906,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-win32-arm64-msvc@npm:15.0.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "@next/swc-win32-ia32-msvc@npm:14.2.16": version: 14.2.16 resolution: "@next/swc-win32-ia32-msvc@npm:14.2.16" @@ -3976,13 +3920,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:15.0.1": - version: 15.0.1 - resolution: "@next/swc-win32-x64-msvc@npm:15.0.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": version: 5.1.1-v1 resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" @@ -5762,22 +5699,13 @@ __metadata: languageName: node linkType: hard -"@swc/counter@npm:0.1.3, @swc/counter@npm:^0.1.3": +"@swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard -"@swc/helpers@npm:0.5.13": - version: 0.5.13 - resolution: "@swc/helpers@npm:0.5.13" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10/6ba2f7e215d32d71fce139e2cfc426b3ed7eaa709febdeb07b97260a4c9eea4784cf047cc1271be273990b08220b576b94a42b5780947c0b3be84973a847a24d - languageName: node - linkType: hard - "@swc/helpers@npm:0.5.5": version: 0.5.5 resolution: "@swc/helpers@npm:0.5.5" @@ -14187,7 +14115,7 @@ __metadata: jest: "npm:^29.7.0" jest-extended: "npm:^4.0.2" lodash: "npm:^4.17.21" - next: "npm:^15.0.1" + next: "npm:^14.2.15" ol-ckeditor: "npm:0.0.0" ol-components: "npm:0.0.0" ol-test-utilities: "npm:0.0.0" @@ -15647,7 +15575,7 @@ __metadata: languageName: node linkType: hard -"next@npm:^14.2.7": +"next@npm:^14.2.15, next@npm:^14.2.7": version: 14.2.16 resolution: "next@npm:14.2.16" dependencies: @@ -15705,67 +15633,6 @@ __metadata: languageName: node linkType: hard -"next@npm:^15.0.1": - version: 15.0.1 - resolution: "next@npm:15.0.1" - dependencies: - "@next/env": "npm:15.0.1" - "@next/swc-darwin-arm64": "npm:15.0.1" - "@next/swc-darwin-x64": "npm:15.0.1" - "@next/swc-linux-arm64-gnu": "npm:15.0.1" - "@next/swc-linux-arm64-musl": "npm:15.0.1" - "@next/swc-linux-x64-gnu": "npm:15.0.1" - "@next/swc-linux-x64-musl": "npm:15.0.1" - "@next/swc-win32-arm64-msvc": "npm:15.0.1" - "@next/swc-win32-x64-msvc": "npm:15.0.1" - "@swc/counter": "npm:0.1.3" - "@swc/helpers": "npm:0.5.13" - busboy: "npm:1.6.0" - caniuse-lite: "npm:^1.0.30001579" - postcss: "npm:8.4.31" - sharp: "npm:^0.33.5" - styled-jsx: "npm:5.1.6" - peerDependencies: - "@opentelemetry/api": ^1.1.0 - "@playwright/test": ^1.41.2 - babel-plugin-react-compiler: "*" - react: ^18.2.0 || 19.0.0-rc-69d4b800-20241021 - react-dom: ^18.2.0 || 19.0.0-rc-69d4b800-20241021 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - sharp: - optional: true - peerDependenciesMeta: - "@opentelemetry/api": - optional: true - "@playwright/test": - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: 10/2919d98749e3d2f4cb21aa87f258aec947678f4dae6ffcaea0190e06d623a723cbdade995a66e8d5ad5e7b0be295554615feb388162b268f99d9a8cbd544ba76 - languageName: node - linkType: hard - "no-case@npm:^3.0.4": version: 3.0.4 resolution: "no-case@npm:3.0.4" @@ -18752,7 +18619,7 @@ __metadata: languageName: node linkType: hard -"sharp@npm:^0.33.3, sharp@npm:^0.33.5": +"sharp@npm:^0.33.3": version: 0.33.5 resolution: "sharp@npm:0.33.5" dependencies: @@ -19494,7 +19361,7 @@ __metadata: languageName: node linkType: hard -"styled-jsx@npm:5.1.6, styled-jsx@npm:^5.1.6": +"styled-jsx@npm:^5.1.6": version: 5.1.6 resolution: "styled-jsx@npm:5.1.6" dependencies: From 00ef518c5c852ef78b882abf37febb4561b54d7d Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Tue, 29 Oct 2024 22:15:16 +0100 Subject: [PATCH 18/28] Update test for unit logo --- .../ChannelPage/ChannelPage.test.tsx | 21 ++++++++++++++++--- .../main/src/app-pages/HomePage/HomePage.tsx | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frontends/main/src/app-pages/ChannelPage/ChannelPage.test.tsx b/frontends/main/src/app-pages/ChannelPage/ChannelPage.test.tsx index 1835398066..d1232c6f46 100644 --- a/frontends/main/src/app-pages/ChannelPage/ChannelPage.test.tsx +++ b/frontends/main/src/app-pages/ChannelPage/ChannelPage.test.tsx @@ -379,7 +379,7 @@ describe("Channel Pages, Topic only", () => { }) describe("Channel Pages, Unit only", () => { - it("Displays the channel title, banner, and avatar", async () => { + it("Displays the channel title, banner", async () => { const { channel } = setupApis({ search_filter: "offered_by=ocw", channel_type: "unit", @@ -388,9 +388,24 @@ describe("Channel Pages, Unit only", () => { url: `/c/${channel.channel_type}/${channel.name}`, }) - const title = await screen.findByRole("heading", { name: channel.title }) - getByImageSrc(title, `${window.origin}${channel.configuration.logo}`) + await screen.findByRole("heading", { name: channel.title }) }) + + it("Displays the channel logo", async () => { + const { channel } = setupApis({ + name: "ocw", + channel_type: "unit", + }) + renderWithProviders(, { + url: `/c/${channel.channel_type}/${channel.name}`, + }) + + const images = await screen.findAllByRole("img", { + name: "MIT OpenCourseWare", + }) + expect(images[0]).toHaveAttribute("src", "/images/unit_logos/ocw.svg") + }) + it("Displays a featured carousel if the channel type is 'unit'", async () => { const { channel } = setupApis({ search_filter: "offered_by=ocw", diff --git a/frontends/main/src/app-pages/HomePage/HomePage.tsx b/frontends/main/src/app-pages/HomePage/HomePage.tsx index 44d9739913..553c797d70 100644 --- a/frontends/main/src/app-pages/HomePage/HomePage.tsx +++ b/frontends/main/src/app-pages/HomePage/HomePage.tsx @@ -43,7 +43,7 @@ const HomePage: React.FC = () => { <> - +
    Date: Tue, 29 Oct 2024 22:19:35 +0100 Subject: [PATCH 19/28] Add Nextjs dependency in ol-utilities --- frontends/ol-utilities/package.json | 1 + yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/frontends/ol-utilities/package.json b/frontends/ol-utilities/package.json index a81c595f3a..01b05d62ab 100644 --- a/frontends/ol-utilities/package.json +++ b/frontends/ol-utilities/package.json @@ -21,6 +21,7 @@ "iso-639-1": "^3.1.0", "lodash": "^4.17.21", "moment": "^2.29.4", + "next": "^14.2.15", "qs": "^6.11.0", "react-helmet-async": "^2.0.3", "striptags": "^3.2.0" diff --git a/yarn.lock b/yarn.lock index 4a4c843e36..eaebadd052 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16073,6 +16073,7 @@ __metadata: iso-639-1: "npm:^3.1.0" lodash: "npm:^4.17.21" moment: "npm:^2.29.4" + next: "npm:^14.2.15" qs: "npm:^6.11.0" react-helmet-async: "npm:^2.0.3" striptags: "npm:^3.2.0" From d75212ab0d078b7d490595e792a218802e14ceac Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:43:49 +0100 Subject: [PATCH 20/28] Remove comments --- frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx index bb6abce574..da3869e627 100644 --- a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx +++ b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx @@ -192,14 +192,10 @@ export const UnitCards: React.FC = (props) => { {units?.map((unit) => { const courseCount = courseCounts[unit.code] || 0 const programCount = programCounts[unit.code] || 0 - // const logo = - // UNIT_LOGOS[unit.code as OfferedByEnum]?.image || - // `/images/unit_logos/${unit.code}.svg` return unit.value_prop ? ( From 0ce9cf906b47a4c1caf1e11bf8c47f88d00f0fee Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:46:39 +0100 Subject: [PATCH 21/28] Remove unnecessary truthy check --- frontends/ol-utilities/src/images/backgroundImages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/ol-utilities/src/images/backgroundImages.ts b/frontends/ol-utilities/src/images/backgroundImages.ts index 96e031ff76..a292365651 100644 --- a/frontends/ol-utilities/src/images/backgroundImages.ts +++ b/frontends/ol-utilities/src/images/backgroundImages.ts @@ -23,5 +23,5 @@ export const backgroundSrcSetCSS = (image: ImageProps["src"]) => { }) .join(", ") - return imageSet ? `image-set(${imageSet})` : "" + return `image-set(${imageSet})` } From e38f0d96073b8ed757ae60a08729bfa1ae7fdd10 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:56:03 +0100 Subject: [PATCH 22/28] Separate Unit/Platform Logo --- .../ChannelPage/UnitChannelTemplate.tsx | 8 +-- .../app-pages/UnitsListingPage/UnitCard.tsx | 4 +- .../src/components/Logo/Logo.tsx | 67 +++++++++++++++---- 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx index a30c2d4135..b475594dfc 100644 --- a/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx @@ -8,7 +8,7 @@ import { BannerBackground, Typography, VisuallyHidden, - PlatformLogo, + UnitLogo, } from "ol-components" import { OfferedByEnum, SourceTypeEnum } from "api" import { SearchSubscriptionToggle } from "@/page-components/SearchSubscriptionToggle/SearchSubscriptionToggle" @@ -53,7 +53,7 @@ const DesktopOnly = styled.div(({ theme }) => ({ }, })) -const PlatformLogoInverted = styled(PlatformLogo)({ +const UnitLogoInverted = styled(UnitLogo)({ filter: "saturate(0%) invert(100%)", }) @@ -137,13 +137,13 @@ const UnitChannelTemplate: React.FC = ({ {channel.data ? ( <> - - diff --git a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx index da3869e627..39e5e5ee2a 100644 --- a/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx +++ b/frontends/main/src/app-pages/UnitsListingPage/UnitCard.tsx @@ -6,7 +6,7 @@ import { Typography, styled, theme, - PlatformLogo, + UnitLogo, } from "ol-components" import { useChannelDetail } from "api/hooks/channels" @@ -139,7 +139,7 @@ const UnitCard: React.FC = (props) => { - + diff --git a/frontends/ol-components/src/components/Logo/Logo.tsx b/frontends/ol-components/src/components/Logo/Logo.tsx index 022f5efc57..5c9d8f52fc 100644 --- a/frontends/ol-components/src/components/Logo/Logo.tsx +++ b/frontends/ol-components/src/components/Logo/Logo.tsx @@ -101,18 +101,15 @@ export const PLATFORM_LOGOS: Record = { const DEFAULT_WIDTH = 200 -export const PlatformLogo: React.FC<{ - unitCode?: OfferedByEnum - platformCode?: PlatformEnum +const Logo: React.FC<{ + name: string + image: string + aspect: number className?: string width?: number height?: number -}> = ({ unitCode, platformCode, className, width, height }) => { - const platform = unitCode - ? UNIT_LOGOS[unitCode] - : PLATFORM_LOGOS[platformCode!] - - if (!platform?.image) { +}> = ({ name, image, aspect, className, width, height }) => { + if (!image) { return null } @@ -124,21 +121,63 @@ export const PlatformLogo: React.FC<{ * not actually applying - "Using `` could result in slower LCP and higher bandwidth.". */ if (width && !height) { - height = width / platform.aspect + height = width / aspect } if (!width && height) { - width = height * platform.aspect + width = height * aspect } if (!width) { width = DEFAULT_WIDTH - height = width / platform.aspect + height = width / aspect } return ( {name} + ) +} + +export const UnitLogo: React.FC<{ + unitCode: OfferedByEnum + className?: string + width?: number + height?: number +}> = ({ unitCode, className, width, height }) => { + const unit = UNIT_LOGOS[unitCode] + if (!unit?.image) return null + const { name, image, aspect } = unit + return ( + + ) +} + +export const PlatformLogo: React.FC<{ + platformCode: PlatformEnum + className?: string + width?: number + height?: number +}> = ({ platformCode, className, width, height }) => { + const platform = PLATFORM_LOGOS[platformCode] + if (!platform?.image) return null + const { name, image, aspect } = platform + return ( + From 1086dde5a263ec53af5124e8ecf047a83bf4d60a Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:58:27 +0100 Subject: [PATCH 23/28] Move to peer dependency --- frontends/ol-utilities/package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/ol-utilities/package.json b/frontends/ol-utilities/package.json index 01b05d62ab..d8902a24d0 100644 --- a/frontends/ol-utilities/package.json +++ b/frontends/ol-utilities/package.json @@ -7,6 +7,7 @@ "./test-utils/factories": "./src/test-utils/factories.ts" }, "peerDependencies": { + "next": "^14.2.15", "react": "18.3.1" }, "dependencies": { @@ -21,7 +22,6 @@ "iso-639-1": "^3.1.0", "lodash": "^4.17.21", "moment": "^2.29.4", - "next": "^14.2.15", "qs": "^6.11.0", "react-helmet-async": "^2.0.3", "striptags": "^3.2.0" diff --git a/yarn.lock b/yarn.lock index eaebadd052..750b3ebf6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16073,12 +16073,12 @@ __metadata: iso-639-1: "npm:^3.1.0" lodash: "npm:^4.17.21" moment: "npm:^2.29.4" - next: "npm:^14.2.15" qs: "npm:^6.11.0" react-helmet-async: "npm:^2.0.3" striptags: "npm:^3.2.0" tiny-invariant: "npm:^1.3.1" peerDependencies: + next: ^14.2.15 react: 18.3.1 languageName: unknown linkType: soft From 36a3982e9f8203ead673b6533c78f4c3623035ed Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:03:40 +0100 Subject: [PATCH 24/28] Bckground src set for topic banner --- .../TopicsListingPage/TopicsListingPage.tsx | 4 +- .../src/components/Banner/Banner.tsx | 46 +++++++++++-------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx b/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx index e01672d355..3177059a4f 100644 --- a/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx +++ b/frontends/main/src/app-pages/TopicsListingPage/TopicsListingPage.tsx @@ -14,7 +14,7 @@ import { Breadcrumbs, } from "ol-components" import Link from "next/link" -import { propsNotNil } from "ol-utilities" +import { propsNotNil, backgroundSrcSetCSS } from "ol-utilities" import { useLearningResourceTopics } from "api/hooks/learningResources" import { LearningResourceTopic } from "api" import RootTopicIcon from "@/components/RootTopicIcon/RootTopicIcon" @@ -275,7 +275,7 @@ const TopicsListingPage: React.FC = () => { } title="Browse by Topic" header="Select a topic below to explore relevant learning resources across all Academic and Professional units." - backgroundUrl={backgroundSteps.src} + backgroundUrl={backgroundSrcSetCSS(backgroundSteps)} /> diff --git a/frontends/ol-components/src/components/Banner/Banner.tsx b/frontends/ol-components/src/components/Banner/Banner.tsx index a908fb5a74..50b4ea6308 100644 --- a/frontends/ol-components/src/components/Banner/Banner.tsx +++ b/frontends/ol-components/src/components/Banner/Banner.tsx @@ -27,26 +27,32 @@ const BannerBackground = styled.div( backgroundUrl = DEFAULT_BACKGROUND_IMAGE_URL, backgroundSize = "cover", backgroundDim = 0, - }) => ({ - backgroundAttachment: "fixed", - backgroundImage: backgroundDim - ? `linear-gradient(rgba(0 0 0 / ${backgroundDim}%), rgba(0 0 0 / ${backgroundDim}%)), url('${backgroundUrl}')` - : `url(${backgroundUrl})`, - backgroundSize: backgroundSize, - backgroundPosition: "center top", - backgroundRepeat: "no-repeat", - color: theme.custom.colors.white, - padding: "48px 0 48px 0", - [theme.breakpoints.up("lg")]: { - backgroundSize: - backgroundUrl === DEFAULT_BACKGROUND_IMAGE_URL - ? "140%" - : backgroundSize, - }, - [theme.breakpoints.down("sm")]: { - padding: "32px 0 32px 0", - }, - }), + }) => { + const backgroundUrlFn = backgroundUrl.startsWith("image-set(") + ? backgroundUrl + : `url('${backgroundUrl}')` + + return { + backgroundAttachment: "fixed", + backgroundImage: backgroundDim + ? `linear-gradient(rgba(0 0 0 / ${backgroundDim}%), rgba(0 0 0 / ${backgroundDim}%)), ${backgroundUrlFn}')` + : backgroundUrlFn, + backgroundSize: backgroundSize, + backgroundPosition: "center top", + backgroundRepeat: "no-repeat", + color: theme.custom.colors.white, + padding: "48px 0 48px 0", + [theme.breakpoints.up("lg")]: { + backgroundSize: + backgroundUrl === DEFAULT_BACKGROUND_IMAGE_URL + ? "140%" + : backgroundSize, + }, + [theme.breakpoints.down("sm")]: { + padding: "32px 0 32px 0", + }, + } + }, ) const InnerContainer = styled.div(({ theme }) => ({ From c868b004cdbd5e716b4447e7b063e8674ef754e5 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:12:30 +0100 Subject: [PATCH 25/28] Background src set on other banner backgrounds --- .../src/app-pages/ChannelPage/DefaultChannelTemplate.tsx | 4 +++- .../main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx | 5 +++-- .../DepartmentListingPage/DepartmentListingPage.tsx | 4 ++-- .../main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx | 3 ++- frontends/ol-components/src/components/Banner/Banner.tsx | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx index c2d27998d3..4114a0b4f4 100644 --- a/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/DefaultChannelTemplate.tsx @@ -1,5 +1,6 @@ import React from "react" import { styled, Breadcrumbs, Banner } from "ol-components" +import { backgroundSrcSetCSS } from "ol-utilities" import { SearchSubscriptionToggle } from "@/page-components/SearchSubscriptionToggle/SearchSubscriptionToggle" import { useChannelDetail } from "api/hooks/channels" import ChannelMenu from "@/components/ChannelMenu/ChannelMenu" @@ -90,7 +91,8 @@ const DefaultChannelTemplate: React.FC = ({ header={displayConfiguration?.heading} subHeader={displayConfiguration?.sub_heading} backgroundUrl={ - displayConfiguration?.banner_background ?? backgroundSteps + displayConfiguration?.banner_background ?? + backgroundSrcSetCSS(backgroundSteps) } extraActions={ diff --git a/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx index 73f1a3b379..f4b2a5de69 100644 --- a/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/TopicChannelTemplate.tsx @@ -23,7 +23,7 @@ import { useLearningResourceTopic, useLearningResourceTopics, } from "api/hooks/learningResources" -import { propsNotNil } from "ol-utilities" +import { propsNotNil, backgroundSrcSetCSS } from "ol-utilities" import invariant from "tiny-invariant" import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" @@ -250,7 +250,8 @@ const TopicChannelTemplateInternal: React.FC< subHeader={displayConfiguration?.sub_heading} extraHeader={} backgroundUrl={ - displayConfiguration?.banner_background ?? backgroundSteps.src + displayConfiguration?.banner_background ?? + backgroundSrcSetCSS(backgroundSteps) } extraActions={ diff --git a/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx b/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx index cbdda18e8e..8399d741db 100644 --- a/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx +++ b/frontends/main/src/app-pages/DepartmentListingPage/DepartmentListingPage.tsx @@ -13,7 +13,7 @@ import { Banner, Breadcrumbs, } from "ol-components" -import { pluralize } from "ol-utilities" +import { pluralize, backgroundSrcSetCSS } from "ol-utilities" import type { LearningResourceSchool } from "api" import { useSchoolsList } from "api/hooks/learningResources" import { @@ -210,7 +210,7 @@ const DepartmentListingPage: React.FC = () => { current="Departments" /> } - backgroundUrl={backgroundSteps.src} + backgroundUrl={backgroundSrcSetCSS(backgroundSteps)} /> diff --git a/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx b/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx index 5494f33f03..112de6ea7e 100644 --- a/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx +++ b/frontends/main/src/app-pages/UnitsListingPage/UnitsListingPage.tsx @@ -11,6 +11,7 @@ import { theme, Breadcrumbs, } from "ol-components" +import { backgroundSrcSetCSS } from "ol-utilities" import backgroundSteps from "@/public/images/backgrounds/background_steps.jpg" import { RiBookOpenLine, RiSuitcaseLine } from "@remixicon/react" import { LearningResourceOfferorDetail } from "api" @@ -248,7 +249,7 @@ const UnitsListingPage: React.FC = () => { } title="Academic & Professional Learning" header="Non-degree learning resources tailored to the needs of students and working professionals." - backgroundUrl={backgroundSteps.src} + backgroundUrl={backgroundSrcSetCSS(backgroundSteps)} /> diff --git a/frontends/ol-components/src/components/Banner/Banner.tsx b/frontends/ol-components/src/components/Banner/Banner.tsx index 50b4ea6308..22dd0bdaa6 100644 --- a/frontends/ol-components/src/components/Banner/Banner.tsx +++ b/frontends/ol-components/src/components/Banner/Banner.tsx @@ -35,7 +35,7 @@ const BannerBackground = styled.div( return { backgroundAttachment: "fixed", backgroundImage: backgroundDim - ? `linear-gradient(rgba(0 0 0 / ${backgroundDim}%), rgba(0 0 0 / ${backgroundDim}%)), ${backgroundUrlFn}')` + ? `linear-gradient(rgba(0 0 0 / ${backgroundDim}%), rgba(0 0 0 / ${backgroundDim}%)), ${backgroundUrlFn}` : backgroundUrlFn, backgroundSize: backgroundSize, backgroundPosition: "center top", From 9386f27c34437d7ee64432589c39c47413a1d402 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:18:03 +0100 Subject: [PATCH 26/28] Remove redundant display breakpoints --- .../ChannelPage/UnitChannelTemplate.tsx | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx b/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx index b475594dfc..d6e8b6c9e0 100644 --- a/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx +++ b/frontends/main/src/app-pages/ChannelPage/UnitChannelTemplate.tsx @@ -39,24 +39,16 @@ const FeaturedCoursesCarousel = styled(ResourceCarousel)(({ theme }) => ({ }, })) -const MobileOnly = styled.div(({ theme }) => ({ - display: "contents", - [theme.breakpoints.up("md")]: { - display: "none", - }, -})) - -const DesktopOnly = styled.div(({ theme }) => ({ - display: "contents", +const UnitLogoInverted = styled(UnitLogo)(({ theme }) => ({ + filter: "saturate(0%) invert(100%)", + height: 50, + maxWidth: "100%", [theme.breakpoints.down("md")]: { - display: "none", + height: 40, + width: "auto", }, })) -const UnitLogoInverted = styled(UnitLogo)({ - filter: "saturate(0%) invert(100%)", -}) - const BannerContent = styled.div(({ theme }) => ({ display: "flex", flexDirection: "row", @@ -135,20 +127,10 @@ const UnitChannelTemplate: React.FC = ({ {channel.data?.title} {channel.data ? ( - <> - - - - - - - + ) : null} From 9fc386adc0b4e55233433fdfa265b0f535aa4aef Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:11:27 +0100 Subject: [PATCH 27/28] Apply changes to LearningResourceExpandedV2 --- .../LearningResourceExpandedV1.tsx | 31 ++------- .../LearningResourceExpandedV2.tsx | 68 +++++++++---------- .../LearningResourceExpanded/VideoFrame.tsx | 32 +++++++++ 3 files changed, 70 insertions(+), 61 deletions(-) create mode 100644 frontends/ol-components/src/components/LearningResourceExpanded/VideoFrame.tsx diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV1.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV1.tsx index b279f14ff4..a0155829db 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV1.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV1.tsx @@ -16,12 +16,12 @@ import { RiExternalLinkLine } from "@remixicon/react" import { theme } from "../ThemeProvider/ThemeProvider" import { SimpleSelect } from "../SimpleSelect/SimpleSelect" import type { SimpleSelectProps } from "../SimpleSelect/SimpleSelect" -import { EmbedlyCard } from "../EmbedlyCard/EmbedlyCard" import { PlatformLogo, PLATFORM_LOGOS } from "../Logo/Logo" import InfoSectionV1 from "./InfoSectionV1" import type { User } from "api/hooks/user" import { LearningResourceCardProps } from "../LearningResourceCard/LearningResourceCard" import type { ImageConfig } from "../../constants/imgConfigs" +import VideoFrame from "./VideoFrame" const Container = styled.div<{ padTop?: boolean }>` display: flex; @@ -143,13 +143,6 @@ const OnPlatform = styled.span` color: ${theme.custom.colors.black}; ` -const VideoFrame = styled.iframe` - border-radius: 8px; - border: none; - width: 100%; - aspect-ratio: 16 / 9; -` - type LearningResourceExpandedV1Props = { resource?: LearningResource user?: User @@ -164,28 +157,16 @@ const ImageSection: React.FC<{ }> = ({ resource, config }) => { const aspect = config.width / config.height if (resource?.resource_type === "video" && resource?.url) { - if (resource?.url?.startsWith("https://www.youtube.com/watch?v=")) { - const videoId = resource?.url?.split("v=")[1] - return ( - - ) - } - return + return ( + + ) } else if (resource?.image) { return ( {resource?.image.alt ) @@ -195,7 +176,7 @@ const ImageSection: React.FC<{ {resource.image?.alt ) diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx index 5b3506d9a8..d273f2f9cb 100644 --- a/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx +++ b/frontends/ol-components/src/components/LearningResourceExpanded/LearningResourceExpandedV2.tsx @@ -2,28 +2,25 @@ import React from "react" import styled from "@emotion/styled" import Skeleton from "@mui/material/Skeleton" import Typography from "@mui/material/Typography" +import { default as NextImage } from "next/image" import { ActionButton, ButtonLink } from "../Button/Button" import type { LearningResource } from "api" import { ResourceTypeEnum, PlatformEnum } from "api" -import { - resourceThumbnailSrc, - DEFAULT_RESOURCE_IMG, - getReadableResourceType, -} from "ol-utilities" +import { DEFAULT_RESOURCE_IMG, getReadableResourceType } from "ol-utilities" import { RiBookmarkLine, RiCloseLargeLine, RiExternalLinkLine, RiMenuAddLine, } from "@remixicon/react" -import type { EmbedlyConfig } from "ol-utilities" +import type { ImageConfig } from "../../constants/imgConfigs" import { theme } from "../ThemeProvider/ThemeProvider" -import { EmbedlyCard } from "../EmbedlyCard/EmbedlyCard" -import { PlatformLogo, PLATFORMS } from "../Logo/Logo" +import { PlatformLogo, PLATFORM_LOGOS } from "../Logo/Logo" import InfoSectionV2 from "./InfoSectionV2" import type { User } from "api/hooks/user" import { LearningResourceCardProps } from "../LearningResourceCard/LearningResourceCard" import { CardActionButton } from "../LearningResourceCard/LearningResourceListCard" +import VideoFrame from "./VideoFrame" const Container = styled.div({ display: "flex", @@ -81,17 +78,17 @@ const RightContainer = styled.div({ }, }) -const EmbedlyContainer = styled.div({ - width: "100%", - overflow: "hidden", -}) +const ImageContainer = styled.div<{ aspect: number }>` + position: relative; + width: 100%; + padding-bottom: ${({ aspect }) => 100 / aspect}%; +` -const Image = styled.img<{ aspect: number }>((aspect) => ({ - aspectRatio: aspect.aspect, +const Image = styled(NextImage)({ borderRadius: "8px", width: "100%", objectFit: "cover", -})) +}) const SkeletonImage = styled(Skeleton)<{ aspect: number }>((aspect) => ({ borderRadius: "8px", @@ -168,7 +165,7 @@ const ListButtonContainer = styled.div({ type LearningResourceExpandedV2Props = { resource?: LearningResource user?: User - imgConfig: EmbedlyConfig + imgConfig: ImageConfig onAddToLearningPathClick?: LearningResourceCardProps["onAddToLearningPathClick"] onAddToUserListClick?: LearningResourceCardProps["onAddToUserListClick"] closeDrawer?: () => void @@ -237,33 +234,32 @@ const TitleSection: React.FC<{ const ImageSection: React.FC<{ resource?: LearningResource - config: EmbedlyConfig + config: ImageConfig }> = ({ resource, config }) => { + const aspect = config.width / config.height if (resource?.resource_type === "video" && resource?.url) { return ( - - - + ) } else if (resource?.image) { return ( - {resource?.image.alt + + {resource?.image.alt + ) } else if (resource) { return ( - {resource.image?.alt + + {resource.image?.alt + ) } else { return ( @@ -323,7 +319,7 @@ const CallToActionSection = ({ onAddToLearningPathClick, onAddToUserListClick, }: { - imgConfig: EmbedlyConfig + imgConfig: ImageConfig resource?: LearningResource hide?: boolean user?: User @@ -350,7 +346,7 @@ const CallToActionSection = ({ (offeredBy?.code as PlatformEnum) === PlatformEnum.Xpro ? (offeredBy?.code as PlatformEnum) : (platform?.code as PlatformEnum) - const platformImage = PLATFORMS[platformCode]?.image + const platformImage = PLATFORM_LOGOS[platformCode]?.image const cta = getCallToActionText(resource) return ( diff --git a/frontends/ol-components/src/components/LearningResourceExpanded/VideoFrame.tsx b/frontends/ol-components/src/components/LearningResourceExpanded/VideoFrame.tsx new file mode 100644 index 0000000000..3f76c24609 --- /dev/null +++ b/frontends/ol-components/src/components/LearningResourceExpanded/VideoFrame.tsx @@ -0,0 +1,32 @@ +import React from "react" +import styled from "@emotion/styled" +import { EmbedlyCard } from "../EmbedlyCard/EmbedlyCard" + +const IFrame = styled.iframe` + border-radius: 8px; + border: none; + width: 100%; + aspect-ratio: 16 / 9; +` + +const VideoFrame: React.FC<{ + src: string + title: string + aspect: number +}> = ({ src, title, aspect }) => { + if (src?.startsWith("https://www.youtube.com/watch?v=")) { + const videoId = src?.split("v=")[1] + return ( +