From d7e2e87c69beaafc767cffc3c890f62b9c39b04f Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:46:07 +0200 Subject: [PATCH 1/3] Set first run language on drawer and card titles and description --- .../LearningResourceExpanded.test.tsx | 19 +++++++++++++++++++ .../ResourceDescription.tsx | 1 + .../LearningResourceExpanded/TitleSection.tsx | 2 +- .../src/components/Card/Card.tsx | 1 + .../src/components/Card/ListCard.tsx | 7 +++++-- .../src/components/Card/ListCardCondensed.tsx | 4 +++- .../LearningResourceCard.test.tsx | 16 ++++++++++++++++ .../LearningResourceCard.tsx | 4 +++- .../LearningResourceListCard.test.tsx | 16 ++++++++++++++++ .../LearningResourceListCard.tsx | 4 +++- .../LearningResourceListCardCondensed.tsx | 5 ++++- 11 files changed, 72 insertions(+), 7 deletions(-) diff --git a/frontends/main/src/page-components/LearningResourceExpanded/LearningResourceExpanded.test.tsx b/frontends/main/src/page-components/LearningResourceExpanded/LearningResourceExpanded.test.tsx index 3e3ddd961a..b7d1550a24 100644 --- a/frontends/main/src/page-components/LearningResourceExpanded/LearningResourceExpanded.test.tsx +++ b/frontends/main/src/page-components/LearningResourceExpanded/LearningResourceExpanded.test.tsx @@ -114,6 +114,25 @@ describe("Learning Resource Expanded", () => { screen.getByText(resource.title) }) + test("Sets lang attribute on title and description", () => { + const resource = factories.learningResources.resource({ + resource_type: ResourceTypeEnum.Course, + runs: [ + factories.learningResources.run({ + languages: ["en-us"], + }), + ], + }) + + setup({ resource }) + + const title = screen.getByText(resource.title) + expect(title).toHaveAttribute("lang", "en-us") + + const description = screen.getByText(resource.description!) + expect(description).toHaveAttribute("lang", "en-us") + }) + test.each([ResourceTypeEnum.Program, ResourceTypeEnum.LearningPath])( 'Renders CTA button for resource type "%s"', (resourceType) => { diff --git a/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx b/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx index f32b5db7a0..0b614436f9 100644 --- a/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx +++ b/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx @@ -83,6 +83,7 @@ const ResourceDescription = ({ resource }: { resource?: LearningResource }) => { * backend during ETL. This is safe to render. */ dangerouslySetInnerHTML={{ __html: resource.description || "" }} + lang={resource.runs?.[0]?.languages?.[0]} /> {(isClamped || clampedOnFirstRender.current) && ( {type} - {title} + {title} = styled(Linkable)` flex-grow: 1; @@ -247,8 +248,10 @@ const ListCard: Card = ({ {info} {title && ( - - <TruncateText lineClamp={2}>{title.children}</TruncateText> + <Title data-card-link={!!title.href} href={title.href}> + <TruncateText lineClamp={2} lang={title.lang}> + {title.children} + </TruncateText> )} diff --git a/frontends/ol-components/src/components/Card/ListCardCondensed.tsx b/frontends/ol-components/src/components/Card/ListCardCondensed.tsx index 1de609be2f..38ffe25a69 100644 --- a/frontends/ol-components/src/components/Card/ListCardCondensed.tsx +++ b/frontends/ol-components/src/components/Card/ListCardCondensed.tsx @@ -159,7 +159,9 @@ const ListCardCondensed: Card = ({ {info} - <TruncateText lineClamp={4}>{title.children}</TruncateText> + <TruncateText lineClamp={4} lang={title.lang}> + {title.children} + </TruncateText>
{footer}
diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.test.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.test.tsx index 3012f299ea..8e2db80b2d 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.test.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.test.tsx @@ -38,6 +38,22 @@ describe("Learning Resource Card", () => { }, ) + test("Sets lang attribute on title and description", () => { + const resource = factories.learningResources.resource({ + resource_type: ResourceTypeEnum.Course, + runs: [ + factories.learningResources.run({ + languages: ["en-us"], + }), + ], + }) + + setup({ resource }) + + const title = screen.getByText(resource.title) + expect(title).toHaveAttribute("lang", "en-us") + }) + test("Displays run start date", () => { const resource = factories.learningResources.resource({ resource_type: ResourceTypeEnum.Course, diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.tsx index 1c70b110fb..19d88ef1cf 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceCard.tsx @@ -241,7 +241,9 @@ const LearningResourceCard: React.FC = ({ - {resource.title} + + {resource.title} + {onAddToLearningPathClick && ( { }, ) + test.only("Sets lang attribute on title and description", () => { + const resource = factories.learningResources.resource({ + resource_type: ResourceTypeEnum.Course, + runs: [ + factories.learningResources.run({ + languages: ["pt-pt"], + }), + ], + }) + + setup({ resource }) + + const title = screen.getByText(resource.title) + expect(title).toHaveAttribute("lang", "pt-pt") + }) + test("Displays run start date", () => { const resource = factories.learningResources.resource({ resource_type: ResourceTypeEnum.Course, diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx index 2d145969ae..e5992ae377 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx @@ -319,7 +319,9 @@ const LearningResourceListCard: React.FC = ({ - {resource.title} + + {resource.title} + {onAddToLearningPathClick && ( - + {resource.title} From 80e74592f313325eabe808267401be1ebc627496 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Thu, 10 Jul 2025 19:27:27 +0200 Subject: [PATCH 2/3] Unfocus test --- .../LearningResourceCard/LearningResourceListCard.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.test.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.test.tsx index cbfff5ef73..4ff19f2170 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.test.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.test.tsx @@ -37,7 +37,7 @@ describe("Learning Resource List Card", () => { }, ) - test.only("Sets lang attribute on title and description", () => { + test("Sets lang attribute on title and description", () => { const resource = factories.learningResources.resource({ resource_type: ResourceTypeEnum.Course, runs: [ From 84137f9756bbef6c823269d5bc7c4def7dd7d2d3 Mon Sep 17 00:00:00 2001 From: Jon Kafton <939376+jonkafton@users.noreply.github.com> Date: Fri, 11 Jul 2025 19:54:03 +0200 Subject: [PATCH 3/3] Get language from last resource run. Provide utility function --- .../LearningResourceExpanded/ResourceDescription.tsx | 4 +++- .../LearningResourceCard/LearningResourceCard.tsx | 3 ++- .../LearningResourceCard/LearningResourceListCard.tsx | 3 ++- .../LearningResourceListCardCondensed.tsx | 6 ++---- .../src/learning-resources/learning-resources.ts | 5 +++++ 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx b/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx index 0b614436f9..56b69564dc 100644 --- a/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx +++ b/frontends/main/src/page-components/LearningResourceExpanded/ResourceDescription.tsx @@ -2,6 +2,8 @@ import React, { useCallback, useRef, useState } from "react" import styled from "@emotion/styled" import { Skeleton, theme, Link } from "ol-components" import type { LearningResource } from "api" +import { getResourceLanguage } from "ol-utilities" + const DescriptionContainer = styled.div({ display: "flex", flexDirection: "column", @@ -83,7 +85,7 @@ const ResourceDescription = ({ resource }: { resource?: LearningResource }) => { * backend during ETL. This is safe to render. */ dangerouslySetInnerHTML={{ __html: resource.description || "" }} - lang={resource.runs?.[0]?.languages?.[0]} + lang={getResourceLanguage(resource)} /> {(isClamped || clampedOnFirstRender.current) && ( = ({ - + {resource.title} diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx index e5992ae377..c1e526a129 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCard.tsx @@ -16,6 +16,7 @@ import { getLearningResourcePrices, getResourceDate, showStartAnytime, + getResourceLanguage, } from "ol-utilities" import { ListCard } from "../Card/ListCard" import type { ActionButtonProps } from "@mitodl/smoot-design" @@ -319,7 +320,7 @@ const LearningResourceListCard: React.FC = ({ - + {resource.title} diff --git a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCardCondensed.tsx b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCardCondensed.tsx index 18edbc26a2..76101733ff 100644 --- a/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCardCondensed.tsx +++ b/frontends/ol-components/src/components/LearningResourceCard/LearningResourceListCardCondensed.tsx @@ -11,6 +11,7 @@ import { LearningResource } from "api" import { getReadableResourceType, getLearningResourcePrices, + getResourceLanguage, } from "ol-utilities" import { ListCardCondensed } from "../Card/ListCardCondensed" import { @@ -128,10 +129,7 @@ const LearningResourceListCardCondensed: React.FC< - + {resource.title} diff --git a/frontends/ol-utilities/src/learning-resources/learning-resources.ts b/frontends/ol-utilities/src/learning-resources/learning-resources.ts index 91c4d4b30f..59bebda13a 100644 --- a/frontends/ol-utilities/src/learning-resources/learning-resources.ts +++ b/frontends/ol-utilities/src/learning-resources/learning-resources.ts @@ -161,6 +161,10 @@ const allRunsAreIdentical = (resource: LearningResource) => { ) } +const getResourceLanguage = (resource: LearningResource) => { + return resource.runs?.[resource.runs.length - 1]?.languages?.[0] +} + export { DEFAULT_RESOURCE_IMG, embedlyCroppedImage, @@ -169,5 +173,6 @@ export { findBestRun, formatRunDate, allRunsAreIdentical, + getResourceLanguage, } export type { EmbedlyConfig }