Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add option to display verb in webhooks #1994

Merged
merged 5 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ You can use all of the following options with the standalone version of the <red
* **summary-only**: displays a summary in the sidebar navigation item. (**default**)
* **path-only**: displays a path in the sidebar navigation item.
* **id-only**: displays the operation id with a fallback to the path in the sidebar navigation item.
* `showWebhookVerb` - when set to `true`, shows the HTTP request method for webhooks in operations and in the sidebar.

### `<redoc>` theme object
* `spacing`
Expand Down
4 changes: 2 additions & 2 deletions cli/__test__/build/configRedoc/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { readFileSync } from 'fs';
describe('build', () => {
it('should use .redocly.yaml', () => {
const r = spawnSync(
'node',
['../../../index.js', 'build', ' ../../../../demo/openapi.yaml', '--output=redocTest.html'],
'ts-node',
['../../../index.ts', 'build', ' ../../../../demo/openapi.yaml', '--output=redocTest.html'],
{
cwd: __dirname,
shell: true,
Expand Down
4 changes: 2 additions & 2 deletions cli/__test__/build/configRedoc/inlineOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { readFileSync } from 'fs';
describe('build with inline options', () => {
it('should use inline options and ignore .redocly.yaml', () => {
const r = spawnSync(
'node',
'ts-node',
[
'../../../index.js',
'../../../index.ts',
'build',
' ../../../../demo/openapi.yaml',
'--options.disableSearch="false" ',
Expand Down
88 changes: 44 additions & 44 deletions src/components/Operation/Operation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,48 +27,48 @@ export interface OperationProps {
operation: OperationModel;
}

@observer
export class Operation extends React.Component<OperationProps> {
render() {
const { operation } = this.props;

const { name: summary, description, deprecated, externalDocs, isWebhook } = operation;
const hasDescription = !!(description || externalDocs);

return (
<OptionsContext.Consumer>
{options => (
<Row {...{ [SECTION_ATTR]: operation.operationHash }} id={operation.operationHash}>
<MiddlePanel>
<H2>
<ShareLink to={operation.id} />
{summary} {deprecated && <Badge type="warning"> Deprecated </Badge>}
{isWebhook && <Badge type="primary"> Webhook </Badge>}
</H2>
{options.pathInMiddlePanel && !isWebhook && (
<Endpoint operation={operation} inverted={true} />
export const Operation = observer(({ operation }: OperationProps): JSX.Element => {
const { name: summary, description, deprecated, externalDocs, isWebhook, httpVerb } = operation;
const hasDescription = !!(description || externalDocs);
const { showWebhookVerb } = React.useContext(OptionsContext);
return (
<OptionsContext.Consumer>
{options => (
<Row {...{ [SECTION_ATTR]: operation.operationHash }} id={operation.operationHash}>
<MiddlePanel>
<H2>
<ShareLink to={operation.id} />
{summary} {deprecated && <Badge type="warning"> Deprecated </Badge>}
{isWebhook && (
<Badge type="primary">
{' '}
Webhook {showWebhookVerb && httpVerb && '| ' + httpVerb.toUpperCase()}
</Badge>
)}
{hasDescription && (
<Description>
{description !== undefined && <Markdown source={description} />}
{externalDocs && <ExternalDocumentation externalDocs={externalDocs} />}
</Description>
)}
<Extensions extensions={operation.extensions} />
<SecurityRequirements securities={operation.security} />
<Parameters parameters={operation.parameters} body={operation.requestBody} />
<ResponsesList responses={operation.responses} />
<CallbacksList callbacks={operation.callbacks} />
</MiddlePanel>
<DarkRightPanel>
{!options.pathInMiddlePanel && !isWebhook && <Endpoint operation={operation} />}
<RequestSamples operation={operation} />
<ResponseSamples operation={operation} />
<CallbackSamples callbacks={operation.callbacks} />
</DarkRightPanel>
</Row>
)}
</OptionsContext.Consumer>
);
}
}
</H2>
{options.pathInMiddlePanel && !isWebhook && (
<Endpoint operation={operation} inverted={true} />
)}
{hasDescription && (
<Description>
{description !== undefined && <Markdown source={description} />}
{externalDocs && <ExternalDocumentation externalDocs={externalDocs} />}
</Description>
)}
<Extensions extensions={operation.extensions} />
<SecurityRequirements securities={operation.security} />
<Parameters parameters={operation.parameters} body={operation.requestBody} />
<ResponsesList responses={operation.responses} />
<CallbacksList callbacks={operation.callbacks} />
</MiddlePanel>
<DarkRightPanel>
{!options.pathInMiddlePanel && !isWebhook && <Endpoint operation={operation} />}
<RequestSamples operation={operation} />
<ResponseSamples operation={operation} />
<CallbackSamples callbacks={operation.callbacks} />
</DarkRightPanel>
</Row>
)}
</OptionsContext.Consumer>
);
});
56 changes: 27 additions & 29 deletions src/components/SideMenu/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { MenuItems } from './MenuItems';
import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements';
import { l } from '../../services/Labels';
import { scrollIntoViewIfNeeded } from '../../utils';
import { OptionsContext } from '../OptionsProvider';

export interface MenuItemProps {
item: IMenuItem;
onActivate?: (item: IMenuItem) => void;
withoutChildren?: boolean;
children?: React.ReactChild;
}

@observer
Expand Down Expand Up @@ -70,37 +72,33 @@ export class MenuItem extends React.Component<MenuItemProps> {

export interface OperationMenuItemContentProps {
item: OperationModel;
children?: React.ReactChild;
}

@observer
export class OperationMenuItemContent extends React.Component<OperationMenuItemContentProps> {
ref = React.createRef<HTMLLabelElement>();
export const OperationMenuItemContent = observer((props: OperationMenuItemContentProps) => {
const { item } = props;
const ref = React.createRef<HTMLLabelElement>();
const { showWebhookVerb } = React.useContext(OptionsContext);

componentDidUpdate() {
if (this.props.item.active && this.ref.current) {
scrollIntoViewIfNeeded(this.ref.current);
React.useEffect(() => {
if (props.item.active && ref.current) {
scrollIntoViewIfNeeded(ref.current);
}
}
}, [props.item.active, ref]);

render() {
const { item } = this.props;
return (
<MenuItemLabel
depth={item.depth}
active={item.active}
deprecated={item.deprecated}
ref={this.ref}
>
{item.isWebhook ? (
<OperationBadge type="hook">{l('webhook')}</OperationBadge>
) : (
<OperationBadge type={item.httpVerb}>{shortenHTTPVerb(item.httpVerb)}</OperationBadge>
)}
<MenuItemTitle width="calc(100% - 38px)">
{item.sidebarLabel}
{this.props.children}
</MenuItemTitle>
</MenuItemLabel>
);
}
}
return (
<MenuItemLabel depth={item.depth} active={item.active} deprecated={item.deprecated} ref={ref}>
{item.isWebhook ? (
<OperationBadge type="hook">
{showWebhookVerb ? item.httpVerb : l('webhook')}
</OperationBadge>
) : (
<OperationBadge type={item.httpVerb}>{shortenHTTPVerb(item.httpVerb)}</OperationBadge>
)}
<MenuItemTitle width="calc(100% - 38px)">
{item.sidebarLabel}
{props.children}
</MenuItemTitle>
</MenuItemLabel>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -360,6 +361,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -589,6 +591,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -885,6 +888,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -1139,6 +1143,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -1368,6 +1373,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -1620,6 +1626,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -1913,6 +1920,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -2167,6 +2175,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down Expand Up @@ -2396,6 +2405,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"scrollYOffset": [Function],
"showExtensions": false,
"showObjectSchemaExamples": false,
"showWebhookVerb": false,
"sideNavStyle": "summary-only",
"simpleOneOfTypeLabel": false,
"sortEnumValuesAlphabetically": false,
Expand Down
3 changes: 3 additions & 0 deletions src/services/RedocNormalizedOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export interface RedocRawOptions {
nonce?: string;
hideFab?: boolean;
minCharacterLengthToInitSearch?: number;
showWebhookVerb?: boolean;
}

export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
Expand Down Expand Up @@ -257,6 +258,7 @@ export class RedocNormalizedOptions {
generatedPayloadSamplesMaxDepth: number;
hideFab: boolean;
minCharacterLengthToInitSearch: number;
showWebhookVerb: boolean;

nonce?: string;

Expand Down Expand Up @@ -334,5 +336,6 @@ export class RedocNormalizedOptions {
this.nonce = raw.nonce;
this.hideFab = argValueToBoolean(raw.hideFab);
this.minCharacterLengthToInitSearch = argValueToNumber(raw.minCharacterLengthToInitSearch) || 3;
this.showWebhookVerb = argValueToBoolean(raw.showWebhookVerb);
}
}