Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
dfa27aa
new width and title section
gumaerc Oct 18, 2024
ca3db13
move close button into drawer content
gumaerc Oct 18, 2024
7717962
use flex instead of absolute positioning for close button
gumaerc Oct 18, 2024
943dde5
reorganize top level layout and remove lorem ipsum
gumaerc Oct 18, 2024
5b79d2a
info section styles
gumaerc Oct 18, 2024
eb35206
call to action styling
gumaerc Oct 18, 2024
1bd0052
simply flip flex direction at medium for now on drawer content
gumaerc Oct 18, 2024
3f2a54f
switch out certificate icon
gumaerc Oct 18, 2024
71eff63
use new separator style on instructors in info section
gumaerc Oct 18, 2024
1f66c67
remove extraneous container gap
gumaerc Oct 18, 2024
e01af78
mobile styling
gumaerc Oct 18, 2024
d589142
add back bookmark and learning path buttons
gumaerc Oct 18, 2024
9189b13
fix certificate display and hide info item icons on mobile
gumaerc Oct 18, 2024
a5f7074
align info item labels center
gumaerc Oct 18, 2024
c604fe3
fix tests, add new tests
gumaerc Oct 18, 2024
06138fc
move title container outside of content container so that when you sc…
gumaerc Oct 21, 2024
84a1e62
convert LearningResourceExpanded styled element to object notation be…
gumaerc Oct 21, 2024
50a77f2
remove remaining traces of run selection dropdown logic, display uniq…
gumaerc Oct 21, 2024
39fa04b
wrap embedly card in a container to restrict its width in cta section
gumaerc Oct 21, 2024
cba30a6
remove extraneous extra top padding
gumaerc Oct 21, 2024
ddd70c3
move start date above price
gumaerc Oct 22, 2024
3cd4e56
use padding for separator instead of spaces
gumaerc Oct 22, 2024
bccad6c
updated boxShadow value for cta section
gumaerc Oct 22, 2024
40621b6
fix rebase issue with closeDrawer parameter
gumaerc Oct 22, 2024
6f7ba4c
refactor getCallToActionText
gumaerc Oct 22, 2024
3db3645
prevent wrapping mid-item
gumaerc Oct 22, 2024
cd7dcfd
fix wrapping in Chrome
gumaerc Oct 22, 2024
8e77b97
re-add hideCloseButton argument on LearningResourceDrawer's RoutedDra…
gumaerc Oct 22, 2024
1a748a2
default CTA for non-OCW courses should be "Learn More"
gumaerc Oct 22, 2024
d31d4bb
adjust description line height to 1.2rem
gumaerc Oct 22, 2024
a1f400c
fix info items alignment
gumaerc Oct 22, 2024
d377eb9
further fix icon alignment
gumaerc Oct 22, 2024
a7b163d
remove incorrectly placed line height directive and set row-gap on in…
gumaerc Oct 22, 2024
d55b6e8
load the playlist URL onto the playlist learning resource in ETL
gumaerc Oct 25, 2024
264f3fd
set the data during the transform step instead, and also pull in the …
gumaerc Oct 25, 2024
c2f433f
fix alignment of list buttons when platform is not present
gumaerc Oct 25, 2024
27a6951
fix description pushing call to action off the drawer
gumaerc Oct 25, 2024
25ac64f
grow the left side
gumaerc Oct 25, 2024
e4683af
fix test
gumaerc Oct 25, 2024
16106ae
fix tests
gumaerc Oct 25, 2024
8fe406f
mobile style fixes
gumaerc Oct 25, 2024
731c99f
fix key prop issue
gumaerc Oct 25, 2024
7552686
fix drawer max width
gumaerc Oct 25, 2024
517e03f
fix info item word wrap
gumaerc Oct 25, 2024
c9e5db2
make tablet view a little better
gumaerc Oct 25, 2024
f11663a
refine info section value items text wrapping strategy
gumaerc Oct 28, 2024
1a347ce
add a zero width space to the end of the separator
gumaerc Oct 28, 2024
91a95ed
fix tests
gumaerc Oct 28, 2024
5818087
wrap price / certificate display on mobile
gumaerc Oct 28, 2024
ef36ac0
add another comment explaining the separator
gumaerc Oct 28, 2024
01b484c
also reduce font size of the certificate section on mobile so it does…
gumaerc Oct 28, 2024
9f57fcc
put the new drawer behind a posthog feature flag
gumaerc Oct 29, 2024
f198879
remove debug code
gumaerc Oct 30, 2024
c42b84a
fix tests
gumaerc Oct 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontends/main/src/common/feature_flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

