mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-08 14:14:56 +03:00
support for a specific vendor extension and toggling content panel area by adding additional option to redoc standalone
This commit is contained in:
parent
965778d3b0
commit
1eae317893
|
@ -17,14 +17,14 @@ info:
|
|||
It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo)
|
||||
tool and [ReDoc](https://github.com/Rebilly/ReDoc) documentation. In addition to standard
|
||||
OpenAPI syntax we use a few [vendor extensions](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md).
|
||||
|
||||
|
||||
# OpenAPI Specification
|
||||
This API is documented in **OpenAPI format** and is based on
|
||||
[Petstore sample](http://petstore.swagger.io/) provided by [swagger.io](http://swagger.io) team.
|
||||
It was **extended** to illustrate features of [generator-openapi-repo](https://github.com/Rebilly/generator-openapi-repo)
|
||||
tool and [ReDoc](https://github.com/Rebilly/ReDoc) documentation. In addition to standard
|
||||
OpenAPI syntax we use a few [vendor extensions](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md).
|
||||
|
||||
|
||||
# Cross-Origin Resource Sharing
|
||||
This API features Cross-Origin Resource Sharing (CORS) implemented in compliance with [W3C spec](https://www.w3.org/TR/cors/).
|
||||
And that allows cross-domain communication from the browser.
|
||||
|
@ -38,8 +38,9 @@ info:
|
|||
OAuth2 - an open protocol to allow secure authorization in a simple
|
||||
and standard method from web, mobile and desktop applications.
|
||||
|
||||
<security-definitions />
|
||||
<security-definitions />
|
||||
|
||||
x-opentext-other: foo
|
||||
version: 1.0.0
|
||||
title: Swagger Petstore
|
||||
termsOfService: 'http://swagger.io/terms/'
|
||||
|
@ -82,6 +83,7 @@ paths:
|
|||
type: integer
|
||||
format: int64
|
||||
post:
|
||||
x-opentext-other: bar
|
||||
tags:
|
||||
- pet
|
||||
summary: Add a new pet to the store
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { StyledLink } from '../../../src/common-elements';
|
||||
|
||||
import { AppStore } from '../../services/AppStore';
|
||||
import { Constants } from '../../../src/services/Constants';
|
||||
import { DarkRightPanel, StyledLink } from '../../../src/common-elements';
|
||||
import { ContentPanel } from '../RightPanelContent/ContentPanel';
|
||||
|
||||
import { MiddlePanel, Row, Section } from '../../common-elements/';
|
||||
|
||||
import { AppStore } from '../../services/AppStore';
|
||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||
import { Markdown } from '../Markdown/Markdown';
|
||||
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
||||
import {
|
||||
ApiHeader,
|
||||
DownloadButton,
|
||||
InfoSpan,
|
||||
InfoSpanBox,
|
||||
InfoSpanBoxWrap,
|
||||
} from './styled.elements';
|
||||
import { ApiHeader, DownloadButton, InfoSpan, InfoSpanBox, InfoSpanBoxWrap, } from './styled.elements';
|
||||
|
||||
export interface ApiInfoProps {
|
||||
store: AppStore;
|
||||
|
@ -29,8 +25,8 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { store } = this.props;
|
||||
const { info, externalDocs } = store.spec;
|
||||
const {store} = this.props;
|
||||
const {info, externalDocs} = store.spec;
|
||||
const hideDownloadButton = store.options.hideDownloadButton;
|
||||
|
||||
const downloadFilename = info.downloadFileName;
|
||||
|
@ -105,11 +101,13 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
|||
</InfoSpanBox>
|
||||
</InfoSpanBoxWrap>
|
||||
)) ||
|
||||
null}
|
||||
null}
|
||||
</StyledMarkdownBlock>
|
||||
<Markdown source={store.spec.info.description} />
|
||||
{externalDocs && <ExternalDocumentation externalDocs={externalDocs} />}
|
||||
<Markdown source={store.spec.info.description}/>
|
||||
{externalDocs && <ExternalDocumentation externalDocs={externalDocs}/>}
|
||||
</MiddlePanel>
|
||||
{store.options.showOtherInfoPanel &&
|
||||
<DarkRightPanel><ContentPanel content={info[Constants.OTX_EXTENSION_KEY]}/></DarkRightPanel>}
|
||||
</Row>
|
||||
</Section>
|
||||
);
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
import * as React from 'react';
|
||||
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
||||
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { OperationPanel } from '../RightPanelContent/OperationPanel';
|
||||
|
||||
import { Badge, DarkRightPanel, H2, MiddlePanel, Row } from '../../common-elements';
|
||||
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
|
||||
import { ShareLink } from '../../common-elements/linkify';
|
||||
import { Endpoint } from '../Endpoint/Endpoint';
|
||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||
import { Markdown } from '../Markdown/Markdown';
|
||||
import { Parameters } from '../Parameters/Parameters';
|
||||
import { RequestSamples } from '../RequestSamples/RequestSamples';
|
||||
import { ResponsesList } from '../Responses/ResponsesList';
|
||||
import { ResponseSamples } from '../ResponseSamples/ResponseSamples';
|
||||
|
||||
import { OperationModel as OperationType } from '../../services/models';
|
||||
import styled from '../../styled-components';
|
||||
import { Endpoint } from '../Endpoint/Endpoint';
|
||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||
import { Extensions } from '../Fields/Extensions';
|
||||
import { Markdown } from '../Markdown/Markdown';
|
||||
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
import { Parameters } from '../Parameters/Parameters';
|
||||
import { ResponsesList } from '../Responses/ResponsesList';
|
||||
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
||||
|
||||
const OperationRow = styled(Row)`
|
||||
backface-visibility: hidden;
|
||||
|
@ -28,7 +26,7 @@ const OperationRow = styled(Row)`
|
|||
`;
|
||||
|
||||
const Description = styled.div`
|
||||
margin-bottom: ${({ theme }) => theme.spacing.unit * 6}px;
|
||||
margin-bottom: ${({theme}) => theme.spacing.unit * 6}px;
|
||||
`;
|
||||
|
||||
export interface OperationProps {
|
||||
|
@ -38,9 +36,9 @@ export interface OperationProps {
|
|||
@observer
|
||||
export class Operation extends React.Component<OperationProps> {
|
||||
render() {
|
||||
const { operation } = this.props;
|
||||
const {operation} = this.props;
|
||||
|
||||
const { name: summary, description, deprecated, externalDocs } = operation;
|
||||
const {name: summary, description, deprecated, externalDocs} = operation;
|
||||
const hasDescription = !!(description || externalDocs);
|
||||
|
||||
return (
|
||||
|
@ -49,25 +47,23 @@ export class Operation extends React.Component<OperationProps> {
|
|||
<OperationRow>
|
||||
<MiddlePanel>
|
||||
<H2>
|
||||
<ShareLink to={operation.id} />
|
||||
<ShareLink to={operation.id}/>
|
||||
{summary} {deprecated && <Badge type="warning"> Deprecated </Badge>}
|
||||
</H2>
|
||||
{options.pathInMiddlePanel && <Endpoint operation={operation} inverted={true} />}
|
||||
{options.pathInMiddlePanel && <Endpoint operation={operation} inverted={true}/>}
|
||||
{hasDescription && (
|
||||
<Description>
|
||||
{description !== undefined && <Markdown source={description} />}
|
||||
{externalDocs && <ExternalDocumentation externalDocs={externalDocs} />}
|
||||
{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} />
|
||||
<Extensions extensions={operation.extensions}/>
|
||||
<SecurityRequirements securities={operation.security}/>
|
||||
<Parameters parameters={operation.parameters} body={operation.requestBody}/>
|
||||
<ResponsesList responses={operation.responses}/>
|
||||
</MiddlePanel>
|
||||
<DarkRightPanel>
|
||||
{!options.pathInMiddlePanel && <Endpoint operation={operation} />}
|
||||
<RequestSamples operation={operation} />
|
||||
<ResponseSamples operation={operation} />
|
||||
<OperationPanel operation={operation} options={options}/>
|
||||
</DarkRightPanel>
|
||||
</OperationRow>
|
||||
)}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import * as PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ThemeProvider } from '../../styled-components';
|
||||
import { OptionsProvider } from '../OptionsProvider';
|
||||
import { ContentItems } from '../../../src/components';
|
||||
|
||||
import { AppStore } from '../../services';
|
||||
|
||||
import { ThemeProvider } from '../../styled-components';
|
||||
import { ApiInfo } from '../ApiInfo/';
|
||||
import { ApiLogo } from '../ApiLogo/ApiLogo';
|
||||
import { ContentItems } from '../ContentItems/ContentItems';
|
||||
import { SideMenu } from '../SideMenu/SideMenu';
|
||||
import { StickyResponsiveSidebar } from '../StickySidebar/StickyResponsiveSidebar';
|
||||
import { ApiContentWrap, BackgroundStub, RedocWrap } from './styled.elements';
|
||||
import { OptionsProvider } from '../OptionsProvider';
|
||||
|
||||
import { SearchBox } from '../SearchBox/SearchBox';
|
||||
import { SideMenu } from '../SideMenu/SideMenu';
|
||||
import { StickyResponsiveSidebar } from '../StickySidebar/StickyResponsiveSidebar';
|
||||
import { StoreProvider } from '../StoreBuilder';
|
||||
import { ApiContentWrap, BackgroundStub, RedocWrap } from './styled.elements';
|
||||
|
||||
export interface RedocProps {
|
||||
store: AppStore;
|
||||
|
|
24
src/components/RightPanelContent/ContentPanel.tsx
Normal file
24
src/components/RightPanelContent/ContentPanel.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { MiddlePanel, Row } from '../../../src/common-elements';
|
||||
|
||||
interface ContentPanelProps {
|
||||
content: string;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ContentPanel extends React.Component<ContentPanelProps> {
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Row>
|
||||
<MiddlePanel>
|
||||
<h1>
|
||||
{this.props.content}
|
||||
</h1>
|
||||
</MiddlePanel>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
37
src/components/RightPanelContent/OperationPanel.tsx
Normal file
37
src/components/RightPanelContent/OperationPanel.tsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { ResponseSamples } from '../../../src/components';
|
||||
import { Endpoint } from '../../../src/components/Endpoint/Endpoint';
|
||||
import { RequestSamples } from '../../../src/components/RequestSamples/RequestSamples';
|
||||
import { RedocNormalizedOptions } from '../../../src/services';
|
||||
import { Constants } from '../../../src/services/Constants';
|
||||
import { OperationModel } from '../../../src/services/models';
|
||||
import { ContentPanel } from './/ContentPanel';
|
||||
|
||||
interface RightPanelContentProps {
|
||||
operation: OperationModel;
|
||||
options: RedocNormalizedOptions;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class OperationPanel extends React.Component<RightPanelContentProps> {
|
||||
render() {
|
||||
if (this.shouldShowOtherInfoPanel()) {
|
||||
return <ContentPanel content={this.props.operation.extensions[Constants.OTX_EXTENSION_KEY]}/>;
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
{!this.props.options.pathInMiddlePanel && <Endpoint operation={this.props.operation}/>}
|
||||
<RequestSamples operation={this.props.operation}/>
|
||||
<ResponseSamples operation={this.props.operation}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private shouldShowOtherInfoPanel() {
|
||||
return this.props.options.showOtherInfoPanel &&
|
||||
this.props.options.showExtensions &&
|
||||
this.props.operation.extensions[Constants.OTX_EXTENSION_KEY];
|
||||
}
|
||||
}
|
3
src/services/Constants.ts
Normal file
3
src/services/Constants.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export class Constants {
|
||||
static readonly OTX_EXTENSION_KEY = 'x-opentext-other';
|
||||
}
|
|
@ -20,6 +20,7 @@ export interface RedocRawOptions {
|
|||
disableSearch?: boolean | string;
|
||||
onlyRequiredInSamples?: boolean | string;
|
||||
showExtensions?: boolean | string | string[];
|
||||
showOtherInfoPanel?: boolean;
|
||||
|
||||
unstable_ignoreMimeParameters?: boolean;
|
||||
|
||||
|
@ -120,6 +121,7 @@ export class RedocNormalizedOptions {
|
|||
disableSearch: boolean;
|
||||
onlyRequiredInSamples: boolean;
|
||||
showExtensions: boolean | string[];
|
||||
showOtherInfoPanel: boolean;
|
||||
|
||||
/* tslint:disable-next-line */
|
||||
unstable_ignoreMimeParameters: boolean;
|
||||
|
@ -147,6 +149,7 @@ export class RedocNormalizedOptions {
|
|||
this.disableSearch = argValueToBoolean(raw.disableSearch);
|
||||
this.onlyRequiredInSamples = argValueToBoolean(raw.onlyRequiredInSamples);
|
||||
this.showExtensions = RedocNormalizedOptions.normalizeShowExtensions(raw.showExtensions);
|
||||
this.showOtherInfoPanel = argValueToBoolean(raw.showOtherInfoPanel);
|
||||
|
||||
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
interface ServerStub {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class produces canned responses for a given OpenAPI spec
|
||||
*/
|
||||
export class OpenApiServerStub implements ServerStub {
|
||||
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
describe('ServerStub', () => {
|
||||
test('TODO IMPLEMENT ME', () => {
|
||||
const fn = jest.fn();
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user