Add new landing hero and assets (#57450)
This commit is contained in:
BIN
assets/images/banner-images/hero-1.png
Normal file
BIN
assets/images/banner-images/hero-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 188 KiB |
BIN
assets/images/banner-images/hero-2.png
Normal file
BIN
assets/images/banner-images/hero-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 212 KiB |
BIN
assets/images/banner-images/hero-3.png
Normal file
BIN
assets/images/banner-images/hero-3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
BIN
assets/images/banner-images/hero-4.png
Normal file
BIN
assets/images/banner-images/hero-4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 196 KiB |
BIN
assets/images/banner-images/hero-5.png
Normal file
BIN
assets/images/banner-images/hero-5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 207 KiB |
BIN
assets/images/banner-images/hero-6.png
Normal file
BIN
assets/images/banner-images/hero-6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 198 KiB |
@@ -202,6 +202,10 @@ export const schema = {
|
||||
product_video_transcript: {
|
||||
type: 'string',
|
||||
},
|
||||
// Hero image for landing pages
|
||||
heroImage: {
|
||||
type: 'string',
|
||||
},
|
||||
interactive: {
|
||||
type: 'boolean',
|
||||
},
|
||||
|
||||
@@ -39,6 +39,7 @@ export type ProductLandingContextT = {
|
||||
introLinks: Record<string, string> | null
|
||||
productVideo: string
|
||||
productVideoTranscript: string
|
||||
heroImage?: string
|
||||
featuredLinks: Record<string, Array<FeaturedLink>>
|
||||
productUserExamples: Array<{ username: string; description: string }>
|
||||
productCommunityExamples: Array<{ repo: string; description: string }>
|
||||
@@ -113,6 +114,7 @@ export const getProductLandingContextFromRequest = async (
|
||||
...pick(page, ['introPlainText', 'beta_product', 'intro']),
|
||||
productVideo,
|
||||
productVideoTranscript: page.product_video_transcript || null,
|
||||
heroImage: page.heroImage || null,
|
||||
hasGuidesPage,
|
||||
product: {
|
||||
href: productTree.href,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { DefaultLayout } from '@/frame/components/DefaultLayout'
|
||||
import { useBespokeContext } from '@/landings/context/BespokeContext'
|
||||
import { useLandingContext } from '@/landings/context/LandingContext'
|
||||
import { LandingHero } from '@/landings/components/shared/LandingHero'
|
||||
import { ArticleGrid } from '@/landings/components/shared/LandingArticleGridWithFilter'
|
||||
|
||||
import type { ArticleCardItems } from '@/landings/types'
|
||||
|
||||
export const BespokeLanding = () => {
|
||||
const { title, intro, tocItems } = useBespokeContext()
|
||||
const { title, intro, heroImage, introLinks, tocItems } = useLandingContext()
|
||||
|
||||
const flatArticles: ArticleCardItems = useMemo(
|
||||
() => tocItems.flatMap((item) => item.childTocItems || []),
|
||||
@@ -18,7 +18,7 @@ export const BespokeLanding = () => {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<div data-search="article-body">
|
||||
<LandingHero title={title} intro={intro} />
|
||||
<LandingHero title={title} intro={intro} heroImage={heroImage} introLinks={introLinks} />
|
||||
|
||||
<div data-search="hide">
|
||||
<ArticleGrid flatArticles={flatArticles} />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { DefaultLayout } from '@/frame/components/DefaultLayout'
|
||||
import { useDiscoveryContext } from '@/landings/context/DiscoveryContext'
|
||||
import { useLandingContext } from '@/landings/context/LandingContext'
|
||||
import { LandingHero } from '@/landings/components/shared/LandingHero'
|
||||
import { ArticleGrid } from '@/landings/components/shared/LandingArticleGridWithFilter'
|
||||
import { LandingCarousel } from '@/landings/components/shared/LandingCarousel'
|
||||
@@ -9,7 +9,7 @@ import { LandingCarousel } from '@/landings/components/shared/LandingCarousel'
|
||||
import type { ArticleCardItems } from '@/landings/types'
|
||||
|
||||
export const DiscoveryLanding = () => {
|
||||
const { title, intro, tocItems, recommended } = useDiscoveryContext()
|
||||
const { title, intro, heroImage, introLinks, tocItems, recommended } = useLandingContext()
|
||||
|
||||
const flatArticles: ArticleCardItems = useMemo(
|
||||
() => tocItems.flatMap((item) => item.childTocItems || []),
|
||||
@@ -19,7 +19,7 @@ export const DiscoveryLanding = () => {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<div>
|
||||
<LandingHero title={title} intro={intro} />
|
||||
<LandingHero title={title} intro={intro} heroImage={heroImage} introLinks={introLinks} />
|
||||
<LandingCarousel flatArticles={flatArticles} recommended={recommended} />
|
||||
<ArticleGrid flatArticles={flatArticles} />
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { DefaultLayout } from '@/frame/components/DefaultLayout'
|
||||
import { useJourneyContext } from '@/landings/context/JourneyContext'
|
||||
import { useLandingContext } from '@/landings/context/LandingContext'
|
||||
import { LandingHero } from '@/landings/components/shared/LandingHero'
|
||||
|
||||
export const JourneyLanding = () => {
|
||||
const { title, intro } = useJourneyContext()
|
||||
const { title, intro, heroImage, introLinks } = useLandingContext()
|
||||
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<div>
|
||||
<LandingHero title={title} intro={intro} />
|
||||
<LandingHero title={title} intro={intro} heroImage={heroImage} introLinks={introLinks} />
|
||||
|
||||
<div>TODO</div>
|
||||
</div>
|
||||
|
||||
191
src/landings/components/shared/LandingHero.module.scss
Normal file
191
src/landings/components/shared/LandingHero.module.scss
Normal file
@@ -0,0 +1,191 @@
|
||||
.landingHero {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4rem 0;
|
||||
background-color: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa));
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
overflow: hidden;
|
||||
height: 28rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
position: relative;
|
||||
width: 50rem;
|
||||
max-width: 50rem;
|
||||
padding: 0 7rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.heroText {
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.heroHeading {
|
||||
font-size: 4rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
margin: 0 0 1rem 0;
|
||||
color: var(--fgColor-default, var(--color-fg-default, #1f2328));
|
||||
max-width: 48rem;
|
||||
}
|
||||
|
||||
.heroDescription {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
|
||||
margin: 0 0 2rem 0;
|
||||
max-width: 36rem;
|
||||
}
|
||||
|
||||
.heroActions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.heroAction {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 6px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
min-height: 2.75rem;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.heroPrimaryAction {
|
||||
background-color: var(
|
||||
--bgColor-success-emphasis,
|
||||
var(--color-btn-primary-bg, #1f883d)
|
||||
);
|
||||
color: var(--fgColor-onEmphasis, var(--color-btn-primary-text, #ffffff));
|
||||
border-color: var(
|
||||
--borderColor-success-emphasis,
|
||||
var(--color-btn-primary-border, #1f883d)
|
||||
);
|
||||
|
||||
&:hover {
|
||||
background-color: var(
|
||||
--bgColor-success-emphasis,
|
||||
var(--color-btn-primary-hover-bg, #1a7f37)
|
||||
);
|
||||
border-color: var(
|
||||
--borderColor-success-emphasis,
|
||||
var(--color-btn-primary-hover-border, #1a7f37)
|
||||
);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid
|
||||
var(
|
||||
--borderColor-success-emphasis,
|
||||
var(--color-btn-primary-focus, #1f883d)
|
||||
);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.heroSecondaryAction {
|
||||
background-color: transparent;
|
||||
color: var(--fgColor-default, var(--color-fg-default, #1f2328));
|
||||
border-color: var(
|
||||
--borderColor-default,
|
||||
var(--color-border-default, #d1d9e0)
|
||||
);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--bgColor-muted, var(--color-canvas-subtle, #f3f4f6));
|
||||
border-color: var(
|
||||
--borderColor-default,
|
||||
var(--color-border-default, #d1d9e0)
|
||||
);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid
|
||||
var(--borderColor-accent-emphasis, var(--color-accent-emphasis, #0969da));
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 865px) {
|
||||
.landingHero {
|
||||
height: 24rem;
|
||||
background-image: none !important;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
background-color: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa));
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
width: 100%;
|
||||
order: 2;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.heroHeading {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.heroDescription {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.heroActions {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.heroAction {
|
||||
width: auto;
|
||||
min-width: 12rem;
|
||||
}
|
||||
|
||||
.heroText {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.landingHero {
|
||||
height: 32rem;
|
||||
background-image: none !important;
|
||||
background-color: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa));
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
padding: 2rem 0 1rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
width: 100%;
|
||||
order: 2;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.heroText {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.heroActions {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,61 @@
|
||||
import { Lead } from '@/frame/components/ui/Lead/Lead'
|
||||
import styles from './LandingHero.module.scss'
|
||||
import { useTranslation } from '@/languages/components/useTranslation'
|
||||
|
||||
type LandingHeroProps = {
|
||||
title: string
|
||||
intro?: string
|
||||
heroImage?: string
|
||||
introLinks?: Record<string, string> | null
|
||||
}
|
||||
|
||||
export const LandingHero = ({ title, intro }: LandingHeroProps) => {
|
||||
export const LandingHero = ({ title, intro, heroImage, introLinks }: LandingHeroProps) => {
|
||||
const { t } = useTranslation(['product_landing'])
|
||||
|
||||
const linkEntries = introLinks ? Object.entries(introLinks) : []
|
||||
const primaryAction = linkEntries[0]
|
||||
const secondaryAction = linkEntries[1]
|
||||
|
||||
return (
|
||||
<header>
|
||||
<div>
|
||||
<h1>TODO: Landing hero placeholder</h1>
|
||||
<h2>{title}</h2>
|
||||
{intro && <Lead>{intro}</Lead>}
|
||||
<div
|
||||
className={styles.landingHero}
|
||||
style={
|
||||
heroImage
|
||||
? {
|
||||
backgroundImage: `url("${heroImage}")`,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<div className={styles.heroContent}>
|
||||
<div className={styles.heroText}>
|
||||
<h1 className={styles.heroHeading}>{title}</h1>
|
||||
{intro && (
|
||||
<div className={styles.heroDescription}>
|
||||
<div dangerouslySetInnerHTML={{ __html: intro }} />
|
||||
</div>
|
||||
)}
|
||||
{(primaryAction || secondaryAction) && (
|
||||
<div className={styles.heroActions}>
|
||||
{primaryAction && (
|
||||
<a
|
||||
href={primaryAction[1]}
|
||||
className={`${styles.heroAction} ${styles.heroPrimaryAction}`}
|
||||
>
|
||||
{t(primaryAction[0])}
|
||||
</a>
|
||||
)}
|
||||
{secondaryAction && (
|
||||
<a
|
||||
href={secondaryAction[1]}
|
||||
className={`${styles.heroAction} ${styles.heroSecondaryAction}`}
|
||||
>
|
||||
{t(secondaryAction[0])}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { createContext, useContext } from 'react'
|
||||
import { FeaturedLink, getFeaturedLinksFromReq } from '@/landings/components/ProductLandingContext'
|
||||
import { mapRawTocItemToTocItem } from '@/landings/types'
|
||||
import type { TocItem } from '@/landings/types'
|
||||
import type { LearningTrack } from '@/types'
|
||||
|
||||
export type BespokeContextT = {
|
||||
title: string
|
||||
intro: string
|
||||
productCallout: string
|
||||
permissions: string
|
||||
tocItems: Array<TocItem>
|
||||
variant?: 'compact' | 'expanded'
|
||||
featuredLinks: Record<string, Array<FeaturedLink>>
|
||||
renderedPage: string
|
||||
currentLearningTrack?: LearningTrack
|
||||
currentLayout: string
|
||||
}
|
||||
|
||||
export const BespokeContext = createContext<BespokeContextT | null>(null)
|
||||
|
||||
export const useBespokeContext = (): BespokeContextT => {
|
||||
const context = useContext(BespokeContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error('"useBespokeContext" may only be used inside "BespokeContext.Provider"')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export const getBespokeContextFromRequest = async (req: any): Promise<BespokeContextT> => {
|
||||
const page = req.context.page
|
||||
|
||||
return {
|
||||
title: page.title,
|
||||
productCallout: page.product || '',
|
||||
permissions: page.permissions || '',
|
||||
intro: page.intro,
|
||||
tocItems: (req.context.genericTocFlat || req.context.genericTocNested || []).map(
|
||||
mapRawTocItemToTocItem,
|
||||
),
|
||||
variant: req.context.genericTocFlat ? 'expanded' : 'compact',
|
||||
featuredLinks: getFeaturedLinksFromReq(req),
|
||||
renderedPage: req.context.renderedPage,
|
||||
currentLearningTrack: req.context.currentLearningTrack,
|
||||
currentLayout: req.context.currentLayoutName,
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
import { createContext, useContext } from 'react'
|
||||
import { FeaturedLink, getFeaturedLinksFromReq } from '@/landings/components/ProductLandingContext'
|
||||
import { mapRawTocItemToTocItem } from '@/landings/types'
|
||||
import type { TocItem } from '@/landings/types'
|
||||
import type { LearningTrack } from '@/types'
|
||||
|
||||
export type DiscoveryContextT = {
|
||||
title: string
|
||||
intro: string
|
||||
productCallout: string
|
||||
permissions: string
|
||||
tocItems: Array<TocItem>
|
||||
variant?: 'compact' | 'expanded'
|
||||
featuredLinks: Record<string, Array<FeaturedLink>>
|
||||
renderedPage: string
|
||||
currentLearningTrack?: LearningTrack
|
||||
currentLayout: string
|
||||
recommended?: string[] // Array of article paths
|
||||
}
|
||||
|
||||
export const DiscoveryContext = createContext<DiscoveryContextT | null>(null)
|
||||
|
||||
export const useDiscoveryContext = (): DiscoveryContextT => {
|
||||
const context = useContext(DiscoveryContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error('"useDiscoveryContext" may only be used inside "DiscoveryContext.Provider"')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export const getDiscoveryContextFromRequest = async (req: any): Promise<DiscoveryContextT> => {
|
||||
const page = req.context.page
|
||||
|
||||
// Support legacy `spotlight` property as `recommended` for pages like Copilot Cookbook
|
||||
// However, `spotlight` will have lower priority than the `recommended` property
|
||||
let recommended: string[] = []
|
||||
if (page.recommended && page.recommended.length > 0) {
|
||||
recommended = page.recommended
|
||||
} else if (page.spotlight && page.spotlight.length > 0) {
|
||||
// Remove the `image` property from spotlight items, since we don't use those for the carousel
|
||||
recommended = page.spotlight.map((item: any) => item.article)
|
||||
}
|
||||
|
||||
return {
|
||||
title: page.title,
|
||||
productCallout: page.product || '',
|
||||
permissions: page.permissions || '',
|
||||
intro: page.intro,
|
||||
tocItems: (req.context.genericTocFlat || req.context.genericTocNested || []).map(
|
||||
mapRawTocItemToTocItem,
|
||||
),
|
||||
variant: req.context.genericTocFlat ? 'expanded' : 'compact',
|
||||
featuredLinks: getFeaturedLinksFromReq(req),
|
||||
renderedPage: req.context.renderedPage,
|
||||
currentLearningTrack: req.context.currentLearningTrack,
|
||||
currentLayout: req.context.currentLayoutName,
|
||||
recommended,
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { createContext, useContext } from 'react'
|
||||
import { FeaturedLink, getFeaturedLinksFromReq } from '@/landings/components/ProductLandingContext'
|
||||
import { mapRawTocItemToTocItem } from '@/landings/types'
|
||||
import type { TocItem } from '@/landings/types'
|
||||
import type { LearningTrack } from '@/types'
|
||||
|
||||
export type JourneyContextT = {
|
||||
title: string
|
||||
intro: string
|
||||
productCallout: string
|
||||
permissions: string
|
||||
tocItems: Array<TocItem>
|
||||
variant?: 'compact' | 'expanded'
|
||||
featuredLinks: Record<string, Array<FeaturedLink>>
|
||||
renderedPage: string
|
||||
currentLearningTrack?: LearningTrack
|
||||
currentLayout: string
|
||||
}
|
||||
|
||||
export const JourneyContext = createContext<JourneyContextT | null>(null)
|
||||
|
||||
export const useJourneyContext = (): JourneyContextT => {
|
||||
const context = useContext(JourneyContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error('"useJourneyContext" may only be used inside "JourneyContext.Provider"')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export const getJourneyContextFromRequest = async (req: any): Promise<JourneyContextT> => {
|
||||
const page = req.context.page
|
||||
|
||||
return {
|
||||
title: page.title,
|
||||
productCallout: page.product || '',
|
||||
permissions: page.permissions || '',
|
||||
intro: page.intro,
|
||||
tocItems: (req.context.genericTocFlat || req.context.genericTocNested || []).map(
|
||||
mapRawTocItemToTocItem,
|
||||
),
|
||||
variant: req.context.genericTocFlat ? 'expanded' : 'compact',
|
||||
featuredLinks: getFeaturedLinksFromReq(req),
|
||||
renderedPage: req.context.renderedPage,
|
||||
currentLearningTrack: req.context.currentLearningTrack,
|
||||
currentLayout: req.context.currentLayoutName,
|
||||
}
|
||||
}
|
||||
76
src/landings/context/LandingContext.tsx
Normal file
76
src/landings/context/LandingContext.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { createContext, useContext } from 'react'
|
||||
import { FeaturedLink, getFeaturedLinksFromReq } from '@/landings/components/ProductLandingContext'
|
||||
import { mapRawTocItemToTocItem } from '@/landings/types'
|
||||
import type { TocItem } from '@/landings/types'
|
||||
import type { LearningTrack } from '@/types'
|
||||
|
||||
export type LandingType = 'bespoke' | 'discovery' | 'journey'
|
||||
|
||||
export type LandingContextT = {
|
||||
landingType: LandingType
|
||||
title: string
|
||||
intro: string
|
||||
productCallout: string
|
||||
permissions: string
|
||||
tocItems: Array<TocItem>
|
||||
variant?: 'compact' | 'expanded'
|
||||
featuredLinks: Record<string, Array<FeaturedLink>>
|
||||
renderedPage: string
|
||||
currentLearningTrack?: LearningTrack
|
||||
currentLayout: string
|
||||
heroImage?: string
|
||||
// For discovery landing pages
|
||||
recommended?: string[] // Array of article paths
|
||||
// For discovery landing pages
|
||||
introLinks?: Record<string, string>
|
||||
}
|
||||
|
||||
export const LandingContext = createContext<LandingContextT | null>(null)
|
||||
|
||||
export const useLandingContext = (): LandingContextT => {
|
||||
const context = useContext(LandingContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error('"useLandingContext" may only be used inside "LandingContext.Provider"')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export const getLandingContextFromRequest = async (
|
||||
req: any,
|
||||
landingType: LandingType,
|
||||
): Promise<LandingContextT> => {
|
||||
const page = req.context.page
|
||||
|
||||
let recommended: string[] = []
|
||||
if (landingType === 'discovery') {
|
||||
// Support legacy `spotlight` property as `recommended` for pages like Copilot Cookbook
|
||||
// However, `spotlight` will have lower priority than the `recommended` property
|
||||
if (page.recommended && page.recommended.length > 0) {
|
||||
recommended = page.recommended
|
||||
} else if (page.spotlight && page.spotlight.length > 0) {
|
||||
// Remove the `image` property from spotlight items, since we don't use those for the carousel
|
||||
recommended = page.spotlight.map((item: any) => item.article)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
landingType,
|
||||
title: page.title,
|
||||
productCallout: page.product || '',
|
||||
permissions: page.permissions || '',
|
||||
intro: page.intro,
|
||||
tocItems: (req.context.genericTocFlat || req.context.genericTocNested || []).map(
|
||||
mapRawTocItemToTocItem,
|
||||
),
|
||||
variant: req.context.genericTocFlat ? 'expanded' : 'compact',
|
||||
featuredLinks: getFeaturedLinksFromReq(req),
|
||||
renderedPage: req.context.renderedPage,
|
||||
currentLearningTrack: req.context.currentLearningTrack,
|
||||
currentLayout: req.context.currentLayoutName,
|
||||
heroImage: page.heroImage || '/assets/images/banner-images/hero-1.png',
|
||||
introLinks: page.introLinks || null,
|
||||
recommended,
|
||||
}
|
||||
}
|
||||
@@ -49,22 +49,12 @@ import {
|
||||
} from '@/frame/components/context/CategoryLandingContext'
|
||||
import { BespokeLanding } from '@/landings/components/bespoke/BespokeLanding'
|
||||
import {
|
||||
BespokeContext,
|
||||
getBespokeContextFromRequest,
|
||||
BespokeContextT,
|
||||
} from '@/landings/context/BespokeContext'
|
||||
LandingContext,
|
||||
getLandingContextFromRequest,
|
||||
LandingContextT,
|
||||
} from '@/landings/context/LandingContext'
|
||||
import { DiscoveryLanding } from '@/landings/components/discovery/DiscoveryLanding'
|
||||
import {
|
||||
DiscoveryContext,
|
||||
DiscoveryContextT,
|
||||
getDiscoveryContextFromRequest,
|
||||
} from '@/landings/context/DiscoveryContext'
|
||||
import { JourneyLanding } from '@/landings/components/journey/JourneyLanding'
|
||||
import {
|
||||
getJourneyContextFromRequest,
|
||||
JourneyContext,
|
||||
JourneyContextT,
|
||||
} from '@/landings/context/JourneyContext'
|
||||
|
||||
function initiateArticleScripts() {
|
||||
copyCode()
|
||||
@@ -79,9 +69,9 @@ type Props = {
|
||||
tocLandingContext?: TocLandingContextT
|
||||
articleContext?: ArticleContextT
|
||||
categoryLandingContext?: CategoryLandingContextT
|
||||
bespokeContext?: BespokeContextT
|
||||
discoveryContext?: DiscoveryContextT
|
||||
journeyContext?: JourneyContextT
|
||||
bespokeContext?: LandingContextT
|
||||
discoveryContext?: LandingContextT
|
||||
journeyContext?: LandingContextT
|
||||
}
|
||||
const GlobalPage = ({
|
||||
mainContext,
|
||||
@@ -108,21 +98,21 @@ const GlobalPage = ({
|
||||
let content
|
||||
if (bespokeContext) {
|
||||
content = (
|
||||
<BespokeContext.Provider value={bespokeContext}>
|
||||
<LandingContext.Provider value={bespokeContext}>
|
||||
<BespokeLanding />
|
||||
</BespokeContext.Provider>
|
||||
</LandingContext.Provider>
|
||||
)
|
||||
} else if (discoveryContext) {
|
||||
content = (
|
||||
<DiscoveryContext.Provider value={discoveryContext}>
|
||||
<LandingContext.Provider value={discoveryContext}>
|
||||
<DiscoveryLanding />
|
||||
</DiscoveryContext.Provider>
|
||||
</LandingContext.Provider>
|
||||
)
|
||||
} else if (journeyContext) {
|
||||
content = (
|
||||
<JourneyContext.Provider value={journeyContext}>
|
||||
<LandingContext.Provider value={journeyContext}>
|
||||
<JourneyLanding />
|
||||
</JourneyContext.Provider>
|
||||
</LandingContext.Provider>
|
||||
)
|
||||
} else if (productLandingContext) {
|
||||
content = (
|
||||
@@ -184,23 +174,23 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
||||
// This looks a little funky, but it's so we only send one context's data to the client
|
||||
// TODO: TEMP: This is a temporary solution to turn off/on new landing pages while we develop them
|
||||
if (currentLayoutName === 'bespoke-landing' || req.query?.feature === 'bespoke-landing') {
|
||||
props.bespokeContext = await getBespokeContextFromRequest(req)
|
||||
additionalUINamespaces.push('bespoke_landing')
|
||||
props.bespokeContext = await getLandingContextFromRequest(req, 'bespoke')
|
||||
additionalUINamespaces.push('bespoke_landing', 'product_landing')
|
||||
} else if (currentLayoutName === 'journey-landing' || req.query?.feature === 'journey-landing') {
|
||||
props.journeyContext = await getJourneyContextFromRequest(req)
|
||||
additionalUINamespaces.push('journey_landing')
|
||||
props.journeyContext = await getLandingContextFromRequest(req, 'journey')
|
||||
additionalUINamespaces.push('journey_landing', 'product_landing')
|
||||
} else if (
|
||||
currentLayoutName === 'discovery-landing' ||
|
||||
req?.query?.feature === 'discovery-landing'
|
||||
) {
|
||||
props.discoveryContext = await getDiscoveryContextFromRequest(req)
|
||||
additionalUINamespaces.push('discovery_landing')
|
||||
props.discoveryContext = await getLandingContextFromRequest(req, 'discovery')
|
||||
additionalUINamespaces.push('discovery_landing', 'product_landing')
|
||||
} else if (currentLayoutName === 'product-landing') {
|
||||
props.productLandingContext = await getProductLandingContextFromRequest(req)
|
||||
additionalUINamespaces.push('product_landing')
|
||||
} else if (currentLayoutName === 'product-guides') {
|
||||
props.productGuidesContext = getProductGuidesContextFromRequest(req)
|
||||
additionalUINamespaces.push('product_guides')
|
||||
additionalUINamespaces.push('product_guides', 'product_landing')
|
||||
} else if (relativePath?.endsWith('index.md')) {
|
||||
if (currentLayoutName === 'category-landing') {
|
||||
props.categoryLandingContext = getCategoryLandingContextFromRequest(req)
|
||||
|
||||
Reference in New Issue
Block a user