Skip to content

Server render search results (search and channel pages) #1836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 48 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4721190
Warn on API calls during initial render not prefetched
jonkafton Nov 6, 2024
96f6c54
Merge branch 'main' into jk/5919-prefetch-mechanism
jonkafton Nov 6, 2024
fc4dcb7
Full prefetch for homepage (commented)
jonkafton Nov 6, 2024
52e6cf7
Prefetch utility
jonkafton Nov 7, 2024
bae8e93
Check for queries prefetched that are not needed during render and warn
jonkafton Nov 7, 2024
73209e0
No need to stringify
jonkafton Nov 7, 2024
9f25822
Replace useQuery overrides with decoupled cache check (wip)
jonkafton Nov 7, 2024
d34bd26
Observer count for unnecessary prefetch warnings
jonkafton Nov 8, 2024
98843c2
Remove useQuery override
jonkafton Nov 8, 2024
23e328e
Add warnings hook
jonkafton Nov 8, 2024
db5916b
Test prefetch warnings
jonkafton Nov 8, 2024
cd9ad5a
Remove inadvertent/unnecessary diff
jonkafton Nov 8, 2024
c41d537
Remove comments
jonkafton Nov 8, 2024
e4c19b7
Prefetch homepage. Invalidate learning resource cache items
jonkafton Nov 12, 2024
573e416
Remove comment
jonkafton Nov 12, 2024
e17f352
Update comment
jonkafton Nov 12, 2024
2cf4ab3
Temp remove featured resource list shuffle
jonkafton Nov 12, 2024
e015ac3
Merge branch 'jk/5919-prefetch-mechanism' into jk/5920-prefetch-homepage
jonkafton Nov 12, 2024
c10f677
Remove unused
jonkafton Nov 12, 2024
af74cb4
Prefetch calls
jonkafton Nov 12, 2024
d3b7fe3
Prefetch topics page
jonkafton Nov 12, 2024
c8cde78
Rename key factory re-exports
jonkafton Nov 13, 2024
12c6955
Merge branch 'main' into jk/5920-prefetch-homepage
jonkafton Nov 13, 2024
0c46451
Units page prefetch
jonkafton Nov 14, 2024
2bdea92
Single request for all unit channel details
jonkafton Nov 14, 2024
84eb78a
Update unit listing page tests
jonkafton Nov 15, 2024
14d49ae
Page arg types
jonkafton Nov 15, 2024
11d76cf
Optional route params
jonkafton Nov 15, 2024
9fe9cd6
Server rendered search page results
jonkafton Nov 15, 2024
45ad720
Unit channel page and search prefetch
jonkafton Nov 15, 2024
abf1fae
Merge branch 'main' into jk/5920-prefetch-homepage
jonkafton Nov 15, 2024
e59621f
Featured list and testimonials only for unit channels
jonkafton Nov 15, 2024
1ac7666
Remove comment
jonkafton Nov 18, 2024
b713b53
Remove unused
jonkafton Nov 18, 2024
0e635f8
Merge branch 'jk/5920-prefetch-homepage' into jk/6035-prefetch-search
jonkafton Nov 18, 2024
4f80868
Map address search params
jonkafton Nov 18, 2024
7e4cee1
Search params test
jonkafton Nov 19, 2024
131e890
URL search param validation anf transforms to align with course-searc…
jonkafton Nov 19, 2024
e70977c
Update to use validators from course-search-utils
jonkafton Nov 19, 2024
7f383a3
Merge branch 'main' into jk/6035-prefetch-search
jonkafton Nov 19, 2024
0fab322
Merge branch 'main' into jk/6035-prefetch-search
jonkafton Nov 22, 2024
1dd9388
Install published @mitodl/course-search-utils
jonkafton Nov 22, 2024
74a328a
Remove comment
jonkafton Nov 22, 2024
c91fd3e
Merge branch 'main' into jk/6035-prefetch-search
jonkafton Nov 25, 2024
7546790
Fix export missed from merge
jonkafton Nov 25, 2024
50a6505
Merge branch 'main' into jk/6035-prefetch-search
jonkafton Nov 25, 2024
8d52ff1
Remove cache invalidation
jonkafton Nov 26, 2024
39b4af0
Merge branch 'main' into jk/6035-prefetch-search
jonkafton Dec 6, 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
4 changes: 3 additions & 1 deletion frontends/api/src/ssr/prefetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export const prefetch = async (
queryClient = queryClient || new QueryClient()

await Promise.all(
queries.map((query) => queryClient.prefetchQuery(query as Query)),
queries
.filter(Boolean)
.map((query) => queryClient.prefetchQuery(query as Query)),
)

return { dehydratedState: dehydrate(queryClient), queryClient }
Expand Down
2 changes: 1 addition & 1 deletion frontends/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@ebay/nice-modal-react": "^1.2.13",
"@emotion/cache": "^11.13.1",
"@mitodl/course-search-utils": "^3.3.1",
"@mitodl/course-search-utils": "3.3.2",
"@next/bundle-analyzer": "^14.2.15",
"@remixicon/react": "^4.2.0",
"@sentry/nextjs": "^8.36.0",
Expand Down
25 changes: 6 additions & 19 deletions frontends/main/src/app-pages/ChannelPage/ChannelPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@ import { useParams } from "next/navigation"
import { ChannelPageTemplate } from "./ChannelPageTemplate"
import { useChannelDetail } from "api/hooks/channels"
import ChannelSearch from "./ChannelSearch"
import type {
Facets,
FacetKey,
BooleanFacets,
} from "@mitodl/course-search-utils"
import { ChannelTypeEnum } from "api/v0"
import { Typography } from "ol-components"
import { getConstantSearchParams } from "./searchRequests"

type RouteParams = {
channelType: ChannelTypeEnum
Expand All @@ -22,20 +18,11 @@ type RouteParams = {
const ChannelPage: React.FC = () => {
const { channelType, name } = useParams<RouteParams>()
const channelQuery = useChannelDetail(String(channelType), String(name))
const searchParams: Facets & BooleanFacets = {}
const publicDescription = channelQuery.data?.public_description

if (channelQuery.data?.search_filter) {
const urlParams = new URLSearchParams(channelQuery.data.search_filter)
for (const [key, value] of urlParams.entries()) {
const paramEntry = searchParams[key as FacetKey]
if (paramEntry !== undefined) {
paramEntry.push(value)
} else {
searchParams[key as FacetKey] = [value]
}
}
}
const channelSearchFilter = channelQuery.data?.search_filter

const searchParams = getConstantSearchParams(channelSearchFilter)

return (
name &&
Expand All @@ -46,9 +33,9 @@ const ChannelPage: React.FC = () => {
{publicDescription && (
<Typography variant="body1">{publicDescription}</Typography>
)}
{channelQuery.data?.search_filter && (
{channelSearchFilter && (
<ChannelSearch
channelTitle={channelQuery.data.title}
channelTitle={channelQuery.data!.title}
constantSearchParams={searchParams}
channelType={channelType}
/>
Expand Down
83 changes: 5 additions & 78 deletions frontends/main/src/app-pages/ChannelPage/ChannelSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import React, { useCallback, useMemo } from "react"
import { LearningResourceOfferor } from "api"
import { ChannelTypeEnum } from "api/v0"
import { useOfferorsList } from "api/hooks/learningResources"

import {
useResourceSearchParams,
UseResourceSearchParamsProps,
} from "@mitodl/course-search-utils"
import type {
Facets,
BooleanFacets,
FacetManifest,
} from "@mitodl/course-search-utils"
import { useResourceSearchParams } from "@mitodl/course-search-utils"
import type { Facets, BooleanFacets } from "@mitodl/course-search-utils"
import { useSearchParams } from "@mitodl/course-search-utils/next"
import SearchDisplay from "@/page-components/SearchDisplay/SearchDisplay"
import { Container, styled, VisuallyHidden } from "ol-components"
import { SearchField } from "@/page-components/SearchField/SearchField"

import { getFacetManifest } from "@/app-pages/SearchPage/SearchPage"
import { getFacets } from "./searchRequests"

import _ from "lodash"

Expand All @@ -35,34 +25,6 @@ const StyledSearchField = styled(SearchField)({
width: "624px",
})

const FACETS_BY_CHANNEL_TYPE: Record<ChannelTypeEnum, string[]> = {
[ChannelTypeEnum.Topic]: [
"free",
"resource_type",
"certification_type",
"delivery",
"offered_by",
"department",
],
[ChannelTypeEnum.Department]: [
"free",
"resource_type",
"certification_type",
"topic",
"delivery",
"offered_by",
],
[ChannelTypeEnum.Unit]: [
"free",
"resource_type",
"topic",
"certification_type",
"delivery",
"department",
],
[ChannelTypeEnum.Pathway]: [],
}

const SHOW_PROFESSIONAL_TOGGLE_BY_CHANNEL_TYPE: Record<
ChannelTypeEnum,
boolean
Expand All @@ -73,24 +35,6 @@ const SHOW_PROFESSIONAL_TOGGLE_BY_CHANNEL_TYPE: Record<
[ChannelTypeEnum.Pathway]: false,
}

const getFacetManifestForChannelType = (
channelType: ChannelTypeEnum,
offerors: Record<string, LearningResourceOfferor>,
constantSearchParams: Facets,
resourceCategory: string | null,
): FacetManifest => {
const facets = FACETS_BY_CHANNEL_TYPE[channelType] || []
return getFacetManifest(offerors, resourceCategory)
.filter(
(facetSetting) =>
!Object.keys(constantSearchParams).includes(facetSetting.name) &&
facets.includes(facetSetting.name),
)
.sort(
(a, b) => facets.indexOf(a.name) - facets.indexOf(b.name),
) as FacetManifest
}

interface ChannelSearchProps {
constantSearchParams: Facets & BooleanFacets
channelType: ChannelTypeEnum
Expand All @@ -110,14 +54,9 @@ const ChannelSearch: React.FC<ChannelSearchProps> = ({
const [searchParams, setSearchParams] = useSearchParams()
const resourceCategory = searchParams.get("resource_category")

const facetManifest = useMemo(
const { facetNames, facetManifest } = useMemo(
() =>
getFacetManifestForChannelType(
channelType,
offerors,
constantSearchParams,
resourceCategory,
),
getFacets(channelType, offerors, constantSearchParams, resourceCategory),
[offerors, channelType, constantSearchParams, resourceCategory],
)

Expand All @@ -140,18 +79,6 @@ const ChannelSearch: React.FC<ChannelSearchProps> = ({
setPage(1)
}, [setPage])

const facetNames = Array.from(
new Set(
facetManifest.flatMap((facet) => {
if (facet.type === "group") {
return facet.facets.map((subfacet) => subfacet.name)
} else {
return [facet.name]
}
}),
),
) as UseResourceSearchParamsProps["facets"]

const {
hasFacets,
params,
Expand Down
102 changes: 102 additions & 0 deletions frontends/main/src/app-pages/ChannelPage/searchRequests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import type {
Facets,
FacetKey,
BooleanFacets,
FacetManifest,
UseResourceSearchParamsProps,
} from "@mitodl/course-search-utils"
import { LearningResourceOfferor } from "api"
import { ChannelTypeEnum } from "api/v0"
import { getFacetManifest } from "@/page-components/SearchDisplay/getFacetManifest"

export const getConstantSearchParams = (searchFilter?: string) => {
const searchParams: Facets & BooleanFacets = {}

if (searchFilter) {
const urlParams = new URLSearchParams(searchFilter)
for (const [key, value] of urlParams.entries()) {
const paramEntry = searchParams[key as FacetKey]
if (paramEntry !== undefined) {
paramEntry.push(value)
} else {
searchParams[key as FacetKey] = [value]
}
}
}

return searchParams
}

const FACETS_BY_CHANNEL_TYPE: Record<ChannelTypeEnum, string[]> = {
[ChannelTypeEnum.Topic]: [
"free",
"resource_type",
"certification_type",
"delivery",
"offered_by",
"department",
],
[ChannelTypeEnum.Department]: [
"free",
"resource_type",
"certification_type",
"topic",
"delivery",
"offered_by",
],
[ChannelTypeEnum.Unit]: [
"free",
"resource_type",
"topic",
"certification_type",
"delivery",
"department",
],
[ChannelTypeEnum.Pathway]: [],
}

const getFacetManifestForChannelType = (
channelType: ChannelTypeEnum,
offerors: Record<string, LearningResourceOfferor>,
constantSearchParams: Facets,
resourceCategory: string | null,
): FacetManifest => {
const facets = FACETS_BY_CHANNEL_TYPE[channelType] || []
return getFacetManifest(offerors, resourceCategory)
.filter(
(facetSetting) =>
!Object.keys(constantSearchParams).includes(facetSetting.name) &&
facets.includes(facetSetting.name),
)
.sort(
(a, b) => facets.indexOf(a.name) - facets.indexOf(b.name),
) as FacetManifest
}

export const getFacets = (
channelType: ChannelTypeEnum,
offerors: Record<string, LearningResourceOfferor>,
constantSearchParams: Facets,
resourceCategory: string | null,
) => {
const facetManifest = getFacetManifestForChannelType(
channelType,
offerors,
constantSearchParams,
resourceCategory,
)

const facetNames = Array.from(
new Set(
facetManifest.flatMap((facet) => {
if (facet.type === "group") {
return facet.facets.map((subFacet) => subFacet.name)
} else {
return [facet.name]
}
}),
),
) as UseResourceSearchParamsProps["facets"]

return { facetNames, facetManifest }
}
Loading
Loading