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

Move more files into automated pipelines directory (#37415)

This commit is contained in:
Kevin Heis
2023-06-01 10:50:58 -07:00
committed by GitHub
parent ef8381943a
commit 85675f9f81
21 changed files with 24 additions and 21 deletions

View File

@@ -0,0 +1,58 @@
import { DefaultLayout } from 'components/DefaultLayout'
import { ArticleTitle } from 'components/article/ArticleTitle'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import { Lead } from 'components/ui/Lead'
import { PermissionsStatement } from 'components/ui/PermissionsStatement'
import { ArticleGridLayout } from '../../../components/article/ArticleGridLayout'
import { MiniTocs } from 'components/ui/MiniTocs'
import { useAutomatedPageContext } from 'src/automated-pipelines/components/AutomatedPageContext'
import { ClientSideHighlight } from 'components/ClientSideHighlight'
import { Callout } from 'components/ui/Callout'
type Props = {
children: React.ReactNode
}
export const AutomatedPage = ({ children }: Props) => {
const { title, intro, renderedPage, miniTocItems, product, permissions } =
useAutomatedPageContext()
return (
<DefaultLayout>
<ClientSideHighlight />
<div className="container-xl px-3 px-md-6 my-4">
<ArticleGridLayout
topper={<ArticleTitle>{title}</ArticleTitle>}
intro={
<>
{intro && (
<Lead data-testid="lead" data-search="lead">
{intro}
</Lead>
)}
{permissions && <PermissionsStatement permissions={permissions} />}
{product && (
<Callout
variant="success"
className="mb-4"
dangerouslySetInnerHTML={{ __html: product }}
/>
)}
</>
}
toc={miniTocItems.length > 1 && <MiniTocs miniTocItems={miniTocItems} />}
>
<div id="article-contents">
{renderedPage && (
<MarkdownContent className="pt-3 pb-4">{renderedPage}</MarkdownContent>
)}
{children && <MarkdownContent className="pt-3 pb-4">{children}</MarkdownContent>}
</div>
</ArticleGridLayout>
</div>
</DefaultLayout>
)
}

View File

@@ -0,0 +1,38 @@
import { createContext, useContext } from 'react'
import type { MiniTocItem } from 'components/context/ArticleContext'
export type AutomatedPageContextT = {
title: string
intro: string
renderedPage: string | JSX.Element[]
miniTocItems: Array<MiniTocItem>
product?: string
permissions?: string
}
export const AutomatedPageContext = createContext<AutomatedPageContextT | null>(null)
export const useAutomatedPageContext = (): AutomatedPageContextT => {
const context = useContext(AutomatedPageContext)
if (!context) {
throw new Error(
'"useAutomatedPageContext" may only be used inside "AutomatedPageContext.Provider"'
)
}
return context
}
export const getAutomatedPageContextFromRequest = (req: any): AutomatedPageContextT => {
const page = req.context.page
return {
title: page.title,
intro: page.intro,
renderedPage: req.context.renderedPage || '',
miniTocItems: req.context.miniTocItems || [],
product: page.product || '',
permissions: page.permissions || '',
}
}

View File

@@ -0,0 +1,21 @@
.childBodyParametersRows {
details tr {
border-top: none;
}
// Remove any default markdown article padding for property cells
details tr td {
padding-bottom: 0.25rem;
}
// Set the left border for in the nested property tables. Also need to override
// a default markdown file style that sets a table's font size based on
// percentage which would cause the table font size to shrink more and more
// as the properties nested more and more.
td {
table {
border-left: 4px solid var(--color-border-muted);
font-size: inherit !important;
}
}
}

View File

@@ -0,0 +1,64 @@
import cx from 'classnames'
import { useTranslation } from 'components/hooks/useTranslation'
import { ParameterRow } from './ParameterRow'
import type { ChildParameter } from './types'
import styles from './ChildBodyParametersRows.module.scss'
type Props = {
open: boolean
slug: string
childParamsGroups: ChildParameter[]
parentName: string
parentType: string
oneOfObject?: boolean
}
export function ChildBodyParametersRows({
open,
slug,
parentName,
parentType,
childParamsGroups,
oneOfObject = false,
}: Props) {
const { t } = useTranslation(['parameter_table', 'products'])
return (
<tr className={cx(styles.childBodyParametersRows, 'color-bg-subtle border-top-0')}>
<td colSpan={4} className="has-nested-table">
<details className="box px-3 ml-1 mb-0" open={open}>
<summary role="button" aria-expanded="false" className="mb-2 keyboard-focus">
{oneOfObject ? (
<span id={`${slug}-${parentName}-${parentType}`}>Can be one of these objects:</span>
) : (
<span id={`${slug}-${parentName}-${parentType}`}>
Properties of <code>{parentName}</code>
</span>
)}
</summary>
<table id={`${parentName}-object`} className="mb-4 color-bg-subtle">
<thead className="visually-hidden">
<tr>
<th>{`${t('name')}, ${t('type')}, ${t('description')}`}</th>
</tr>
</thead>
<tbody>
{childParamsGroups.map((childParam, index) => {
return (
<ParameterRow
rowParams={childParam}
slug={slug}
isChild={true}
key={`${childParam.name}-${index}`}
rowIndex={index}
/>
)
})}
</tbody>
</table>
</details>
</td>
</tr>
)
}

View File

@@ -0,0 +1,184 @@
import cx from 'classnames'
import { useTranslation } from 'components/hooks/useTranslation'
import { KeyboardEventHandler } from 'react'
import { ChildBodyParametersRows } from './ChildBodyParametersRows'
import type { ChildParameter } from './types'
type Props = {
rowParams: ChildParameter
slug: string
numPreviews?: number
isChild?: boolean
rowIndex?: number
bodyParamExpandCallback?: KeyboardEventHandler<HTMLButtonElement> | undefined
clickedBodyParameterName?: string | undefined
}
// Webhooks have these same properties in common that we describe separately in its
// own section on the webhooks page:
//
// https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#webhook-payload-object-common-properties
//
// Since there's more details for these particular properties, we chose not
// show their child properties for each webhook and we also don't grab this
// information from the schema.
//
// We use this list of common properties to make sure we don't try and request
// the child properties for these specific properties.
const NO_CHILD_WEBHOOK_PROPERTIES = [
'action',
'enterprise',
'installation',
'organization',
'repository',
'sender',
]
export function ParameterRow({
rowParams,
slug,
numPreviews = 0,
isChild = false,
rowIndex = 0,
bodyParamExpandCallback = undefined,
clickedBodyParameterName = undefined,
}: Props) {
const { t } = useTranslation(['parameter_table', 'products'])
// This will be true if `rowParams` does not have a key called `default`
// and it will be true if it does and its actual value is `undefined`.
const hasDefault = rowParams.default !== undefined
return (
<>
<tr className={`${isChild ? 'color-bg-subtle' : ''}`}>
<td className={`${isChild ? 'px-3' : ''}`}>
<div
className={cx(
'pl-0 pt-1 pr-1 pb-1',
`${rowIndex > 0 && isChild ? 'pt-3 border-top color-border-muted' : ''}`
)}
>
<div>
{rowParams.name ? (
<>
<code className={`text-bold f5`}>{rowParams.name}</code>
{/* This whitespace is important otherwise, when the CSS is
ignored, the plain text becomes `foobar` if the HTML
was `<code>foo</code><span>bar</span>`.
*/}{' '}
<span className="color-fg-muted pl-2 f5">
{Array.isArray(rowParams.type) ? rowParams.type.join(' or ') : rowParams.type}
</span>
{/* Ditto about the important explicit whitespace */}{' '}
{rowParams.isRequired ? (
<span className="color-fg-attention f5 pl-3">{t('required')}</span>
) : null}
</>
) : (
<>
<span className="color-fg-muted pl-1 f5">
{Array.isArray(rowParams.type) ? rowParams.type.join(' or ') : rowParams.type}
</span>
{/* Ditto about the important explicit whitespace */}{' '}
{rowParams.isRequired ? (
<span className="color-fg-attention f5 pl-3">{t('required')}</span>
) : null}
</>
)}
</div>
<div className={cx('pl-1 f5', `${rowParams.description ? 'pt-2' : 'pt-0'}`)}>
<div dangerouslySetInnerHTML={{ __html: rowParams.description }} />
{numPreviews > 0 && (
<a href={`#${slug}-preview-notices`} className="d-inline">
{numPreviews > 1 ? ` ${t('see_preview_notices')}` : ` ${t('see_preview_notice')}`}
</a>
)}
<div className={cx(`${hasDefault || rowParams.enum ? 'pt-2' : 'pt-0'}`)}>
{hasDefault && (
<p>
<span>{t('default')}: </span>
<code>
{typeof rowParams.default === 'string'
? // In the schema, the default value for strings can
// potentially be the empty string so we handle this case
// in particular by rendering it as "". Otherwise we would
// display an empty code block which could be confusing.
rowParams.default || '""'
: JSON.stringify(rowParams.default)}
</code>
</p>
)}
{rowParams.enum && rowParams.enum.length && (
<p>
<span>
{rowParams.enum.length === 1
? t('single_enum_description')
: t('enum_description_title')}
:{' '}
</span>
{rowParams.enum.map((item, index, array) => (
<span key={`${item}${index}`}>
<code>{item === null ? <i>null</i> : item}</code>
{index !== array.length - 1 && ','}{' '}
</span>
))}
</p>
)}
</div>
</div>
</div>
</td>
</tr>
{rowParams.childParamsGroups && rowParams.childParamsGroups.length > 0 && (
<ChildBodyParametersRows
slug={slug}
parentName={rowParams.name}
parentType={Array.isArray(rowParams.type) ? rowParams.type.join(' or ') : rowParams.type}
childParamsGroups={rowParams.childParamsGroups}
open={rowParams.name === clickedBodyParameterName}
oneOfObject={rowParams.oneOfObject}
/>
)}
{/* These conditions tell us:
1. the param is an object or array AND:
2. the param has no child param groups AND:
3. the param isn't one of the common webhook properties
If all these are true, then that means we haven't yet loaded the
nested parameters so we show a stub <details> element that triggers
an API request to get the nested parameter data.
*/}
{rowParams.type &&
(rowParams.type === 'object' || rowParams.type.includes('array of')) &&
rowParams.childParamsGroups &&
rowParams.childParamsGroups.length === 0 &&
!NO_CHILD_WEBHOOK_PROPERTIES.includes(rowParams.name) ? (
<tr className="border-top-0">
<td colSpan={4} className="has-nested-table">
<details
data-nested-param-id={rowParams.name}
className="box px-3 ml-1 mb-0"
onToggle={bodyParamExpandCallback}
>
<summary role="button" aria-expanded="false" className="mb-2 keyboard-focus">
{rowParams.oneOfObject ? (
<span id={`${slug}-${rowParams.name}`}>
Can be one of these objects: <code>{rowParams.name}</code>
</span>
) : (
<span id={`${slug}-${rowParams.name}`}>
Properties of <code>{rowParams.name}</code>
</span>
)}
</summary>
</details>
</td>
</tr>
) : null}
</>
)
}

View File

@@ -0,0 +1,26 @@
.parameterTable {
// this is for the child parameter table row that contains the top level
// properties details toggle element because we want it to match the
// background color of the top level parameter rows. We need the !important
// because the child parameter rows (the nested expanded properties) otherwise
// have the same background color.
& > tbody > tr {
background: var(--color-canvas-default) !important;
}
// also for the top level child parameter table row, we want the details toggle
// to align with the top level parameter rows. Child parameter rows have some
// left padding so they can indent as they nest but we don't want that in
// this case. We need the !important to override general default markdown
// article styling.
& > tbody > tr > td > details {
padding-left: 0px !important;
margin-bottom: 4px !important;
}
& > tbody > tr > td > * {
width: auto;
display: block;
word-break: break-word;
}
}

View File

@@ -0,0 +1,159 @@
import cx from 'classnames'
import { useTranslation } from 'components/hooks/useTranslation'
import { KeyboardEventHandler } from 'react'
import { ParameterRow } from './ParameterRow'
import { BodyParameter, ChildParameter, Parameter } from './types'
import styles from './ParameterTable.module.scss'
type Props = {
slug: string
numPreviews?: number
heading?: string
headers?: Array<ChildParameter>
parameters?: Array<Parameter>
bodyParameters: Array<BodyParameter>
bodyParamExpandCallback?: KeyboardEventHandler<HTMLButtonElement> | undefined
clickedBodyParameterName?: string | undefined
}
export function ParameterTable({
slug,
numPreviews = 0,
heading = '',
headers = [],
parameters = [],
bodyParameters,
bodyParamExpandCallback = undefined,
clickedBodyParameterName = '',
}: Props) {
const { t } = useTranslation(['parameter_table', 'products'])
const queryParams = parameters.filter((param) => param.in === 'query')
const pathParams = parameters.filter((param) => param.in === 'path')
return (
<>
{heading && (
<h3 className="mt-4 mb-3 pt-3 h4" id={`${slug}--parameters`}>
<a href={`#${slug}--parameters`}>{heading}</a>
</h3>
)}
<table
className={cx(styles.parameterTable)}
summary="Column one has the type of parameter and the other columns show the name, type, and description of the parameters"
>
<thead>
<tr>
<th
id="header"
scope="col"
className={cx(headers.length === 0 && 'visually-hidden', 'text-bold pl-0')}
>
{t('headers')}
</th>
</tr>
<tr className="visually-hidden">
<th scope="col">{`${t('name')}, ${t('type')}, ${t('description')}`}</th>
</tr>
</thead>
<tbody>
{headers.length > 0 && (
<>
{headers.map((header, index) => (
<ParameterRow
rowParams={header}
slug={slug}
numPreviews={numPreviews}
key={`${index}-${header.name}`}
/>
))}
</>
)}
{pathParams.length > 0 && (
<>
<tr className="border-top-0">
<th className="text-bold pl-0 border-top-0" scope="colgroup">
{t('path')}
</th>
</tr>
<tr className="visually-hidden">
<th scope="colgroup">{`${t('name')}, ${t('type')}, ${t('description')}`}</th>
</tr>
{pathParams.map((param, index) => (
<ParameterRow
rowParams={{
name: param.name,
type: param.schema.type,
description: param.description,
isRequired: param.required,
default: param.schema.default,
enum: param.schema.enum,
}}
slug={slug}
key={`${index}-${param}`}
/>
))}
</>
)}
{queryParams.length > 0 && (
<>
<tr className="border-top-0">
<th className="text-bold pl-0" scope="colgroup">
{t('query')}
</th>
</tr>
<tr className="visually-hidden">
<th scope="colgroup">{`${t('name')}, ${t('type')}, ${t('description')}`}</th>
</tr>
{queryParams.map((param, index) => (
<ParameterRow
rowParams={{
name: param.name,
type: param.schema.type,
description: param.description,
isRequired: param.required,
default: param.schema.default,
enum: param.schema.enum,
}}
slug={slug}
key={`${index}-${param}`}
/>
))}
</>
)}
{bodyParameters.length > 0 && (
<>
<tr className="border-top-0">
{/* webhooks don't have a 'Parameters' table heading text so
we adjust the size of the body params heading in that case */}
<th scope="colgroup" className={cx(heading ? 'text-bold' : 'h4', 'pl-0')}>
{t('body')}
</th>
</tr>
<tr className="visually-hidden">
<th scope="colgroup">{`${t('name')}, ${t('type')}, ${t('description')}`}</th>
</tr>
{bodyParameters.map((param, index) => (
<ParameterRow
bodyParamExpandCallback={bodyParamExpandCallback}
clickedBodyParameterName={clickedBodyParameterName}
rowParams={param}
slug={slug}
key={`${index}-${param}`}
/>
))}
</>
)}
</tbody>
</table>
</>
)
}

View File

@@ -0,0 +1,33 @@
export interface Parameter {
in: string
name: string
description: string
required: boolean
schema: {
type: string
default?: string
enum?: Array<string>
}
}
export interface BodyParameter {
in: string
name: string
description: string
type: string
isRequired?: boolean
default?: string
enum?: Array<string>
childParamsGroups?: Array<ChildParameter>
}
export interface ChildParameter {
name: string
description: string
type: string
isRequired?: boolean
enum?: Array<string | null>
default?: string | boolean | number | undefined | string[]
childParamsGroups?: ChildParameter[]
oneOfObject?: boolean
}