1
0
mirror of synced 2025-12-19 18:10:59 -05:00

Permissions redesign (#48873)

This commit is contained in:
Rachael Sewell
2024-02-20 14:36:36 -08:00
committed by GitHub
parent 664c779482
commit 4cd427842a
14 changed files with 100 additions and 67 deletions

View File

@@ -47,7 +47,7 @@ pages:
miniToc: In this article
all_enterprise_releases: All Enterprise Server releases
about_versions: About versions
permissions_statement: Who can use this feature
permissions_callout_title: Who can use this feature?
video_from_transcript: See video for this transcript
support:
still_need_help: Still need help?

View File

@@ -7,7 +7,6 @@ import { ArticleGridLayout } from 'src/frame/components/article/ArticleGridLayou
import { MiniTocs } from 'src/frame/components/ui/MiniTocs'
import { useAutomatedPageContext } from 'src/automated-pipelines/components/AutomatedPageContext'
import { ClientSideHighlight } from 'src/frame/components/ClientSideHighlight'
import { Alert } from 'src/frame/components/ui/Alert'
import { Breadcrumbs } from 'src/frame/components/page-header/Breadcrumbs'
type Props = {
@@ -40,9 +39,7 @@ export const AutomatedPage = ({ children }: Props) => {
</Lead>
)}
{permissions && <PermissionsStatement permissions={permissions} />}
{product && <Alert className="mb-4" html={product} />}
<PermissionsStatement permissions={permissions} product={product} />
</>
}
toc={miniTocItems.length > 1 && <MiniTocs miniTocItems={miniTocItems} />}

View File

@@ -15,6 +15,7 @@ children:
- /for-playwright
- /html-short-title
- /page-with-callout
- /page-with-permissions-and-product-callout
- /table-with-ifversions
- /code-snippet-with-hashbang
---

View File

@@ -0,0 +1,17 @@
---
title: Page with permissions and product callout
shortTitle: Callout page
intro: A very short intro
permissions: This is a permission callout
product: '{% data reusables.gated-features.not-for-ghes %}'
versions:
fpt: '*'
ghes: '*'
ghec: '*'
---
## Heading
Note that this page uses the `product` and `permissions` frontmatter property. So it should
result in a call out box rendered with two messages. But only if the version is *not*
Enterprise Server.

View File

@@ -47,7 +47,7 @@ pages:
miniToc: In this article
all_enterprise_releases: All Enterprise Server releases
about_versions: About versions
permissions_statement: Who can use this feature
permissions_callout_title: Who can use this feature?
video_from_transcript: See video for this transcript
support:
still_need_help: Still need help?

View File

@@ -1,26 +0,0 @@
import { getDOM } from '#src/tests/helpers/e2etest.js'
describe('alerts', () => {
test('article page', async () => {
const $ = await getDOM('/get-started/foo/page-with-callout')
const callout = $('[data-testid=alert] div')
expect(callout.html()).toBe('<p>Callout for HubGit Pages</p>')
})
test('callout disappears depend on Liquid inside it', async () => {
// This page has `product:` property which is a piece of Liquid
// which makes it so that the rendered output of that becomes
// an empty string.
// This test tests that alert is not rendered if its output
// "exits" but is empty.
const $ = await getDOM('/enterprise-server@latest/get-started/foo/page-with-callout')
const callout = $('[data-testid=alert]')
expect(callout.length).toBe(0)
})
test('toc landing page', async () => {
const $ = await getDOM('/actions/category')
const callout = $('[data-testid=alert] div')
expect(callout.html()).toBe('<p>This is the callout text</p>')
})
})

View File