export enum FeatureFlags {
EnableEcommerce = "enable-ecommerce",
DrawerV2Enabled = "lr_drawer_v2",
}
Original file line number Diff line number Diff line change
@@ -1,132 +1,14 @@
import React, { Suspense, useCallback, useEffect, useMemo } from "react"
import {
RoutedDrawer,
LearningResourceExpanded,
imgConfigs,
} from "ol-components"
import type {
LearningResourceCardProps,
RoutedDrawerProps,
} from "ol-components"
import { useLearningResourcesDetail } from "api/hooks/learningResources"
import { useSearchParams, ReadonlyURLSearchParams } from "next/navigation"

import React, { useCallback } from "react"
import { RESOURCE_DRAWER_QUERY_PARAM } from "@/common/urls"
import { useUserMe } from "api/hooks/user"
import NiceModal from "@ebay/nice-modal-react"
import {
AddToLearningPathDialog,
AddToUserListDialog,
} from "../Dialogs/AddToListDialog"
import { SignupPopover } from "../SignupPopover/SignupPopover"
import { usePostHog } from "posthog-js/react"

const RESOURCE_DRAWER_PARAMS = [RESOURCE_DRAWER_QUERY_PARAM] as const

const useCapturePageView = (resourceId: number) => {
const { data, isSuccess } = useLearningResourcesDetail(Number(resourceId))
const posthog = usePostHog()
const apiKey = process.env.NEXT_PUBLIC_POSTHOG_API_KEY

useEffect(() => {
if (!apiKey || apiKey.length < 1) return
if (!isSuccess) return
posthog.capture("lrd_view", {
resourceId: data?.id,
readableId: data?.readable_id,
platformCode: data?.platform?.code,
resourceType: data?.resource_type,
})
}, [
isSuccess,
posthog,
data?.id,
data?.readable_id,
data?.platform?.code,
data?.resource_type,
apiKey,
])
}

/**
* Convert HTML to plaintext, removing any HTML tags.
* This conversion method has some issues:
* 1. It is unsafe for untrusted HTML
* 2. It must be run in a browser, not on a server.
*/
// eslint-disable-next-line camelcase
// const unsafe_html2plaintext = (text: string) => {
// const div = document.createElement("div")
// div.innerHTML = text
// return div.textContent || div.innerText || ""
// }

const DrawerContent: React.FC<{
resourceId: number
}> = ({ resourceId }) => {
const resource = useLearningResourcesDetail(Number(resourceId))
const [signupEl, setSignupEl] = React.useState<HTMLElement | null>(null)
const { data: user } = useUserMe()
const handleAddToLearningPathClick: LearningResourceCardProps["onAddToLearningPathClick"] =
useMemo(() => {
if (user?.is_learning_path_editor) {
return (event, resourceId: number) => {
NiceModal.show(AddToLearningPathDialog, { resourceId })
}
}
return null
}, [user])
const handleAddToUserListClick: LearningResourceCardProps["onAddToUserListClick"] =
useMemo(() => {
return (event, resourceId: number) => {
if (!user?.is_authenticated) {
setSignupEl(event.currentTarget)
return
}
NiceModal.show(AddToUserListDialog, { resourceId })
}
}, [user])
useCapturePageView(Number(resourceId))

return (
<>
<LearningResourceExpanded
imgConfig={imgConfigs.large}
resource={resource.data}
user={user}
onAddToLearningPathClick={handleAddToLearningPathClick}
onAddToUserListClick={handleAddToUserListClick}
/>
<SignupPopover anchorEl={signupEl} onClose={() => setSignupEl(null)} />
</>
)
}

