1
0
mirror of synced 2025-12-22 19:34:15 -05:00

Merge pull request #7248 from github/repo-sync

repo sync
This commit is contained in:
Octomerger Bot
2021-06-10 07:34:43 +10:00
committed by GitHub
23 changed files with 791 additions and 13 deletions

View File

@@ -45,7 +45,7 @@ export const DefaultLayout = (props: Props) => {
</Head> </Head>
<SidebarNav /> <SidebarNav />
<main className="width-full"> <main className="flex-1 min-width-0">
<Header /> <Header />
<DeprecationBanner /> <DeprecationBanner />

View File

@@ -22,7 +22,8 @@ export const Header = () => {
const showVersionPicker = const showVersionPicker =
relativePath === 'index.md' || relativePath === 'index.md' ||
currentLayoutName === 'product-landing' || currentLayoutName === 'product-landing' ||
currentLayoutName === 'product-sublanding' currentLayoutName === 'product-sublanding' ||
currentLayoutName === 'release-notes'
return ( return (
<div className="border-bottom color-border-secondary no-print"> <div className="border-bottom color-border-secondary no-print">

View File

@@ -87,6 +87,7 @@ export const HeaderNotifications = () => {
const isLast = i === allNotifications.length - 1 const isLast = i === allNotifications.length - 1
return ( return (
<div <div
key={content}
className={cx( className={cx(
'header-notifications text-center f5 color-text-primary py-4 px-6', 'header-notifications text-center f5 color-text-primary py-4 px-6',
type === NotificationType.TRANSLATION && 'translation_notice color-bg-info', type === NotificationType.TRANSLATION && 'translation_notice color-bg-info',

View File

@@ -59,6 +59,7 @@ type EnterpriseServerReleases = {
isOldestReleaseDeprecated: boolean isOldestReleaseDeprecated: boolean
oldestSupported: string oldestSupported: string
nextDeprecationDate: string nextDeprecationDate: string
supported: Array<string>
} }
export type MainContextT = { export type MainContextT = {
breadcrumbs: { breadcrumbs: {
@@ -154,6 +155,7 @@ export const getMainContextFromRequest = (req: any): MainContextT => {
'isOldestReleaseDeprecated', 'isOldestReleaseDeprecated',
'oldestSupported', 'oldestSupported',
'nextDeprecationDate', 'nextDeprecationDate',
'supported',
]), ]),
enterpriseServerVersions: req.context.enterpriseServerVersions, enterpriseServerVersions: req.context.enterpriseServerVersions,
currentLanguage: req.context.currentLanguage, currentLanguage: req.context.currentLanguage,

View File

@@ -52,6 +52,12 @@ export type ProductLandingContextT = {
changelogUrl?: string changelogUrl?: string
whatsNewChangelog?: Array<{ href: string; title: string; date: string }> whatsNewChangelog?: Array<{ href: string; title: string; date: string }>
tocItems: Array<TocItem> tocItems: Array<TocItem>
releases: Array<{
version: string
firstPreviousRelease: string
secondPreviousRelease: string
patches: Array<{ date: string; version: string }>
}>
} }
export const ProductLandingContext = createContext<ProductLandingContextT | null>(null) export const ProductLandingContext = createContext<ProductLandingContextT | null>(null)
@@ -89,6 +95,7 @@ export const getProductLandingContextFromRequest = (req: any): ProductLandingCon
changelogUrl: req.context.changelogUrl || [], changelogUrl: req.context.changelogUrl || [],
productCodeExamples: req.context.productCodeExamples || [], productCodeExamples: req.context.productCodeExamples || [],
productCommunityExamples: req.context.productCommunityExamples || [], productCommunityExamples: req.context.productCommunityExamples || [],
releases: req.context.releases || [],
productUserExamples: (req.context.productUserExamples || []).map( productUserExamples: (req.context.productUserExamples || []).map(
({ user, description }: any) => ({ ({ user, description }: any) => ({

View File

@@ -0,0 +1,25 @@
import { useState, useEffect, MutableRefObject, RefObject } from 'react'
export function useOnScreen<T extends Element>(
ref: MutableRefObject<T | undefined> | RefObject<T>,
rootMargin: string = '0px'
): boolean {
const [isIntersecting, setIntersecting] = useState(false)
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
setIntersecting(entry.isIntersecting)
},
{
rootMargin,
}
)
if (ref.current) {
observer.observe(ref.current)
}
return () => {
ref.current && observer.unobserve(ref.current)
}
}, [])
return isIntersecting
}

View File

@@ -3,10 +3,15 @@ import { useRouter } from 'next/router'
type VersionInfo = { type VersionInfo = {
currentVersion: string currentVersion: string
isEnterprise: boolean isEnterprise: boolean
isEnterpriseServer: boolean
} }
const DEFAULT_VERSION = 'free-pro-team@latest' const DEFAULT_VERSION = 'free-pro-team@latest'
export const useVersion = (): VersionInfo => { export const useVersion = (): VersionInfo => {
const router = useRouter() const router = useRouter()
const currentVersion = (router.query.versionId as string) || DEFAULT_VERSION const currentVersion = (router.query.versionId as string) || DEFAULT_VERSION
return { currentVersion, isEnterprise: currentVersion.includes('enterprise') } return {
currentVersion,
isEnterprise: currentVersion.includes('enterprise'),
isEnterpriseServer: currentVersion.includes('enterprise-server'),
}
} }

View File

@@ -10,8 +10,13 @@ import { CodeExamples } from 'components/landing/CodeExamples'
import { LandingSection } from 'components/landing/LandingSection' import { LandingSection } from 'components/landing/LandingSection'
import { useTranslation } from 'components/hooks/useTranslation' import { useTranslation } from 'components/hooks/useTranslation'
import { ProductArticlesList } from 'components/landing/ProductArticlesList' import { ProductArticlesList } from 'components/landing/ProductArticlesList'
import { ProductReleases } from 'components/landing/ProductReleases'
import { useRouter } from 'next/router'
import { useVersion } from 'components/hooks/useVersion'
export const ProductLanding = () => { export const ProductLanding = () => {
const router = useRouter()
const { isEnterpriseServer } = useVersion()
const { const {
shortTitle, shortTitle,
guideCards, guideCards,
@@ -49,9 +54,11 @@ export const ProductLanding = () => {
</LandingSection> </LandingSection>
)} )}
{/* {% if currentVersion contains 'enterprise-server' and currentProduct == 'admin' %} {router.query.productId === 'admin' && isEnterpriseServer && (
{% include product-releases %} <LandingSection title={t('supported_releases')} className="my-6">
{% endif %} */} <ProductReleases />
</LandingSection>
)}
{guideCards.length > 0 && ( {guideCards.length > 0 && (
<div className="color-bg-tertiary py-6 my-8"> <div className="color-bg-tertiary py-6 my-8">

View File

@@ -0,0 +1,68 @@
import { ArrowRightIcon, ArrowUpIcon, FileIcon, ListUnorderedIcon } from '@primer/octicons-react'
import { useMainContext } from 'components/context/MainContext'
import { useProductLandingContext } from 'components/context/ProductLandingContext'
import { useTranslation } from 'components/hooks/useTranslation'
import { Link } from 'components/Link'
import { useRouter } from 'next/router'
export function ProductReleases() {
const { t } = useTranslation('product_landing')
const router = useRouter()
const { enterpriseServerReleases, allVersions } = useMainContext()
const { releases } = useProductLandingContext()
const currentPath = router.asPath.split('?')[0]
return (
<div>
<div className="d-lg-flex gutter-lg flex-items-stretch">
{releases.map((release) => {
const releaseNumber = release.version
if (!enterpriseServerReleases.supported.includes(releaseNumber)) {
return null
}
const releaseVersion = `enterprise-server@${releaseNumber}`
const latestPatch = release.patches[0]
const firstPreviousVersion = `enterprise-server@${release.firstPreviousRelease}`
const secondPreviousVersion = `enterprise-server@${release.secondPreviousRelease}`
return (
<div key={releaseNumber} className="col-lg-4 col-12 mb-3">
<div className="Box color-shadow-medium height-full d-block hover-shadow-large no-underline color-text-primary p-5">
<h2>{allVersions[releaseVersion].versionTitle}</h2>
<p className="mt-2 mb-4 color-text-tertiary">
<ListUnorderedIcon />{' '}
<Link
href={`/${router.locale}/${releaseVersion}/admin/release-notes#${latestPatch.version}`}
>
{t('release_notes_for')} {latestPatch.version}
</Link>{' '}
({latestPatch.date})
</p>
<p className="mt-2 mb-4 color-text-tertiary">
<ArrowUpIcon /> {t('upgrade_from')}{' '}
<Link
href={`/${router.locale}/${firstPreviousVersion}/admin/enterprise-management/upgrading-github-enterprise-server`}
>
{release.firstPreviousRelease}
</Link>{' '}
or{' '}
<Link
href={`/${router.locale}/${secondPreviousVersion}/admin/enterprise-management/upgrading-github-enterprise-server`}
>
{release.secondPreviousRelease}
</Link>
</p>
<p className="mt-2 mb-4 color-text-tertiary">
<FileIcon />{' '}
<Link href={`/${router.locale}/${releaseVersion}`}>{t('browse_all_docs')}</Link>
</p>
</div>
</div>
)
})}
</div>
<Link href={`${currentPath}/release-notes}`} className="btn btn-outline float-right">
{t('explore_release_notes')} <ArrowRightIcon />
</Link>
</div>
)
}

View File

@@ -0,0 +1,59 @@
import { useRef, useEffect } from 'react'
import { useTranslation } from 'components/hooks/useTranslation'
import { useOnScreen } from 'components/hooks/useOnScreen'
import { PatchNotes } from './PatchNotes'
import { ReleaseNotePatch } from './types'
type Props = { patch: ReleaseNotePatch; didEnterView: () => void }
export function GHAEReleaseNotePatch({ patch, didEnterView }: Props) {
const { t } = useTranslation('release_notes')
const containerRef = useRef<HTMLDivElement>(null)
const onScreen = useOnScreen(containerRef, '-40% 0px -50%')
useEffect(() => {
if (onScreen) {
didEnterView()
}
}, [onScreen])
const bannerText = patch.currentWeek
? t('banner_text_current')
: `${t('banner_text_past')} ${patch.friendlyDate}.`
return (
<div
ref={containerRef}
className="mb-10 color-bg-secondary pb-6 border-bottom border-top"
id={patch.date}
>
<header
style={{ zIndex: 1 }}
className="container-xl position-sticky top-0 color-bg-secondary border-bottom px-3 pt-4 pb-2"
>
<div className="d-flex flex-items-center">
<h2 className="border-bottom-0 m-0 p-0">{patch.title}</h2>
{patch.release_candidate && (
<span
className="IssueLabel color-bg-warning-inverse color-text-inverse ml-3"
style={{ whiteSpace: 'pre' }}
>
Release Candidate
</span>
)}
<button className="js-print btn-link ml-3 text-small text-bold">Print</button>
</div>
<p className="color-text-secondary mt-1">
{patch.friendlyDate} - {bannerText}
</p>
</header>
<div className="container-xl px-3">
<div className="mt-3" dangerouslySetInnerHTML={{ __html: patch.intro }} />
<PatchNotes patch={patch} />
</div>
</div>
)
}

View File

@@ -0,0 +1,89 @@
import { useState } from 'react'
import cx from 'classnames'
import { ChevronDownIcon } from '@primer/octicons-react'
import { GHAEReleaseNotePatch } from './GHAEReleaseNotePatch'
import { GHAEReleaseNotesContextT } from './types'
type GitHubAEProps = {
context: GHAEReleaseNotesContextT
}
export function GHAEReleaseNotes({ context }: GitHubAEProps) {
const { releaseNotes, releases, currentVersion } = context
const [focusedPatch, setFocusedPatch] = useState('')
return (
<div className="d-flex">
<article className="min-width-0 flex-1">
<div className="d-flex flex-items-center flex-justify-between color-bg-primary px-5 py-2">
<div></div>
<h1 className="f4 py-3 m-0">{currentVersion.planTitle} release notes</h1>
<div></div>
</div>
<div className="markdown-body">
{releaseNotes.map((patch) => {
return (
<GHAEReleaseNotePatch
key={patch.version}
patch={patch}
didEnterView={() => setFocusedPatch(patch.version)}
/>
)
})}
</div>
</article>
<aside
className="markdown-body position-sticky top-0 d-none d-md-block border-left no-print color-bg-primary flex-shrink-0"
style={{ width: 260, height: '100vh' }}
>
<nav className="height-full overflow-auto">
<ul className="list-style-none pl-0 text-bold">
{releases.map((release) => {
return (
<li key={release.version} className="border-bottom">
<details
className="my-0 details-reset release-notes-version-picker"
aria-current="page"
open
>
<summary className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between">
{release.version}
<div className="d-flex">
<span className="color-text-tertiary text-mono text-small text-normal mr-1">
{release.patches.length} releases
</span>
<ChevronDownIcon />
</div>
</summary>
<ul className="color-bg-tertiary border-top list-style-none py-4 px-0 my-0">
{release.patches.map((patch) => {
const isActive = patch.version === focusedPatch
return (
<li
key={patch.version}
className={cx(
'js-release-notes-patch-link px-3 my-0 py-1',
isActive && 'selected'
)}
>
<a
href={`#${patch.date}`}
className="d-flex flex-items-center flex-justify-between"
>
{patch.friendlyDate}
</a>
</li>
)
})}
</ul>
</details>
</li>
)
})}
</ul>
</nav>
</aside>
</div>
)
}

View File

@@ -0,0 +1,110 @@
import { useEffect, useRef } from 'react'
import dayjs from 'dayjs'
import { useTranslation } from 'components/hooks/useTranslation'
import { PatchNotes } from './PatchNotes'
import { Link } from 'components/Link'
import { CurrentVersion, ReleaseNotePatch, GHESMessage } from './types'
import { useOnScreen } from 'components/hooks/useOnScreen'
type Props = {
patch: ReleaseNotePatch
currentVersion: CurrentVersion
latestPatch: string
latestRelease: string
message: GHESMessage
didEnterView: () => void
}
export function GHESReleaseNotePatch({
patch,
currentVersion,
latestPatch,
latestRelease,
message,
didEnterView,
}: Props) {
const { t } = useTranslation('header')
const containerRef = useRef<HTMLDivElement>(null)
const onScreen = useOnScreen(containerRef, '-40% 0px -50%')
useEffect(() => {
if (onScreen) {
didEnterView()
}
}, [onScreen])
return (
<div
ref={containerRef}
className="mb-10 color-bg-secondary pb-6 border-bottom border-top"
id={patch.version}
>
<header
style={{ zIndex: 1 }}
className="container-xl position-sticky top-0 color-bg-secondary border-bottom px-3 pt-4 pb-2"
>
<div className="d-flex flex-items-center">
<h2 className="border-bottom-0 m-0 p-0">
{currentVersion.versionTitle}.{patch.patchVersion}
</h2>
{patch.release_candidate && (
<span
className="IssueLabel color-bg-warning-inverse color-text-inverse ml-3"
style={{ whiteSpace: 'pre' }}
>
Release Candidate
</span>
)}
{currentVersion.plan == 'enterprise-server' && (
<Link
href={`https://enterprise.github.com/releases/${patch.downloadVersion}/download`}
className="ml-3 text-small text-bold"
>
Download
</Link>
)}
<button className="js-print btn-link ml-3 text-small text-bold">Print</button>
</div>
<p className="color-text-secondary mt-1">{dayjs(patch.date).format('MMMM, DD, YYYY')}</p>
{patch.version !== latestPatch && currentVersion.currentRelease === latestRelease && (
<p className="color-text-secondary mt-1">
<span
dangerouslySetInnerHTML={{ __html: message.ghes_release_notes_upgrade_patch_only }}
/>{' '}
{t('notices.release_notes_use_latest')}
</p>
)}
{patch.version === latestPatch && currentVersion.currentRelease !== latestRelease && (
<p className="color-text-secondary mt-1">
<span
dangerouslySetInnerHTML={{ __html: message.ghes_release_notes_upgrade_release_only }}
/>{' '}
{t('notices.release_notes_use_latest')}
</p>
)}
{patch.version !== latestPatch && currentVersion.currentRelease !== latestRelease && (
<p className="color-text-secondary mt-1">
<span
dangerouslySetInnerHTML={{
__html: message.ghes_release_notes_upgrade_patch_and_release,
}}
/>{' '}
{t('notices.release_notes_use_latest')}
</p>
)}
</header>
<div className="container-xl px-3">
<div className="mt-3" dangerouslySetInnerHTML={{ __html: patch.intro }} />
<PatchNotes patch={patch} withReleaseNoteLabel />
</div>
</div>
)
}

View File

@@ -0,0 +1,170 @@
import { useState } from 'react'
import cx from 'classnames'
import {
ChevronDownIcon,
ChevronLeftIcon,
ChevronRightIcon,
LinkExternalIcon,
} from '@primer/octicons-react'
import { useMainContext } from 'components/context/MainContext'
import dayjs from 'dayjs'
import { Link } from 'components/Link'
import { GHESReleaseNotesContextT } from './types'
import { GHESReleaseNotePatch } from './GHESReleaseNotePatch'
type Props = {
context: GHESReleaseNotesContextT
}
export function GHESReleaseNotes({ context }: Props) {
const { currentLanguage, currentProduct } = useMainContext()
const [focusedPatch, setFocusedPatch] = useState('')
const {
prevRelease,
nextRelease,
latestPatch,
latestRelease,
currentVersion,
releaseNotes,
releases,
message,
} = context
return (
<div className="d-flex">
<article className="min-width-0 flex-1">
<div className="d-flex flex-items-center flex-justify-between color-bg-primary text-bold px-5 py-2">
{prevRelease ? (
<Link
className="btn btn-outline"
href={`/${currentLanguage}/${currentVersion.plan}@${prevRelease}/${currentProduct}/release-notes`}
>
<ChevronLeftIcon /> {prevRelease}
</Link>
) : (
<div />
)}
<h1 className="f4 py-3 m-0">
{currentVersion.planTitle} {currentVersion.currentRelease} release notes
</h1>
{nextRelease ? (
<Link
className="btn btn-outline"
href={`/${currentLanguage}/${currentVersion.plan}@${nextRelease}/${currentProduct}/release-notes`}
>
{nextRelease} <ChevronRightIcon />
</Link>
) : (
<div />
)}
</div>
<div className="markdown-body">
{releaseNotes.map((patch) => {
return (
<GHESReleaseNotePatch
key={patch.version}
patch={patch}
currentVersion={currentVersion}
latestPatch={latestPatch}
latestRelease={latestRelease}
message={message}
didEnterView={() => {
setFocusedPatch(patch.version)
}}
/>
)
})}
</div>
</article>
<aside
className="markdown-body position-sticky top-0 d-none d-md-block border-left no-print color-bg-primary flex-shrink-0"
style={{ width: 260, height: '100vh' }}
>
<nav className="height-full overflow-auto">
<ul className="list-style-none pl-0 text-bold">
{releases.map((release) => {
const releaseLink = `/${currentLanguage}/${currentVersion.plan}@${release.version}/${currentProduct?.id}/release-notes`
if (!release.patches || release.patches.length === 0) {
return (
<li key={release.version} className="border-bottom">
<Link
href={releaseLink}
className="Link--primary no-underline px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"
>
{release.version}
<LinkExternalIcon />
</Link>
</li>
)
}
if (release.version === currentVersion.currentRelease) {
return (
<li key={release.version} className="border-bottom">
<details
className="my-0 details-reset release-notes-version-picker"
aria-current="page"
open
>
<summary className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between">
{release.version}
<div className="d-flex">
<span className="color-text-tertiary text-mono text-small text-normal mr-1">
{release.patches.length} releases
</span>
<ChevronDownIcon />
</div>
</summary>
<ul className="color-bg-tertiary border-top list-style-none py-4 px-0 my-0">
{release.patches.map((patch) => {
const isActive = patch.version === focusedPatch
return (
<li
key={patch.version}
className={cx(
'js-release-notes-patch-link px-3 my-0 py-1',
isActive && 'selected'
)}
>
<Link
href={`${releaseLink}#${patch.version}`}
className="d-flex flex-items-center flex-justify-between"
>
{patch.version}
<span className="color-text-tertiary text-mono text-small text-normal">
{dayjs(patch.date).format('MMMM DD, YYYY')}
</span>
</Link>
</li>
)
})}
</ul>
</details>
</li>
)
}
return (
<li key={release.version} className="border-bottom">
<Link
className="px-3 py-4 my-0 d-flex flex-items-center flex-justify-between"
href={releaseLink}
>
{release.version}
<span className="color-text-tertiary text-mono text-small text-normal mr-1">
{release.patches.length} releases
</span>
</Link>
</li>
)
})}
</ul>
</nav>
</aside>
</div>
)
}

View File

@@ -0,0 +1,84 @@
import cx from 'classnames'
import slugger from 'github-slugger'
import { ReleaseNotePatch } from './types'
import { Link } from 'components/Link'
const SectionToLabelMap: Record<string, string> = {
features: 'Features',
bugs: 'Bug fixes',
known_issues: 'Known issues',
security_fixes: 'Security fixes',
changes: 'Changes',
deprecations: 'Deprecations',
backups: 'Backups',
}
type Props = {
patch: ReleaseNotePatch
withReleaseNoteLabel?: boolean
}
export function PatchNotes({ patch, withReleaseNoteLabel }: Props) {
return (
<>
{Object.entries(patch.sections).map(([key, sectionItems], i, arr) => {
const isLast = i === arr.length - 1
return (
<div
key={key}
className={cx(
`release-notes-section-${key}`,
'py-6 d-block d-xl-flex gutter-xl flex-items-baseline',
!withReleaseNoteLabel && 'mx-6',
!isLast && 'border-bottom'
)}
>
{withReleaseNoteLabel && (
<div className="col-12 col-xl-3 mb-5">
<span className="px-3 py-2 text-small text-bold text-uppercase text-mono color-text-inverse release-notes-section-label">
{SectionToLabelMap[key] || 'INVALID SECTION'}
</span>
</div>
)}
<ul className={cx(withReleaseNoteLabel && 'col-xl-9', 'col-12 release-notes-list')}>
{sectionItems.map((item) => {
if (typeof item === 'string') {
return (
<li key={item} className="release-notes-list-item">
<span dangerouslySetInnerHTML={{ __html: item }} />
</li>
)
}
const slug = item.heading ? slugger.slug(item.heading) : ''
return (
<li key={slug} className="release-notes-list-item list-style-none">
<h4
id={slug}
className="release-notes-section-heading text-uppercase text-bold"
>
<Link href={`#${slug}`} className="text-inherit">
{item.heading}
</Link>
</h4>
<ul className="pl-0 pb-4 mt-2 release-notes-list">
{item.notes.map((note) => {
return (
<li
key={note}
className="release-notes-list-item"
dangerouslySetInnerHTML={{ __html: note }}
/>
)
})}
</ul>
</li>
)
})}
</ul>
</div>
)
})}
</>
)
}

View File

@@ -0,0 +1,49 @@
export type CurrentVersion = {
plan: string
planTitle: string
versionTitle: string
currentRelease: string
}
export type GHESMessage = {
ghes_release_notes_upgrade_patch_only: string
ghes_release_notes_upgrade_release_only: string
ghes_release_notes_upgrade_patch_and_release: string
}
type ReleaseNoteSection =
| {
heading?: string
notes: Array<string>
}
| string
export type ReleaseNotePatch = {
patchVersion: string
version: string
downloadVersion: string
intro: string
date: string
friendlyDate: string
title: string
release_candidate?: boolean
currentWeek: boolean
sections: Record<string, Array<ReleaseNoteSection>>
}
export type GHAEReleaseNotesContextT = {
releaseNotes: Array<ReleaseNotePatch>
releases: Array<{ version: string; patches: Array<ReleaseNotePatch> }>
currentVersion: CurrentVersion
}
export type GHESReleaseNotesContextT = {
latestPatch: string
prevRelease?: string
nextRelease?: string
latestRelease: string
currentVersion: CurrentVersion
releaseNotes: Array<ReleaseNotePatch>
releases: Array<{ version: string; patches: Array<ReleaseNotePatch> }>
message: GHESMessage
}

View File

@@ -20,9 +20,9 @@ header:
early_access: 📣 Please <b>do not share</b> this URL publicly. This page contains content about an early access feature. early_access: 📣 Please <b>do not share</b> this URL publicly. This page contains content about an early access feature.
release_notes_use_latest: Please use the latest release for the latest security, performance, and bug fixes. release_notes_use_latest: Please use the latest release for the latest security, performance, and bug fixes.
# GHES release notes # GHES release notes
ghes_release_notes_upgrade_patch_only: 📣 This is not the <a href="#{{ latestPatch }}">latest patch release</a> of Enterprise Server. {% data ui.header.notices.release_notes_use_latest %} ghes_release_notes_upgrade_patch_only: 📣 This is not the <a href="#{{ latestPatch }}">latest patch release</a> of Enterprise Server.
ghes_release_notes_upgrade_release_only: 📣 This is not the <a href="/enterprise-server@{{ latestRelease }}/admin/release-notes">latest release</a> of Enterprise Server. {% data ui.header.notices.release_notes_use_latest %} ghes_release_notes_upgrade_release_only: 📣 This is not the <a href="/enterprise-server@{{ latestRelease }}/admin/release-notes">latest release</a> of Enterprise Server.
ghes_release_notes_upgrade_patch_and_release: 📣 This is not the <a href="#{{ latestPatch }}">latest patch release</a> of this release series, and this is not the <a href="/enterprise-server@{{ latestRelease }}/admin/release-notes">latest release</a> of Enterprise Server. {% data ui.header.notices.release_notes_use_latest %} ghes_release_notes_upgrade_patch_and_release: 📣 This is not the <a href="#{{ latestPatch }}">latest patch release</a> of this release series, and this is not the <a href="/enterprise-server@{{ latestRelease }}/admin/release-notes">latest release</a> of Enterprise Server.
release_notes: release_notes:
banner_text_current: These changes will roll out over the next one week. banner_text_current: These changes will roll out over the next one week.
banner_text_past: These changes rolled out to enterprises during the week of banner_text_past: These changes rolled out to enterprises during the week of

View File

@@ -54,15 +54,15 @@
<p class="color-text-secondary mt-1">{{ patch.date | date: "%B %d, %Y" }}</p> <p class="color-text-secondary mt-1">{{ patch.date | date: "%B %d, %Y" }}</p>
{% if patch.version != latestPatch and currentVersionObject.currentRelease == latestRelease %} {% if patch.version != latestPatch and currentVersionObject.currentRelease == latestRelease %}
<p class="color-text-secondary mt-1">{% data ui.header.notices.ghes_release_notes_upgrade_patch_only %}</p> <p class="color-text-secondary mt-1">{% data ui.header.notices.ghes_release_notes_upgrade_patch_only %} {% data ui.header.notices.release_notes_use_latest %}</p>
{% endif %} {% endif %}
{% if patch.version == latestPatch and currentVersionObject.currentRelease != latestRelease %} {% if patch.version == latestPatch and currentVersionObject.currentRelease != latestRelease %}
<p class="color-text-secondary mt-1">{% data ui.header.notices.ghes_release_notes_upgrade_release_only %}</p> <p class="color-text-secondary mt-1">{% data ui.header.notices.ghes_release_notes_upgrade_release_only %} {% data ui.header.notices.release_notes_use_latest %}</p>
{% endif %} {% endif %}
{% if patch.version != latestPatch and currentVersionObject.currentRelease != latestRelease %} {% if patch.version != latestPatch and currentVersionObject.currentRelease != latestRelease %}
<p class="color-text-secondary mt-1">{% data ui.header.notices.ghes_release_notes_upgrade_patch_and_release %}</p> <p class="color-text-secondary mt-1">{% data ui.header.notices.ghes_release_notes_upgrade_patch_and_release %} {% data ui.header.notices.release_notes_use_latest %}</p>
{% endif %} {% endif %}
</header> </header>

View File

@@ -1,4 +1,5 @@
export default function releaseNotes () { export default function releaseNotes () {
if (window.next) return
const patches = Array.from(document.querySelectorAll('.js-release-notes-patch')) const patches = Array.from(document.querySelectorAll('.js-release-notes-patch'))
if (patches.length === 0) return if (patches.length === 0) return

13
package-lock.json generated
View File

@@ -93,6 +93,7 @@
"@graphql-inspector/core": "^2.5.0", "@graphql-inspector/core": "^2.5.0",
"@graphql-tools/load": "^6.2.8", "@graphql-tools/load": "^6.2.8",
"@octokit/rest": "^18.5.3", "@octokit/rest": "^18.5.3",
"@types/github-slugger": "^1.3.0",
"@types/lodash": "^4.14.169", "@types/lodash": "^4.14.169",
"@types/react": "^17.0.6", "@types/react": "^17.0.6",
"@types/react-dom": "^17.0.5", "@types/react-dom": "^17.0.5",
@@ -4040,6 +4041,12 @@
"integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==", "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==",
"devOptional": true "devOptional": true
}, },
"node_modules/@types/github-slugger": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@types/github-slugger/-/github-slugger-1.3.0.tgz",
"integrity": "sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g==",
"dev": true
},
"node_modules/@types/graceful-fs": { "node_modules/@types/graceful-fs": {
"version": "4.1.5", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
@@ -27663,6 +27670,12 @@
"integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==", "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==",
"devOptional": true "devOptional": true
}, },
"@types/github-slugger": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@types/github-slugger/-/github-slugger-1.3.0.tgz",
"integrity": "sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g==",
"dev": true
},
"@types/graceful-fs": { "@types/graceful-fs": {
"version": "4.1.5", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",

View File

@@ -99,6 +99,7 @@
"@graphql-inspector/core": "^2.5.0", "@graphql-inspector/core": "^2.5.0",
"@graphql-tools/load": "^6.2.8", "@graphql-tools/load": "^6.2.8",
"@octokit/rest": "^18.5.3", "@octokit/rest": "^18.5.3",
"@types/github-slugger": "^1.3.0",
"@types/lodash": "^4.14.169", "@types/lodash": "^4.14.169",
"@types/react": "^17.0.6", "@types/react": "^17.0.6",
"@types/react-dom": "^17.0.5", "@types/react-dom": "^17.0.5",

View File

@@ -0,0 +1,81 @@
import { GetServerSideProps } from 'next'
import { Liquid } from 'liquidjs'
const liquid = new Liquid()
import {
MainContextT,
MainContext,
getMainContextFromRequest,
} from 'components/context/MainContext'
import { DefaultLayout } from 'components/DefaultLayout'
import { GHAEReleaseNotes } from 'components/release-notes/GHAEReleaseNotes'
import { GHESReleaseNotes } from 'components/release-notes/GHESReleaseNotes'
import {
CurrentVersion,
GHAEReleaseNotesContextT,
GHESReleaseNotesContextT,
} from 'components/release-notes/types'
type Props = {
mainContext: MainContextT
ghaeContext: GHAEReleaseNotesContextT
ghesContext: GHESReleaseNotesContextT
currentVersion: CurrentVersion
}
export default function ReleaseNotes({
mainContext,
ghesContext,
ghaeContext,
currentVersion,
}: Props) {
return (
<MainContext.Provider value={mainContext}>
<DefaultLayout>
{currentVersion.plan === 'enterprise-server' && <GHESReleaseNotes context={ghesContext} />}
{currentVersion.plan === 'github-ae' && <GHAEReleaseNotes context={ghaeContext} />}
</DefaultLayout>
</MainContext.Provider>
)
}
export const getServerSideProps: GetServerSideProps<Props> = async (context) => {
const req = context.req as any
const currentVersion = req.context.allVersions[req.context.currentVersion]
const { latestPatch = '', latestRelease = '' } = req.context
return {
props: {
mainContext: getMainContextFromRequest(req),
currentVersion,
ghesContext: {
currentVersion,
latestPatch,
latestRelease,
prevRelease: req.context.prevRelease || '',
nextRelease: req.context.nextRelease || '',
releaseNotes: req.context.releaseNotes,
releases: req.context.releases,
message: {
ghes_release_notes_upgrade_patch_only: liquid.parseAndRenderSync(
req.context.site.data.ui.header.notices.ghes_release_notes_upgrade_patch_only,
{ latestPatch, latestRelease }
),
ghes_release_notes_upgrade_release_only: liquid.parseAndRenderSync(
req.context.site.data.ui.header.notices.ghes_release_notes_upgrade_release_only,
{ latestPatch, latestRelease }
),
ghes_release_notes_upgrade_patch_and_release: liquid.parseAndRenderSync(
req.context.site.data.ui.header.notices.ghes_release_notes_upgrade_patch_and_release,
{ latestPatch, latestRelease }
),
},
},
ghaeContext: {
currentVersion,
releaseNotes: req.context.releaseNotes,
releases: req.context.releases,
},
},
}
}

View File

@@ -15,6 +15,10 @@ ul.release-notes-list li.release-notes-list-item {
.release-notes-section-heading { .release-notes-section-heading {
font-size: 15px !important; font-size: 15px !important;
scroll-margin-top: 280px !important;
@include breakpoint(sm) {
scroll-margin-top: 200px !important;
}
} }
details[open].release-notes-version-picker details[open].release-notes-version-picker
@@ -36,7 +40,7 @@ $colors-list: (
security_fixes: var(--color-auto-pink-5), security_fixes: var(--color-auto-pink-5),
changes: var(--color-auto-green-5), changes: var(--color-auto-green-5),
deprecations: var(--color-auto-purple-5), deprecations: var(--color-auto-purple-5),
backups: var(--color-auto-orange-5) backups: var(--color-auto-orange-5),
); );
@each $key, $val in $colors-list { @each $key, $val in $colors-list {

View File

@@ -15,6 +15,7 @@
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve", "jsx": "preserve",
"baseUrl": ".", "baseUrl": ".",
"allowSyntheticDefaultImports": true
}, },
"exclude": ["node_modules"], "exclude": ["node_modules"],
"include": ["*.d.ts", "**/*.ts", "**/*.tsx"] "include": ["*.d.ts", "**/*.ts", "**/*.tsx"]