feat: add alternate landing page layout (#19571)

This commit is contained in:
Mike Surowiec 2021-05-27 07:21:40 -07:00 коммит произвёл GitHub
Родитель 170a3e9dca
Коммит 4661a36d5d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 159 добавлений и 28 удалений

Просмотреть файл

@ -0,0 +1,58 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { Dropdown } from '@primer/components'
import { useMainContext } from 'components/context/MainContext'
import { useVersion } from 'components/hooks/useVersion'
import { useTranslation } from 'components/hooks/useTranslation'
export const ArticleVersionPicker = () => {
const router = useRouter()
const { currentVersion } = useVersion()
const { allVersions, page, enterpriseServerVersions } = useMainContext()
const { t } = useTranslation('pages')
if (page.permalinks && page.permalinks.length <= 1) {
return null
}
return (
<div className="d-none d-lg-flex flex-justify-end">
<Dropdown
css={`
ul {
width: unset;
}
`}
>
<summary className="f4 h5-mktg btn-outline-mktg btn-mktg p-2">
<span className="d-md-none d-xl-inline-block">{t('article_version')}</span>{' '}
{allVersions[currentVersion].versionTitle}
<Dropdown.Caret />
</summary>
<Dropdown.Menu direction="sw">
{(page.permalinks || []).map((permalink) => {
if (permalink.pageVersion === 'homepage') {
return null
}
return (
<Dropdown.Item key={permalink.href}>
<Link href={permalink.href}>
<a>{permalink.pageVersionTitle}</a>
</Link>
</Dropdown.Item>
)
})}
<div className="pb-1">
<Link href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}>
<a className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap">
See all Enterprise releases
</a>
</Link>
</div>
</Dropdown.Menu>
</Dropdown>
</div>
)
}

Просмотреть файл

@ -1,6 +1,11 @@
import { createContext, useContext } from 'react'
import pick from 'lodash/pick'
export type TocItem = {
fullPath: string
title: string
intro?: string
}
export type FeaturedLink = {
title: string
href: string
@ -28,19 +33,12 @@ export type ProductLandingContextT = {
intro: string
beta_product: boolean
product: Product
// primaryAction: LinkButtonT
// secondaryAction?: LinkButtonT
introLinks: {
quickstart?: string
reference?: string
overview?: string
}
} | null
product_video?: string
// featuredLinks?: {
// guides: Array<FeaturedLink>
// popular: Array<FeaturedLink>
// guideCards: Array<FeaturedLink>
// }
guideCards: Array<FeaturedLink>
productCodeExamples: Array<CodeExample>
productUserExamples: Array<{ username: string; description: string }>
@ -53,6 +51,7 @@ export type ProductLandingContextT = {
changelog: { label: string; prefix: string }
changelogUrl?: string
whatsNewChangelog?: Array<{ href: string; title: string; date: string }>
tocItems: Array<TocItem>
}
export const ProductLandingContext = createContext<ProductLandingContextT | null>(null)
@ -97,20 +96,26 @@ export const getProductLandingContextFromRequest = (req: any): ProductLandingCon
})
),
introLinks: {
quickstart: productTree.page.introLinks.quickstart,
reference: productTree.page.introLinks.reference,
overview: productTree.page.introLinks.overview,
},
introLinks: productTree.page.introLinks
? {
quickstart: productTree.page.introLinks.quickstart,
reference: productTree.page.introLinks.reference,
overview: productTree.page.introLinks.overview,
}
: null,
guideCards: (req.context.featuredLinks ? (req.context.featuredLinks.guideCards || []) : []).map((link: any) => {
return {
href: link.href,
title: link.title,
intro: link.intro,
authors: link.page.authors || [],
guideCards: (req.context.featuredLinks ? req.context.featuredLinks.guideCards || [] : []).map(
(link: any) => {
return {
href: link.href,
title: link.title,
intro: link.intro,
authors: link.page.authors || [],
}
}
}),
),
tocItems: req.context.tocItems || [],
featuredArticles: Object.entries(req.context.featuredLinks || [])
.filter(([key]) => {
@ -119,7 +124,10 @@ export const getProductLandingContextFromRequest = (req: any): ProductLandingCon
.map(([key, links]: any) => {
return {
label: req.context.site.data.ui.toc[key],
viewAllHref: key === 'guides' && !req.context.currentCategory ? `${req.context.currentPath}/${key}` : '',
viewAllHref:
key === 'guides' && !req.context.currentCategory
? `${req.context.currentPath}/${key}`
: '',
articles: links.map((link: any) => {
return {
hideIntro: key === 'popular',
@ -130,7 +138,6 @@ export const getProductLandingContextFromRequest = (req: any): ProductLandingCon
}
}),
}
}
),
}),
}
}