const PAPER_PROPS: RoutedDrawerProps["PaperProps"] = {
sx: {
maxWidth: (theme) => theme.breakpoints.values.sm,
minWidth: (theme) => ({
[theme.breakpoints.down("sm")]: {
minWidth: "100%",
},
}),
},
}
import { ReadonlyURLSearchParams, useSearchParams } from "next/navigation"
import { useFeatureFlagEnabled } from "posthog-js/react"
import LearningResourceDrawerV2 from "./LearningResourceDrawerV2"
import LearningResourceDrawerV1 from "./LearningResourceDrawerV1"
import { FeatureFlags } from "@/common/feature_flags"

const LearningResourceDrawer = () => {
return (
<Suspense>
<RoutedDrawer
anchor="right"
requiredParams={RESOURCE_DRAWER_PARAMS}
PaperProps={PAPER_PROPS}
>
{({ params }) => {
return <DrawerContent resourceId={Number(params.resource)} />
}}
</RoutedDrawer>
</Suspense>
)
const drawerV2 = useFeatureFlagEnabled(FeatureFlags.DrawerV2Enabled)
return drawerV2 ? <LearningResourceDrawerV2 /> : <LearningResourceDrawerV1 />
}

const getOpenDrawerSearchParams = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {
waitFor,
within,
} from "@/test-utils"
import LearningResourceDrawer from "./LearningResourceDrawer"
import LearningResourceDrawerV1 from "./LearningResourceDrawerV1"
import { urls, factories, setMockResponse } from "api/test-utils"
import { LearningResourceExpanded } from "ol-components"
import { LearningResourceExpandedV1 } from "ol-components"
import { RESOURCE_DRAWER_QUERY_PARAM } from "@/common/urls"
import { ResourceTypeEnum } from "api"
import invariant from "tiny-invariant"
Expand All @@ -17,7 +17,7 @@ jest.mock("ol-components", () => {
const actual = jest.requireActual("ol-components")
return {
...actual,
LearningResourceExpanded: jest.fn(actual.LearningResourceExpanded),
LearningResourceExpandedV1: jest.fn(actual.LearningResourceExpandedV1),
}
})

Expand All @@ -33,7 +33,7 @@ jest.mock("posthog-js/react", () => ({
},
}))