@@ -8,17 +8,6 @@ describe('markdown rendering', () => {
expect(html).toMatch('<code>syntax</code>')
expect(html).toMatch('<em>HubGit</em>')
})
test('page with permission frontmatter', async () => {
const $ = await getDOM('/get-started/markdown/permissions')
const html = $('[data-testid="permissions-statement"]').html()
// part of the UI
expect(html).toMatch('Who can use this feature')
// Markdown
expect(html).toMatch('<strong>admin</strong>')
// Liquid
expect(html).toMatch('HubGit Pages site')
})
})
describe('alerts', () => {

View File

@@ -0,0 +1,48 @@
import { getDOM } from '#src/tests/helpers/e2etest.js'
describe('permission statements', () => {
test('article page product statement', async () => {
const $ = await getDOM('/get-started/foo/page-with-callout')
const callout = $('[data-testid=product-statement] div')
expect(callout.html()).toBe('<p>Callout for HubGit Pages</p>')
})
test('callout disappears depend on Liquid inside it', async () => {
// This page has `product:` property which is a piece of Liquid
// which makes it so that the rendered output of that becomes
// an empty string.
// This test tests that alert is not rendered if its output
// "exits" but is empty.
const $ = await getDOM('/enterprise-server@latest/get-started/foo/page-with-callout')
const callout = $('[data-testid=product-statement]')
expect(callout.length).toBe(0)
})
test('toc landing page', async () => {
const $ = await getDOM('/actions/category')
const callout = $('[data-testid=product-statement] div')
expect(callout.html()).toBe('<p>This is the callout text</p>')
})
test('page with permission frontmatter', async () => {
const $ = await getDOM('/get-started/markdown/permissions')
const html = $('[data-testid=permissions-statement] div').html()
// Markdown
expect(html).toMatch('<strong>admin</strong>')
// Liquid
expect(html).toMatch('HubGit Pages site')
})
test('page with permission frontmatter and product statement', async () => {
const $ = await getDOM('/get-started/foo/page-with-permissions-and-product-callout.md')
const html = $('[data-testid=permissions-callout] div').html()
// part of the UI
expect(html).toMatch('Who can use this feature')
const permission = $('[data-testid=permissions-statement] div')
expect(permission.html()).toBe('<p>This is a permission callout</p>')
const product = $('[data-testid=product-statement] div')
expect(product.html()).toBe('<p>Callout for HubGit Pages</p>')
})
})

View File

@@ -25,7 +25,7 @@ export const ArticleGridLayout = ({
<Box className={cx(styles.containerBox, className)}>
{topper && <Box gridArea="topper">{topper}</Box>}
{intro && (
<Box id="article-intro" gridArea="intro" className="f4">
<Box id="article-intro" gridArea="intro" className="f4 pb-4">
{intro}
</Box>
)}

View File

@@ -3,7 +3,6 @@ import dynamic from 'next/dynamic'
import cx from 'classnames'
import { LinkExternalIcon } from '@primer/octicons-react'
import { Alert } from 'src/frame/components/ui/Alert'
import { DefaultLayout } from 'src/frame/components/DefaultLayout'
import { ArticleTitle } from 'src/frame/components/article/ArticleTitle'
import { useArticleContext } from 'src/frame/components/context/ArticleContext'
@@ -62,12 +61,10 @@ export const ArticlePage = () => {
const introCalloutsProp = (
<>
{permissions && <PermissionsStatement permissions={permissions} />}
<PermissionsStatement permissions={permissions} product={product} />
{includesPlatformSpecificContent && <PlatformPicker />}
{includesToolSpecificContent && <ToolPicker />}
{product && <Alert className="mb-4" html={product} />}
</>
)

View File

@@ -1,3 +0,0 @@
.permissions_statement {
border-left: 0.25rem solid var(--color-border-muted);
}

View File

@@ -1,22 +1,35 @@
import cx from 'classnames'
import { Box } from '@primer/react'
import { PersonIcon, BriefcaseIcon } from '@primer/octicons-react'
import styles from './PermissionsStatement.module.scss'
import { useTranslation } from 'src/languages/components/useTranslation'
type Props = {
permissions: string
product?: string
permissions?: string
}
export function PermissionsStatement({ permissions }: Props) {
export function PermissionsStatement({ product, permissions }: Props) {
const { t } = useTranslation('pages')
if (!permissions && !product) return null
return (
<div
className={cx(styles.permissions_statement, 'pl-3 my-4')}
data-search="hide"
data-testid="permissions-statement"
>
<div className="text-bold pr-2">{t('permissions_statement')}</div>
<div dangerouslySetInnerHTML={{ __html: permissions }} />
</div>
<Box sx={{ borderRadius: 10, borderStyle: 'solid', borderColor: 'border.default', p: 3 }}>
<div data-search="hide" data-testid="permissions-callout">
<div className="mb-3 d-inline-block">
<h2 className="f4">{t('permissions_callout_title')}</h2>
</div>
{permissions && (
<div className="d-flex" data-testid="permissions-statement">
<PersonIcon className="mt-1" />
<div className="pl-2" dangerouslySetInnerHTML={{ __html: permissions }} />
</div>
)}
{product && (
<div className="d-flex" data-testid="product-statement">
<BriefcaseIcon className="mt-1" />
<div className="pl-2" dangerouslySetInnerHTML={{ __html: product }} />
</div>
)}
</div>
</Box>
)
}

View File

@@ -9,7 +9,7 @@ import { ArticleTitle } from 'src/frame/components/article/ArticleTitle'
import { MarkdownContent } from 'src/frame/components/ui/MarkdownContent'
import { ArticleList } from 'src/landings/components/ArticleList'
import { ArticleGridLayout } from 'src/frame/components/article/ArticleGridLayout'
import { Alert } from 'src/frame/components/ui/Alert'
import { PermissionsStatement } from 'src/frame/components/ui/PermissionsStatement'
import { Lead } from 'src/frame/components/ui/Lead'
import { LearningTrackNav } from 'src/learning-track/components/article/LearningTrackNav'
import { ClientSideRedirects } from 'src/rest/components/ClientSideRedirects'
@@ -46,7 +46,7 @@ export const TocLanding = () => {
{intro && <Lead data-search="lead">{intro}</Lead>}
{productCallout && <Alert html={productCallout} />}
<PermissionsStatement product={productCallout} />
<div className="border-bottom border-xl-0 pb-4 mb-5 pb-xl-2 mb-xl-2" />

View File

@@ -16,7 +16,7 @@ export type StructuredContentT = {
}
export const RestReferencePage = ({ restOperations }: StructuredContentT) => {
const { title, intro, renderedPage, permissions } = useAutomatedPageContext()
const { title, intro, renderedPage, permissions, product } = useAutomatedPageContext()
// Scrollable code blocks in our REST API docs and elsewhere aren't accessible
// via keyboard navigation without setting tabindex="0". But we don't want to set
@@ -54,7 +54,7 @@ export const RestReferencePage = ({ restOperations }: StructuredContentT) => {
</Lead>
)}
{permissions && <PermissionsStatement permissions={permissions} />}
<PermissionsStatement permissions={permissions} product={product} />
{renderedPage && <MarkdownContent className="pt-3 pb-4">{renderedPage}</MarkdownContent>}
{restOperations.length > 0 && (