From 8e030a08a3828a3acde6bf9221600c69683f22d9 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Mon, 17 Jun 2019 11:42:20 +0100 Subject: [PATCH 01/77] add opt-in Prettier config --- .prettierrc.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .prettierrc.yaml diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000000..8ad24d2054d --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,6 @@ +semi: false +trailingComma: es5 +endOfLine: lf +singleQuote: true +requirePragma: true +insertPragma: true From b0725d170a8e102d75a45b7f9259d7c657fbc128 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Mon, 17 Jun 2019 11:43:11 +0100 Subject: [PATCH 02/77] remove legacy `examples` implementation --- src/core/components/response.jsx | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/core/components/response.jsx b/src/core/components/response.jsx index 58af705ec79..2c83e7de079 100644 --- a/src/core/components/response.jsx +++ b/src/core/components/response.jsx @@ -5,18 +5,7 @@ import cx from "classnames" import { fromJS, Seq, Iterable, List, Map } from "immutable" import { getSampleSchema, fromJSOrdered, stringify } from "core/utils" -const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => { - if ( examples && examples.size ) { - return examples.entrySeq().map( ([ key, example ]) => { - let exampleValue = stringify(example) - - return (
-
{ key }
- -
) - }).toArray() - } - +const getExampleComponent = ( sampleResponse, HighlightCode ) => { if ( sampleResponse ) { return
@@ -79,7 +68,6 @@ export default class Response extends React.Component { let { isOAS3 } = specSelectors let headers = response.get("headers") - let examples = response.get("examples") let links = response.get("links") const Headers = getComponent("headers") const HighlightCode = getComponent("highlightCode") @@ -117,14 +105,7 @@ export default class Response extends React.Component { }) : null } - if(examples) { - examples = examples.map(example => { - // Remove unwanted properties from examples - return example.set ? example.set("$$ref", undefined) : example - }) - } - - let example = getExampleComponent( sampleResponse, examples, HighlightCode ) + let example = getExampleComponent( sampleResponse, HighlightCode ) return ( From 3e52c40efe41f5c97b7eef6f519d42a351fd1b00 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 18 Jun 2019 11:55:22 +0100 Subject: [PATCH 03/77] create ExamplesSelect --- src/core/components/examples-select.jsx | 68 +++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/core/components/examples-select.jsx diff --git a/src/core/components/examples-select.jsx b/src/core/components/examples-select.jsx new file mode 100644 index 00000000000..97321245166 --- /dev/null +++ b/src/core/components/examples-select.jsx @@ -0,0 +1,68 @@ +/** + * @prettier + */ + +import React from "react" +import Im from "immutable" +import PropTypes from "prop-types" +import ImPropTypes from "react-immutable-proptypes" + +export default class ExamplesSelect extends React.PureComponent { + static propTypes = { + examples: ImPropTypes.map.isRequired, + onSelect: PropTypes.func, + currentValue: PropTypes.any.isRequired, + } + + static defaultProps = { + examples: Im.Map({}), + onSelect: (...args) => + console.log( + // FIXME: remove before merging to master... + `DEBUG: ExamplesSelect was not given an onSelect callback`, + ...args + ), + currentValue: null, + } + + _onSelectChange = e => { + debugger // eslint-disable-line + if (typeof this.props.onSelect === "function") { + const element = e.target.selectedOptions[0] + const key = element.getAttribute("data-key") + const value = this.props.examples.getIn([key, "value"]) + this.props.onSelect(value && value.toJS ? value.toJS() : value, key) + } + } + + render() { + const { examples, currentValue } = this.props + + const isCurrentValueAnExampleValue = examples.some( + example => example.get("value") === currentValue + ) + + debugger //eslint-disable-line + + return ( + + ) + } +} From 3cacbeb1fe930dc65d15db3634e8c1b62678b78a Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 18 Jun 2019 12:21:34 +0100 Subject: [PATCH 04/77] support `Response.examples` in OpenAPI 3 --- src/core/components/response.jsx | 62 +++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/core/components/response.jsx b/src/core/components/response.jsx index 2c83e7de079..2a18fbc0427 100644 --- a/src/core/components/response.jsx +++ b/src/core/components/response.jsx @@ -4,9 +4,10 @@ import ImPropTypes from "react-immutable-proptypes" import cx from "classnames" import { fromJS, Seq, Iterable, List, Map } from "immutable" import { getSampleSchema, fromJSOrdered, stringify } from "core/utils" +import ExamplesSelect from "./examples-select" const getExampleComponent = ( sampleResponse, HighlightCode ) => { - if ( sampleResponse ) { return
+ if ( sampleResponse !== undefined ) { return
} @@ -18,7 +19,8 @@ export default class Response extends React.Component { super(props, context) this.state = { - responseContentType: "" + responseContentType: "", + activeExamplesKey: null, } } @@ -50,6 +52,17 @@ export default class Response extends React.Component { }) } + getTargetExamplesKey = () => { + const { response, contentType } = this.props + + const activeContentType = this.state.responseContentType || contentType + const activeMediaType = response.getIn(["content", activeContentType], Map({})) + const examplesForMediaType = activeMediaType.get("examples", null) + + const firstExamplesKey = examplesForMediaType.keySeq().first() + return this.state.activeExamplesKey || firstExamplesKey + } + render() { let { code, @@ -76,29 +89,44 @@ export default class Response extends React.Component { const OperationLink = getComponent("operationLink") const ContentType = getComponent("contentType") + var sampleResponse - var sampleSchema var schema, specPathWithPossibleSchema const activeContentType = this.state.responseContentType || contentType + const activeMediaType = response.getIn(["content", activeContentType], Map({})) + const examplesForMediaType = activeMediaType.get("examples", null) + // Goal: find a schema value for `schema` if(isOAS3()) { - const mediaType = response.getIn(["content", activeContentType], Map({})) - const oas3SchemaForContentType = mediaType.get("schema", Map({})) + const oas3SchemaForContentType = activeMediaType.get("schema", Map({})) - if(mediaType.get("example") !== undefined) { - sampleSchema = stringify(mediaType.get("example")) - } else { - sampleSchema = getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, { - includeReadOnly: true - }) - } - sampleResponse = oas3SchemaForContentType ? sampleSchema : null schema = oas3SchemaForContentType ? inferSchema(oas3SchemaForContentType.toJS()) : null specPathWithPossibleSchema = oas3SchemaForContentType ? List(["content", this.state.responseContentType, "schema"]) : specPath } else { schema = inferSchema(response.toJS()) // TODO: don't convert back and forth. Lets just stick with immutable for inferSchema specPathWithPossibleSchema = response.has("schema") ? specPath.push("schema") : specPath + } + + // Goal: find an example value for `sampleResponse` + if(isOAS3()) { + const oas3SchemaForContentType = activeMediaType.get("schema", Map({})) + + if(examplesForMediaType) { + debugger // eslint-disable-line + const targetExamplesKey = this.getTargetExamplesKey() + const targetExample = examplesForMediaType.get(targetExamplesKey) + sampleResponse = stringify(targetExample.get("value")) + } else if(activeMediaType.get("example") !== undefined) { + // use the example key's value + sampleResponse = stringify(activeMediaType.get("example")) + } else { + // use an example value generated based on the schema + sampleResponse = getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, { + includeReadOnly: true + }) + } + } else { sampleResponse = schema ? getSampleSchema(schema, activeContentType, { includeReadOnly: true, includeWriteOnly: true // writeOnly has no filtering effect in swagger 2.0 @@ -131,6 +159,14 @@ export default class Response extends React.Component {
: null } + { isOAS3 && examplesForMediaType ? + this.setState({ activeExamplesKey: key })}> + + : null} + { example ? ( Date: Tue, 18 Jun 2019 14:08:54 +0100 Subject: [PATCH 05/77] create response controls group --- src/core/components/response.jsx | 56 +++++++++++++++++++++----------- src/style/_layout.scss | 37 ++++++++++++++++----- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/core/components/response.jsx b/src/core/components/response.jsx index 2a18fbc0427..874fde77b7b 100644 --- a/src/core/components/response.jsx +++ b/src/core/components/response.jsx @@ -146,26 +146,44 @@ export default class Response extends React.Component { - { isOAS3 ? -
- +
+ Media type + - { controlsAcceptHeader ? Controls Accept header. : null } -
- : null } - - { isOAS3 && examplesForMediaType ? - this.setState({ activeExamplesKey: key })}> - - : null} + {controlsAcceptHeader ? ( + + Controls Accept header. + + ) : null} +
+ {examplesForMediaType ? ( +
+ Examples + this.setState({ activeExamplesKey: key })} + /> +
+ ) : null} + + ) : null + } { example ? ( Date: Tue, 18 Jun 2019 14:12:03 +0100 Subject: [PATCH 06/77] prettier reformat --- src/core/components/response.jsx | 76 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/src/core/components/response.jsx b/src/core/components/response.jsx index 874fde77b7b..ce955405d69 100644 --- a/src/core/components/response.jsx +++ b/src/core/components/response.jsx @@ -146,44 +146,50 @@ export default class Response extends React.Component { - { - isOAS3 ? ( -
-
- Media type - +
+ + Media type + + + {controlsAcceptHeader ? ( + + Controls Accept header. + + ) : null} +
+ {examplesForMediaType ? ( +
+ + Examples + + + this.setState({ activeExamplesKey: key }) } - onChange={this._onContentTypeChange} /> - {controlsAcceptHeader ? ( - - Controls Accept header. - - ) : null}
- {examplesForMediaType ? ( -
- Examples - this.setState({ activeExamplesKey: key })} - /> -
- ) : null} -
- ) : null - } + ) : null} + + ) : null} { example ? ( Date: Tue, 18 Jun 2019 14:30:10 +0100 Subject: [PATCH 07/77] prepare to break up Parameters --- src/core/components/parameters/index.js | 1 + src/core/components/{ => parameters}/parameters.jsx | 0 src/core/presets/base.js | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 src/core/components/parameters/index.js rename src/core/components/{ => parameters}/parameters.jsx (100%) diff --git a/src/core/components/parameters/index.js b/src/core/components/parameters/index.js new file mode 100644 index 00000000000..5809afbeb2c --- /dev/null +++ b/src/core/components/parameters/index.js @@ -0,0 +1 @@ +export { default as Parameters } from "./parameters" diff --git a/src/core/components/parameters.jsx b/src/core/components/parameters/parameters.jsx similarity index 100% rename from src/core/components/parameters.jsx rename to src/core/components/parameters/parameters.jsx diff --git a/src/core/presets/base.js b/src/core/presets/base.js index cff809cd5b6..91090966fe6 100644 --- a/src/core/presets/base.js +++ b/src/core/presets/base.js @@ -41,7 +41,7 @@ import HighlightCode from "core/components/highlight-code" import Responses from "core/components/responses" import Response from "core/components/response" import ResponseBody from "core/components/response-body" -import Parameters from "core/components/parameters" +import { Parameters } from "core/components/parameters" import ParameterExt from "core/components/parameter-extension" import ParameterIncludeEmpty from "core/components/parameter-include-empty" import ParameterRow from "core/components/parameter-row" From 78754733ace65162da83e014eb0de030a24799da Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 18 Jun 2019 15:05:37 +0100 Subject: [PATCH 08/77] reunify Parameters and OAS3 Parameters --- src/core/components/operation.jsx | 2 + src/core/components/parameters/parameters.jsx | 97 +++++++- .../plugins/oas3/wrap-components/index.js | 2 - .../oas3/wrap-components/parameters.jsx | 214 ------------------ 4 files changed, 97 insertions(+), 218 deletions(-) delete mode 100644 src/core/plugins/oas3/wrap-components/parameters.jsx diff --git a/src/core/components/operation.jsx b/src/core/components/operation.jsx index f441a5d0fbe..ac2258776f8 100644 --- a/src/core/components/operation.jsx +++ b/src/core/components/operation.jsx @@ -156,6 +156,8 @@ export default class Operation extends PureComponent { specSelectors={ specSelectors } pathMethod={ [path, method] } getConfigs={ getConfigs } + oas3Actions={ oas3Actions } + oas3Selectors={ oas3Selectors } /> } diff --git a/src/core/components/parameters/parameters.jsx b/src/core/components/parameters/parameters.jsx index 5245cc12e90..364e002b9c2 100644 --- a/src/core/components/parameters/parameters.jsx +++ b/src/core/components/parameters/parameters.jsx @@ -1,18 +1,29 @@ import React, { Component } from "react" import PropTypes from "prop-types" +import Im, { Map, List } from "immutable" import ImPropTypes from "react-immutable-proptypes" -import Im from "immutable" // More readable, just iterate over maps, only const eachMap = (iterable, fn) => iterable.valueSeq().filter(Im.Map.isMap).map(fn) export default class Parameters extends Component { + constructor(props) { + super(props) + this.state = { + callbackVisible: false, + parametersVisible: true + } + } + static propTypes = { parameters: ImPropTypes.list.isRequired, + operation: PropTypes.object.isRequired, specActions: PropTypes.object.isRequired, getComponent: PropTypes.func.isRequired, specSelectors: PropTypes.object.isRequired, + oas3Actions: PropTypes.object.isRequired, + oas3Selectors: PropTypes.object.isRequired, fn: PropTypes.object.isRequired, tryItOutEnabled: PropTypes.bool, allowTryItOut: PropTypes.bool, @@ -52,6 +63,20 @@ export default class Parameters extends Component { changeConsumesValue(onChangeKey, val) } + toggleTab = (tab) => { + if(tab === "parameters"){ + return this.setState({ + parametersVisible: true, + callbackVisible: false + }) + }else if(tab === "callbacks"){ + return this.setState({ + callbackVisible: true, + parametersVisible: false + }) + } + } + render(){ let { @@ -67,24 +92,48 @@ export default class Parameters extends Component { getConfigs, specSelectors, specActions, - pathMethod + pathMethod, + oas3Actions, + oas3Selectors, + operation } = this.props const ParameterRow = getComponent("parameterRow") const TryItOutButton = getComponent("TryItOutButton") + const ContentType = getComponent("contentType") + const Callbacks = getComponent("Callbacks", true) + const RequestBody = getComponent("RequestBody", true) const isExecute = tryItOutEnabled && allowTryItOut + const isOAS3 = specSelectors.isOAS3() + const requestBody = operation.get("requestBody") return (
+ { isOAS3 ? (
+
this.toggleTab("parameters")} className={`tab-item ${this.state.parametersVisible && "active"}`}> +

Parameters

+
+ { operation.get("callbacks") ? + ( +
this.toggleTab("callbacks")} className={`tab-item ${this.state.callbackVisible && "active"}`}> +

Callbacks

+
+ ) : null + } +
+ ) : ( +

Parameters

+ )} { allowTryItOut ? ( ) : null }
+ {this.state.parametersVisible ?
{ !parameters.count() ?

No parameters

:
@@ -117,6 +166,50 @@ export default class Parameters extends Component {
} +
: null } + + {this.state.callbackVisible ?
+ +
: null } + { + isOAS3 && requestBody && this.state.parametersVisible && +
+
+

Request body

+ +
+
+ { + if(path) { + const lastValue = oas3Selectors.requestBodyValue(...pathMethod) + const usableValue = Map.isMap(lastValue) ? lastValue : Map() + return oas3Actions.setRequestBodyValue({ + pathMethod, + value: usableValue.setIn(path, value) + }) + } + oas3Actions.setRequestBodyValue({ value, pathMethod }) + }} + contentType={oas3Selectors.requestContentType(...pathMethod)}/> +
+
+ }
) } diff --git a/src/core/plugins/oas3/wrap-components/index.js b/src/core/plugins/oas3/wrap-components/index.js index fd0c99f587a..2c421add245 100644 --- a/src/core/plugins/oas3/wrap-components/index.js +++ b/src/core/plugins/oas3/wrap-components/index.js @@ -1,6 +1,5 @@ import Markdown from "./markdown" import AuthItem from "./auth-item" -import parameters from "./parameters" import VersionStamp from "./version-stamp" import OnlineValidatorBadge from "./online-validator-badge" import Model from "./model" @@ -9,7 +8,6 @@ import JsonSchema_string from "./json-schema-string" export default { Markdown, AuthItem, - parameters, JsonSchema_string, VersionStamp, model: Model, diff --git a/src/core/plugins/oas3/wrap-components/parameters.jsx b/src/core/plugins/oas3/wrap-components/parameters.jsx deleted file mode 100644 index ba2f2b0f104..00000000000 --- a/src/core/plugins/oas3/wrap-components/parameters.jsx +++ /dev/null @@ -1,214 +0,0 @@ -import React, { Component } from "react" -import PropTypes from "prop-types" -import Im, { Map, List } from "immutable" -import ImPropTypes from "react-immutable-proptypes" -import { OAS3ComponentWrapFactory } from "../helpers" - -// More readable, just iterate over maps, only -const eachMap = (iterable, fn) => iterable.valueSeq().filter(Im.Map.isMap).map(fn) - -class Parameters extends Component { - - constructor(props) { - super(props) - this.state = { - callbackVisible: false, - parametersVisible: true - } - } - - static propTypes = { - parameters: ImPropTypes.list.isRequired, - specActions: PropTypes.object.isRequired, - operation: PropTypes.object.isRequired, - getComponent: PropTypes.func.isRequired, - getConfigs: PropTypes.func.isRequired, - specSelectors: PropTypes.object.isRequired, - oas3Actions: PropTypes.object.isRequired, - oas3Selectors: PropTypes.object.isRequired, - fn: PropTypes.object.isRequired, - tryItOutEnabled: PropTypes.bool, - allowTryItOut: PropTypes.bool, - specPath: ImPropTypes.list.isRequired, - onTryoutClick: PropTypes.func, - onCancelClick: PropTypes.func, - onChangeKey: PropTypes.array, - pathMethod: PropTypes.array.isRequired - } - - - static defaultProps = { - onTryoutClick: Function.prototype, - onCancelClick: Function.prototype, - tryItOutEnabled: false, - allowTryItOut: true, - onChangeKey: [], - } - - onChange = ( param, value, isXml ) => { - let { - specActions: { changeParamByIdentity }, - onChangeKey, - } = this.props - - changeParamByIdentity( onChangeKey, param, value, isXml) - } - - onChangeConsumesWrapper = ( val ) => { - let { - specActions: { changeConsumesValue }, - onChangeKey - } = this.props - - changeConsumesValue(onChangeKey, val) - } - - toggleTab = (tab) => { - if(tab === "parameters"){ - return this.setState({ - parametersVisible: true, - callbackVisible: false - }) - }else if(tab === "callbacks"){ - return this.setState({ - callbackVisible: true, - parametersVisible: false - }) - } - } - - render(){ - - let { - onTryoutClick, - onCancelClick, - parameters, - allowTryItOut, - tryItOutEnabled, - - fn, - getComponent, - getConfigs, - specSelectors, - specActions, - oas3Actions, - oas3Selectors, - pathMethod, - specPath, - operation - } = this.props - - const ParameterRow = getComponent("parameterRow") - const TryItOutButton = getComponent("TryItOutButton") - const ContentType = getComponent("contentType") - const Callbacks = getComponent("Callbacks", true) - const RequestBody = getComponent("RequestBody", true) - - const isExecute = tryItOutEnabled && allowTryItOut - const { isOAS3 } = specSelectors - - const requestBody = operation.get("requestBody") - const requestBodySpecPath = specPath.slice(0, -1).push("requestBody") // remove the "parameters" part - - return ( -
-
-
-
this.toggleTab("parameters")} className={`tab-item ${this.state.parametersVisible && "active"}`}> -

