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

Ft/3803 multiple responses using one of attribute do not appear in ui #5530

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7d17742
Merge pull request #1 from swagger-api/master
VIIgit Aug 9, 2019
f94f42c
Merge pull request #2 from swagger-api/master
VIIgit Aug 14, 2019
e4d8a7d
3803-Multiple-responses-using-oneOf-attribute-do-not-appear-in-UI
VIIgit Aug 14, 2019
865a922
lint-errors fixed
VIIgit Aug 15, 2019
7faa035
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Aug 22, 2019
b642ce7
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Aug 30, 2019
8b07279
Consider oneOf/AnyOf on top level
VIIgit Sep 21, 2019
14cc22b
Move conflicting file
VIIgit Sep 21, 2019
ff2a6ff
Merge branch 'master' of https://github.com/swagger-api/swagger-ui in…
VIIgit Sep 21, 2019
64bcbd2
Merge branch 'swagger-api-master' into ft/3803-Multiple-responses-usi…
VIIgit Sep 21, 2019
03fb990
Rename fn.js to fn-2.js
VIIgit Sep 23, 2019
b4ac5a9
Create fn.js
VIIgit Sep 23, 2019
6cadd4c
Revert "Create fn.js"
VIIgit Sep 23, 2019
7ba60fc
Revert "Rename fn.js to fn-2.js"
VIIgit Sep 23, 2019
62d48d6
Adapt test for additional getConfigs check
VIIgit Sep 23, 2019
4a0abb3
Rename Element to Item
VIIgit Sep 23, 2019
eaca85d
Update fn.js
VIIgit Sep 23, 2019
1c2ff55
Simplify alternativeSchema
VIIgit Sep 23, 2019
7b5e94b
alternative schema (oneOf/anyOf) with discriminator
VIIgit Sep 25, 2019
2252f39
oneOf in arrays and improve oneOf item name
VIIgit Sep 25, 2019
53ae729
eslint issues fixed
VIIgit Sep 25, 2019
78bab69
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Sep 25, 2019
fff7d11
more tests for primitive oneOfs added
VIIgit Sep 28, 2019
791b09b
alternative schema (anyOf) of array type added
VIIgit Sep 29, 2019
e767c88
eslint fixed
VIIgit Sep 29, 2019
e24a1bd
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Oct 2, 2019
f45f3d4
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Oct 6, 2019
03c497e
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Oct 12, 2019
68b70ca
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Dec 7, 2019
12846db
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Jan 11, 2020
99bd7a2
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Mar 15, 2020
b3d85b6
prevent log warning for missing getComponent in production
tim-lai Mar 13, 2020
9afc994
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Mar 22, 2020
81410e8
Merge branch 'master' of github.com:swagger-api/swagger-ui into bug/g…
tim-lai Mar 24, 2020
204dc0c
ft: new optional config parameter for getComponent
tim-lai Mar 24, 2020
772c6bb
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Mar 24, 2020
7225fef
Update src/core/plugins/view/root-injects.jsx
tim-lai Mar 31, 2020
1899efe
Update src/core/plugins/view/root-injects.jsx
tim-lai Mar 31, 2020
7b75cde
Update src/core/plugins/view/root-injects.jsx
tim-lai Mar 31, 2020
b7ad2e4
Update src/core/json-schema-components.jsx
tim-lai Mar 31, 2020
4b81aea
housekeeping: prevent log warning for missing getComponent in product…
tim-lai Apr 1, 2020
305e6ee
prevent log warning for missing getComponent in production
tim-lai Mar 13, 2020
1d4125a
Merge branch 'master' into master
tim-lai Apr 1, 2020
5ef1a15
Merge pull request #5940 from tim-lai/master
tim-lai Apr 1, 2020
1365c9a
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Apr 2, 2020
b739096
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Apr 10, 2020
8c60bac
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Apr 25, 2020
05a7816
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Jul 26, 2020
658da1e
Merge branch 'master' into ft/3803-Multiple-responses-using-oneOf-att…
VIIgit Aug 16, 2020
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 docs/usage/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Parameter name | Docker variable | Description
<a name="operationsSorter"></a>`operationsSorter` | _Unavailable_ | `Function=(a => a)`. Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.
<a name="showExtensions"></a>`showExtensions` | `SHOW_EXTENSIONS` | `Boolean=false`. Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema.
<a name="showCommonExtensions"></a>`showCommonExtensions` | `SHOW_COMMON_EXTENSIONS` | `Boolean=false`. Controls the display of extensions (`pattern`, `maxLength`, `minLength`, `maximum`, `minimum`) fields and values for Parameters.
<a name="showAlternativeSchemaExample"></a>`showAlternativeSchemaExample` | _Unavailable_ | `Boolean=false`. Controls the display of alternative schemas (oneOf/anyOf) in the Example View.
<a name="tagSorter"></a>`tagsSorter` | _Unavailable_ | `Function=(a => a)`. Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function (see [Array.prototype.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger UI.
<a name="onComplete"></a>`onComplete` | _Unavailable_ | `Function=NOOP`. Provides a mechanism to be notified when Swagger UI has finished rendering a newly provided definition.

Expand Down
91 changes: 91 additions & 0 deletions src/core/components/alternative-schema-select.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { Component } from "react"
import PropTypes from "prop-types"

export default class AlternativeSchemaSelect extends Component {

static propTypes = {
alternativeSchemaSelections: PropTypes.object.isRequired,
onSelectionChanged: PropTypes.func.isRequired,
isManualMode: PropTypes.bool.isRequired,
alternativeSchemas: PropTypes.object.isRequired
}

constructor(props) {
super(props)
this.onModeChange = this.onModeChange.bind(this)
this.oneOfChange = this.oneOfChange.bind(this)
this.selectOneOfComponent = this.selectOneOfComponent.bind(this)
this.state = {
isManualMode: false,
alternativeSchemaSelections: {}
}
}

onModeChange(e) {
var { onSelectionChanged } = this.props
var { alternativeSchemaSelections } = this.state

onSelectionChanged( (e.target.dataset.name === "MANUAL" ? alternativeSchemaSelections :{}))
this.setState({isManualMode: e.target.dataset.name === "MANUAL"})
}

oneOfChange(e, id) {
var { onSelectionChanged } = this.props
var { alternativeSchemaSelections } = this.state

alternativeSchemaSelections[id] = parseInt(e.target.value)

onSelectionChanged( alternativeSchemaSelections )
}

selectOneOfComponent(attributePath, options, defaultOption, type) {
if (options) {
return (
<div key={"OneOf" + attributePath} style={{ padding: "0 0 10px 0" }} className={"content-type-wrapper "}>
<div>
<small htmlFor={attributePath} className={"response-control-alternative-examples__title"}>Choose {type} {attributePath}:</small>
</div>
<select
className="content-type"
name={attributePath}
value={defaultOption}
onChange={(e) => this.oneOfChange(e, attributePath)}
>
<option key={"empty"} value={"-1"}>{"<empty>"}</option>
{Object.keys(options).map((key, index) => {
return <option key={index + key} value={index}>{options[key]}</option>
})}
</select>
</div>
)
}
return null
}

render() {

const { alternativeSchemas } = this.props
const { isManualMode } = this.state

var oneOfComponents = []
if (isManualMode && alternativeSchemas) {
alternativeSchemas.map((attribute) => {
oneOfComponents.push(this.selectOneOfComponent(attribute.key, attribute.options, attribute.selectedIndex, attribute.type))
return true
})
}
return (
<div>
<ul className="response-control-alternative-examples tab">Example Value with:
<li className={"tabitem" + (isManualMode ? "" : " active")}>
<a className="tablinks" data-name="FIRST" onClick={this.onModeChange} >first `oneOf` item</a>
</li>
<li className={"tabitem" + (isManualMode ? " active" : "")}>
<a className="tablinks" data-name="MANUAL" onClick={this.onModeChange} >manually selected `oneOf` item</a>
</li>
</ul>
{oneOfComponents}
</div>
)
}
}
14 changes: 13 additions & 1 deletion src/core/components/model-example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export default class ModelExample extends React.Component {
isExecute: PropTypes.bool,
getConfigs: PropTypes.func.isRequired,
specPath: ImPropTypes.list.isRequired,
alternativeSchemas: PropTypes.object,
onSelectedAlternativeOptionChanged: PropTypes.func,
onChange: PropTypes.func,
}

constructor(props, context) {
Expand Down Expand Up @@ -52,10 +55,11 @@ export default class ModelExample extends React.Component {
}

render() {
let { getComponent, specSelectors, schema, example, isExecute, getConfigs, specPath } = this.props
let { getComponent, specSelectors, schema, example, isExecute, getConfigs, specPath, alternativeSchemas, onChange } = this.props
let { defaultModelExpandDepth } = getConfigs()
const ModelWrapper = getComponent("ModelWrapper")
const HighlightCode = getComponent("highlightCode")
const AlternativeSchemaSelect = getComponent("alternativeSchemaSelect")

let isOAS3 = specSelectors.isOAS3()

Expand All @@ -78,6 +82,14 @@ export default class ModelExample extends React.Component {
)
) : null
}
{
this.state.activeTab === "example" && alternativeSchemas && onChange ? (
<AlternativeSchemaSelect
alternativeSchemas = {alternativeSchemas}
onSelectionChanged = {onChange}
/>
) : null
}
{
this.state.activeTab === "model" && <ModelWrapper schema={ schema }
getComponent={ getComponent }
Expand Down
8 changes: 7 additions & 1 deletion src/core/components/parameters/parameters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export default class Parameters extends Component {
super(props)
this.state = {
callbackVisible: false,
parametersVisible: true
parametersVisible: true,
alternativeSchemaSelections: {}
}
}

Expand All @@ -33,6 +34,7 @@ export default class Parameters extends Component {
pathMethod: PropTypes.array.isRequired,
getConfigs: PropTypes.func.isRequired,
specPath: ImPropTypes.list.isRequired,
alternativeSchemaSelections: PropTypes.object,
}


Expand Down Expand Up @@ -197,6 +199,7 @@ export default class Parameters extends Component {
requestBody={requestBody}
requestBodyValue={oas3Selectors.requestBodyValue(...pathMethod)}
isExecute={isExecute}
alternativeSchemaSelections= {this.state.alternativeSchemaSelections || {}}
activeExamplesKey={oas3Selectors.activeExamplesMember(
...pathMethod,
"requestBody",
Expand All @@ -222,6 +225,9 @@ export default class Parameters extends Component {
}
oas3Actions.setRequestBodyValue({ value, pathMethod })
}}
onAlternativeSchemaChange= {(alternativeSchemaSelections) => {
this.setState({alternativeSchemaSelections: alternativeSchemaSelections})
}}
contentType={oas3Selectors.requestContentType(...pathMethod)}/>
</div>
</div>
Expand Down
17 changes: 15 additions & 2 deletions src/core/components/response.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class Response extends React.Component {

this.state = {
responseContentType: "",
alternativeSchemaSelections: {}
}
}

Expand All @@ -40,7 +41,8 @@ export default class Response extends React.Component {
contentType: PropTypes.string,
activeExamplesKey: PropTypes.string,
controlsAcceptHeader: PropTypes.bool,
onContentTypeChange: PropTypes.func
onContentTypeChange: PropTypes.func,
alternativeSchemaSelections: PropTypes.object
}

static defaultProps = {
Expand All @@ -57,6 +59,10 @@ export default class Response extends React.Component {
})
}

_onAlternativeSchemaChanged = (alternativeSchemaSelections) =>{
this.setState({alternativeSchemaSelections: alternativeSchemaSelections})
}

getTargetExamplesKey = () => {
const { response, contentType, activeExamplesKey } = this.props

Expand Down Expand Up @@ -85,6 +91,8 @@ export default class Response extends React.Component {
oas3Actions,
} = this.props

const { showAlternativeSchemaExample } = getConfigs()

let { inferSchema } = fn
let isOAS3 = specSelectors.isOAS3()

Expand Down Expand Up @@ -131,8 +139,11 @@ export default class Response extends React.Component {
sampleResponse = stringify(activeMediaType.get("example"))
} else {
// use an example value generated based on the schema
var alternativeSchemas = showAlternativeSchemaExample === true ? [] : undefined
sampleResponse = getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, {
includeReadOnly: true
includeReadOnly: true,
alternativeSchemas: alternativeSchemas,
alternativeSchemaSelections: this.state.alternativeSchemaSelections || {}
})
}
} else {
Expand Down Expand Up @@ -218,6 +229,8 @@ export default class Response extends React.Component {
getConfigs={ getConfigs }
specSelectors={ specSelectors }
schema={ fromJSOrdered(schema) }
alternativeSchemas= { alternativeSchemas }
onChange = { this._onAlternativeSchemaChanged }
example={ example }/>
) : null }

Expand Down
1 change: 1 addition & 0 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export default function SwaggerUI(opts) {
defaultModelsExpandDepth: 1,
showExtensions: false,
showCommonExtensions: false,
showAlternativeSchemaExample: false,
withCredentials: undefined,
supportedSubmitMethods: [
"get",
Expand Down
19 changes: 16 additions & 3 deletions src/core/plugins/oas3/components/request-body.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ImPropTypes from "react-immutable-proptypes"
import { Map, OrderedMap, List } from "immutable"
import { getCommonExtensions, getSampleSchema, stringify } from "core/utils"

function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey) {
function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey, alternativeSchemas, alternativeSchemaSelections) {
let mediaTypeValue = requestBody.getIn(["content", mediaType])
let schema = mediaTypeValue.get("schema").toJS()
let example =
Expand All @@ -25,7 +25,9 @@ function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey) {
return stringify(
example ||
getSampleSchema(schema, mediaType, {
includeWriteOnly: true
includeWriteOnly: true,
alternativeSchemas: alternativeSchemas,
alternativeSchemaSelections: alternativeSchemaSelections
}) ||
""
)
Expand All @@ -47,6 +49,8 @@ const RequestBody = ({
onChange,
activeExamplesKey,
updateActiveExamplesKey,
alternativeSchemaSelections,
onAlternativeSchemaChange,
}) => {
const handleFile = (e) => {
onChange(e.target.files[0])
Expand All @@ -59,7 +63,7 @@ const RequestBody = ({
const ExamplesSelectValueRetainer = getComponent("ExamplesSelectValueRetainer")
const Example = getComponent("Example")

const { showCommonExtensions } = getConfigs()
const { showCommonExtensions, showAlternativeSchemaExample } = getConfigs()

const requestBodyDescription = (requestBody && requestBody.get("description")) || null
const requestBodyContent = (requestBody && requestBody.get("content")) || new OrderedMap()
Expand Down Expand Up @@ -175,6 +179,8 @@ const RequestBody = ({
</div>
}

var alternativeSchemas = showAlternativeSchemaExample === true ? [] : undefined

return <div>
{ requestBodyDescription &&
<Markdown source={requestBodyDescription} />
Expand Down Expand Up @@ -207,6 +213,7 @@ const RequestBody = ({
/>
</div>
) : (

<ModelExample
getComponent={ getComponent }
getConfigs={ getConfigs }
Expand All @@ -215,13 +222,17 @@ const RequestBody = ({
isExecute={isExecute}
schema={mediaTypeValue.get("schema")}
specPath={specPath.push("content", contentType)}
alternativeSchemas= { alternativeSchemas }
onChange= { onAlternativeSchemaChange }
example={
<HighlightCode
className="body-param__example"
value={stringify(requestBodyValue) || getDefaultRequestBodyValue(
requestBody,
contentType,
activeExamplesKey,
alternativeSchemas,
alternativeSchemaSelections
)}
/>
}
Expand Down Expand Up @@ -252,6 +263,8 @@ RequestBody.propTypes = {
specPath: PropTypes.array.isRequired,
activeExamplesKey: PropTypes.string,
updateActiveExamplesKey: PropTypes.func,
alternativeSchemaSelections: PropTypes.object,
onAlternativeSchemaChange: PropTypes.func,
}

export default RequestBody
Loading