From 1eae3178938b87270d1c02f5039e4724713cff23 Mon Sep 17 00:00:00 2001 From: Jason Ibrahim Date: Fri, 15 Mar 2019 16:43:08 -0700 Subject: [PATCH] support for a specific vendor extension and toggling content panel area by adding additional option to redoc standalone --- demo/openapi.yaml | 8 ++-- src/components/ApiInfo/ApiInfo.tsx | 28 +++++------ src/components/Operation/Operation.tsx | 48 +++++++++---------- src/components/Redoc/Redoc.tsx | 14 +++--- .../RightPanelContent/ContentPanel.tsx | 24 ++++++++++ .../RightPanelContent/OperationPanel.tsx | 37 ++++++++++++++ src/services/Constants.ts | 3 ++ src/services/RedocNormalizedOptions.ts | 3 ++ src/services/ServerStub.ts | 10 ---- src/services/__tests__/ServerStub.test.ts | 6 --- 10 files changed, 114 insertions(+), 67 deletions(-) create mode 100644 src/components/RightPanelContent/ContentPanel.tsx create mode 100644 src/components/RightPanelContent/OperationPanel.tsx create mode 100644 src/services/Constants.ts delete mode 100644 src/services/ServerStub.ts delete mode 100644 src/services/__tests__/ServerStub.test.ts diff --git a/demo/openapi.yaml b/demo/openapi.yaml index fc3ce073..36e0c047 100644 --- a/demo/openapi.yaml +++ b/demo/openapi.yaml @@ -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. - + + 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 diff --git a/src/components/ApiInfo/ApiInfo.tsx b/src/components/ApiInfo/ApiInfo.tsx index 9b8bf6eb..c85180e5 100644 --- a/src/components/ApiInfo/ApiInfo.tsx +++ b/src/components/ApiInfo/ApiInfo.tsx @@ -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 { }; 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 { )) || - null} + null} - - {externalDocs && } + + {externalDocs && } + {store.options.showOtherInfoPanel && + } ); diff --git a/src/components/Operation/Operation.tsx b/src/components/Operation/Operation.tsx index 1283a6ad..03df37eb 100644 --- a/src/components/Operation/Operation.tsx +++ b/src/components/Operation/Operation.tsx @@ -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 { 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 {

- + {summary} {deprecated && Deprecated }

- {options.pathInMiddlePanel && } + {options.pathInMiddlePanel && } {hasDescription && ( - {description !== undefined && } - {externalDocs && } + {description !== undefined && } + {externalDocs && } )} - - - - + + + +
- {!options.pathInMiddlePanel && } - - +
)} diff --git a/src/components/Redoc/Redoc.tsx b/src/components/Redoc/Redoc.tsx index 2b43e77d..d7938067 100644 --- a/src/components/Redoc/Redoc.tsx +++ b/src/components/Redoc/Redoc.tsx @@ -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; diff --git a/src/components/RightPanelContent/ContentPanel.tsx b/src/components/RightPanelContent/ContentPanel.tsx new file mode 100644 index 00000000..688eff05 --- /dev/null +++ b/src/components/RightPanelContent/ContentPanel.tsx @@ -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 { + render() { + return ( + <> + + +

+ {this.props.content} +

+
+
+ + ); + } +} diff --git a/src/components/RightPanelContent/OperationPanel.tsx b/src/components/RightPanelContent/OperationPanel.tsx new file mode 100644 index 00000000..ad1aa20d --- /dev/null +++ b/src/components/RightPanelContent/OperationPanel.tsx @@ -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 { + render() { + if (this.shouldShowOtherInfoPanel()) { + return ; + } else { + return ( + <> + {!this.props.options.pathInMiddlePanel && } + + + + ); + } + } + + private shouldShowOtherInfoPanel() { + return this.props.options.showOtherInfoPanel && + this.props.options.showExtensions && + this.props.operation.extensions[Constants.OTX_EXTENSION_KEY]; + } +} diff --git a/src/services/Constants.ts b/src/services/Constants.ts new file mode 100644 index 00000000..00c23fbb --- /dev/null +++ b/src/services/Constants.ts @@ -0,0 +1,3 @@ +export class Constants { + static readonly OTX_EXTENSION_KEY = 'x-opentext-other'; +} diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts index d445b667..ef771f86 100644 --- a/src/services/RedocNormalizedOptions.ts +++ b/src/services/RedocNormalizedOptions.ts @@ -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); diff --git a/src/services/ServerStub.ts b/src/services/ServerStub.ts deleted file mode 100644 index 470a94b3..00000000 --- a/src/services/ServerStub.ts +++ /dev/null @@ -1,10 +0,0 @@ -interface ServerStub { - -} - -/** - * This class produces canned responses for a given OpenAPI spec - */ -export class OpenApiServerStub implements ServerStub { - -} diff --git a/src/services/__tests__/ServerStub.test.ts b/src/services/__tests__/ServerStub.test.ts deleted file mode 100644 index 985f7977..00000000 --- a/src/services/__tests__/ServerStub.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -describe('ServerStub', () => { - test('TODO IMPLEMENT ME', () => { - const fn = jest.fn(); - expect(fn).toHaveBeenCalled(); - }); -});