Parameters

-
- { operation.get("callbacks") ? - ( -
this.toggleTab("callbacks")} className={`tab-item ${this.state.callbackVisible && "active"}`}> -

Callbacks

-
- ) : null - } -
- { allowTryItOut ? ( - - ) : null } -
- {this.state.parametersVisible ?
- { !parameters.count() ?

No parameters

: -
- - - - - - - - - { - eachMap(parameters, (parameter, i) => ( - - )).toArray() - } - -
NameDescription
-
- } -
: "" } - - {this.state.callbackVisible ?
- -
: "" } - { - isOAS3() && requestBody && this.state.parametersVisible && -
-
-

Request body

- -
-
- { - if(path) { - const lastValue = oas3Selectors.requestBodyValue(...pathMethod) - const usableValue = Map.isMap(lastValue) ? lastValue : Map() - return oas3Actions.setRequestBodyValue({ - pathMethod, - value: usableValue.setIn(path, value) - }) - } - oas3Actions.setRequestBodyValue({ value, pathMethod }) - }} - contentType={oas3Selectors.requestContentType(...pathMethod)}/> -
-
- } -
- ) - } -} - - -export default OAS3ComponentWrapFactory(Parameters) From 6153a652ec678f946ae0cf0e3076bd2b983d23d8 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 18 Jun 2019 17:02:20 +0100 Subject: [PATCH 09/77] Parameter Examples --- src/core/components/examples-select.jsx | 6 +- src/core/components/examples.jsx | 87 +++++++++++++++++++++++++ src/core/components/parameter-row.jsx | 40 ++++++++++-- src/core/utils.js | 6 +- src/style/_layout.scss | 30 +++++++++ src/style/_table.scss | 1 + 6 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 src/core/components/examples.jsx diff --git a/src/core/components/examples-select.jsx b/src/core/components/examples-select.jsx index 97321245166..a520657a718 100644 --- a/src/core/components/examples-select.jsx +++ b/src/core/components/examples-select.jsx @@ -12,6 +12,7 @@ export default class ExamplesSelect extends React.PureComponent { examples: ImPropTypes.map.isRequired, onSelect: PropTypes.func, currentValue: PropTypes.any.isRequired, + selectMessage: PropTypes.string, } static defaultProps = { @@ -23,6 +24,7 @@ export default class ExamplesSelect extends React.PureComponent { ...args ), currentValue: null, + selectMessage: "Select an example...", } _onSelectChange = e => { @@ -36,7 +38,7 @@ export default class ExamplesSelect extends React.PureComponent { } render() { - const { examples, currentValue } = this.props + const { examples, currentValue, selectMessage } = this.props const isCurrentValueAnExampleValue = examples.some( example => example.get("value") === currentValue @@ -47,7 +49,7 @@ export default class ExamplesSelect extends React.PureComponent { return ( + - {!isCurrentValueAnExampleValue ? ( +