Просмотреть файл

@ -50,9 +50,10 @@ const ArticleList = ({ page }: { page: CurrentProductTree }) => {
<a>{grandchildPage.page.title}</a>
</Link>
{grandchildPage.page.documentType === 'mapTopic' ? (
<small className="color-text-secondary d-inline-block">
&nbsp;&bull; {page.childPages.length} articles
</small>) : null}
<small className="color-text-secondary d-inline-block">
&nbsp;&bull; {page.childPages.length} articles
</small>
) : null}
</li>
)
})}

Просмотреть файл

@ -0,0 +1,30 @@
import { useRouter } from 'next/router'
import Link from 'next/link'
import cx from 'classnames'
import type { TocItem } from '../context/ProductLandingContext'
export const TableOfContents = (props: { items?: Array<TocItem> }) => {
const router = useRouter()
return (
<div>
{(props.items || []).map(({ fullPath: href, title, intro }) => {
const isActive = router.pathname === href
return (
<div key={href} className={cx('mb-5', isActive && 'color-auto-gray-4')}>
<Link href={href}>
<a className="Bump-link--hover no-underline d-block py-1 border-bottom color-border-primary">
<h4>
{title}
<span className="Bump-link-symbol"></span>
</h4>
</a>
</Link>
{intro && <p className="f4 mt-3" dangerouslySetInnerHTML={{ __html: intro }} />}
</div>
)
})}
</div>
)
}

Просмотреть файл

@ -1,4 +1,5 @@
import { GetServerSideProps } from 'next'
import { Grid } from '@primer/components'
import {
MainContextT,
@ -22,6 +23,8 @@ import { CodeExamples } from 'components/landing/CodeExamples'
import { LandingSection } from 'components/landing/LandingSection'
import { useTranslation } from 'components/hooks/useTranslation'
import { ProductArticlesList } from 'components/landing/ProductArticlesList'
import { TableOfContents } from 'components/landing/TableOfContents'
import { ArticleVersionPicker } from 'components/article/ArticleVersionPicker'
type Props = {
mainContext: MainContextT
@ -31,13 +34,17 @@ const ProductPage = ({ mainContext, productLandingContext }: Props) => {
return (
<MainContext.Provider value={mainContext}>
<ProductLandingContext.Provider value={productLandingContext}>
<ProductPageInner />
{mainContext.currentLayoutName === 'product-landing' ? (
<ProductLanding />
) : (
<TocProductLanding />
)}
</ProductLandingContext.Provider>
</MainContext.Provider>
)
}
const ProductPageInner = () => {
const ProductLanding = () => {
const { title, guideCards, productUserExamples, productCommunityExamples, productCodeExamples } =
useProductLandingContext()
const { t } = useTranslation('product_landing')
@ -85,6 +92,34 @@ const ProductPageInner = () => {
)
}
const TocProductLanding = () => {
const { title, introPlainText, tocItems } = useProductLandingContext()
return (
<DefaultLayout>
<Grid
className="container-xl px-3 px-md-6 my-4 my-lg-4 container-xl "
gridTemplateColumns="minmax(500px, 720px) minmax(220px, 1fr)"
gridTemplateRows="auto 1fr"
gridGap={16}
>
<div>
<h1 className="my-4">{title}</h1>
<div className="lead-mktg">
<p>{introPlainText}</p>
</div>
<div className="mt-7">
<TableOfContents items={tocItems} />
</div>
</div>
<div>
<ArticleVersionPicker />
</div>
</Grid>
</DefaultLayout>
)
}
export default ProductPage
export const getServerSideProps: GetServerSideProps<Props> = async (context) => {