describe("LearningResourceDrawer", () => {
describe("LearningResourceDrawerV1", () => {
it.each([
{ descriptor: "is enabled", enablePostHog: true },
{ descriptor: "is not enabled", enablePostHog: false },
Expand All @@ -50,12 +50,12 @@ describe("LearningResourceDrawer", () => {
resource,
)

renderWithProviders(<LearningResourceDrawer />, {
renderWithProviders(<LearningResourceDrawerV1 />, {
url: `?dog=woof&${RESOURCE_DRAWER_QUERY_PARAM}=${resource.id}`,
})
expect(LearningResourceExpanded).toHaveBeenCalled()
expect(LearningResourceExpandedV1).toHaveBeenCalled()
await waitFor(() => {
expectProps(LearningResourceExpanded, { resource })
expectProps(LearningResourceExpandedV1, { resource })
})
await screen.findByRole("heading", { name: resource.title })

Expand All @@ -68,10 +68,10 @@ describe("LearningResourceDrawer", () => {
)

it("Does not render drawer content when resource=id is NOT in the URL", async () => {
renderWithProviders(<LearningResourceDrawer />, {
renderWithProviders(<LearningResourceDrawerV1 />, {
url: "?dog=woof",
})
expect(LearningResourceExpanded).not.toHaveBeenCalled()
expect(LearningResourceExpandedV1).not.toHaveBeenCalled()
})

test.each([
Expand Down Expand Up @@ -118,14 +118,14 @@ describe("LearningResourceDrawer", () => {
setMockResponse.get(urls.userMe.get(), null, { code: 403 })
}

renderWithProviders(<LearningResourceDrawer />, {
renderWithProviders(<LearningResourceDrawerV1 />, {
url: `?resource=${resource.id}`,
})

expect(LearningResourceExpanded).toHaveBeenCalled()
expect(LearningResourceExpandedV1).toHaveBeenCalled()

await waitFor(() => {
expectProps(LearningResourceExpanded, { resource })
expectProps(LearningResourceExpandedV1, { resource })
})

const section = screen
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React, { Suspense, useEffect, useMemo } from "react"
import {
RoutedDrawer,
LearningResourceExpandedV1,
imgConfigs,
} from "ol-components"
import type {
LearningResourceCardProps,
RoutedDrawerProps,
} from "ol-components"
import { useLearningResourcesDetail } from "api/hooks/learningResources"

import { RESOURCE_DRAWER_QUERY_PARAM } from "@/common/urls"
import { useUserMe } from "api/hooks/user"
import NiceModal from "@ebay/nice-modal-react"
import {
AddToLearningPathDialog,
AddToUserListDialog,
} from "../Dialogs/AddToListDialog"
import { SignupPopover } from "../SignupPopover/SignupPopover"
import { usePostHog } from "posthog-js/react"

const RESOURCE_DRAWER_PARAMS = [RESOURCE_DRAWER_QUERY_PARAM] as const

const useCapturePageView = (resourceId: number) => {
const { data, isSuccess } = useLearningResourcesDetail(Number(resourceId))
const posthog = usePostHog()
const apiKey = process.env.NEXT_PUBLIC_POSTHOG_API_KEY

useEffect(() => {
if (!apiKey || apiKey.length < 1) return
if (!isSuccess) return
posthog.capture("lrd_view", {
resourceId: data?.id,
readableId: data?.readable_id,
platformCode: data?.platform?.code,
resourceType: data?.resource_type,
})
}, [
isSuccess,
posthog,
data?.id,
data?.readable_id,
data?.platform?.code,
data?.resource_type,
apiKey,
])
}

/**
* Convert HTML to plaintext, removing any HTML tags.
* This conversion method has some issues:
* 1. It is unsafe for untrusted HTML
* 2. It must be run in a browser, not on a server.
*/
// eslint-disable-next-line camelcase
// const unsafe_html2plaintext = (text: string) => {
// const div = document.createElement("div")
// div.innerHTML = text
// return div.textContent || div.innerText || ""
// }

const DrawerContent: React.FC<{
resourceId: number
}> = ({ resourceId }) => {
const resource = useLearningResourcesDetail(Number(resourceId))
const [signupEl, setSignupEl] = React.useState<HTMLElement | null>(null)
const { data: user } = useUserMe()
const handleAddToLearningPathClick: LearningResourceCardProps["onAddToLearningPathClick"] =
useMemo(() => {
if (user?.is_learning_path_editor) {
return (event, resourceId: number) => {
NiceModal.show(AddToLearningPathDialog, { resourceId })
}
}
return null
}, [user])
const handleAddToUserListClick: LearningResourceCardProps["onAddToUserListClick"] =
useMemo(() => {
return (event, resourceId: number) => {
if (!user?.is_authenticated) {
setSignupEl(event.currentTarget)
return
}
NiceModal.show(AddToUserListDialog, { resourceId })
}
}, [user])
useCapturePageView(Number(resourceId))

return (
<>
<LearningResourceExpandedV1
imgConfig={imgConfigs.large}
resource={resource.data}
user={user}
onAddToLearningPathClick={handleAddToLearningPathClick}
onAddToUserListClick={handleAddToUserListClick}
/>
<SignupPopover anchorEl={signupEl} onClose={() => setSignupEl(null)} />
</>
)
}

const PAPER_PROPS: RoutedDrawerProps["PaperProps"] = {
sx: {
maxWidth: (theme) => theme.breakpoints.values.sm,
minWidth: (theme) => ({
[theme.breakpoints.down("sm")]: {
minWidth: "100%",
},
}),
},
}

const LearningResourceDrawerV1 = () => {
return (
<Suspense>
<RoutedDrawer
anchor="right"
requiredParams={RESOURCE_DRAWER_PARAMS}
PaperProps={PAPER_PROPS}
>
{({ params }) => {
return <DrawerContent resourceId={Number(params.resource)} />
}}
</RoutedDrawer>
</Suspense>
)
}

export default LearningResourceDrawerV1
Loading
Loading