252 lines
8.4 KiB
JavaScript
252 lines
8.4 KiB
JavaScript
import React from "react"
|
|
import PropTypes from "prop-types"
|
|
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"
|
|
|
|
const getExampleComponent = ( sampleResponse, HighlightCode, getConfigs ) => {
|
|
if (
|
|
sampleResponse !== undefined &&
|
|
sampleResponse !== null
|
|
) { return <div>
|
|
<HighlightCode className="example" getConfigs={ getConfigs } value={ stringify(sampleResponse) } />
|
|
</div>
|
|
}
|
|
return null
|
|
}
|
|
|
|
export default class Response extends React.Component {
|
|
constructor(props, context) {
|
|
super(props, context)
|
|
|
|
this.state = {
|
|
responseContentType: "",
|
|
}
|
|
}
|
|
|
|
static propTypes = {
|
|
path: PropTypes.string.isRequired,
|
|
method: PropTypes.string.isRequired,
|
|
code: PropTypes.string.isRequired,
|
|
response: PropTypes.instanceOf(Iterable),
|
|
className: PropTypes.string,
|
|
getComponent: PropTypes.func.isRequired,
|
|
getConfigs: PropTypes.func.isRequired,
|
|
specSelectors: PropTypes.object.isRequired,
|
|
oas3Actions: PropTypes.object.isRequired,
|
|
specPath: ImPropTypes.list.isRequired,
|
|
fn: PropTypes.object.isRequired,
|
|
contentType: PropTypes.string,
|
|
activeExamplesKey: PropTypes.string,
|
|
controlsAcceptHeader: PropTypes.bool,
|
|
onContentTypeChange: PropTypes.func
|
|
}
|
|
|
|
static defaultProps = {
|
|
response: fromJS({}),
|
|
onContentTypeChange: () => {}
|
|
};
|
|
|
|
_onContentTypeChange = (value) => {
|
|
const { onContentTypeChange, controlsAcceptHeader } = this.props
|
|
this.setState({ responseContentType: value })
|
|
onContentTypeChange({
|
|
value: value,
|
|
controlsAcceptHeader
|
|
})
|
|
}
|
|
|
|
getTargetExamplesKey = () => {
|
|
const { response, contentType, activeExamplesKey } = 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 activeExamplesKey || firstExamplesKey
|
|
}
|
|
|
|
render() {
|
|
let {
|
|
path,
|
|
method,
|
|
code,
|
|
response,
|
|
className,
|
|
specPath,
|
|
fn,
|
|
getComponent,
|
|
getConfigs,
|
|
specSelectors,
|
|
contentType,
|
|
controlsAcceptHeader,
|
|
oas3Actions,
|
|
} = this.props
|
|
|
|
let { inferSchema } = fn
|
|
let isOAS3 = specSelectors.isOAS3()
|
|
|
|
let headers = response.get("headers")
|
|
let links = response.get("links")
|
|
const Headers = getComponent("headers")
|
|
const HighlightCode = getComponent("highlightCode")
|
|
const ModelExample = getComponent("modelExample")
|
|
const Markdown = getComponent("Markdown", true)
|
|
const OperationLink = getComponent("operationLink")
|
|
const ContentType = getComponent("contentType")
|
|
const ExamplesSelect = getComponent("ExamplesSelect")
|
|
const Example = getComponent("Example")
|
|
|
|
|
|
var sampleResponse
|
|
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 oas3SchemaForContentType = activeMediaType.get("schema")
|
|
|
|
schema = oas3SchemaForContentType ? inferSchema(oas3SchemaForContentType.toJS()) : null
|
|
specPathWithPossibleSchema = oas3SchemaForContentType ? List(["content", this.state.responseContentType, "schema"]) : specPath
|
|
} else {
|
|
schema = response.get("schema")
|
|
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) {
|
|
const targetExamplesKey = this.getTargetExamplesKey()
|
|
const targetExample = examplesForMediaType.get(targetExamplesKey, Map({}))
|
|
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 {
|
|
if(response.getIn(["examples", activeContentType])) {
|
|
sampleResponse = response.getIn(["examples", activeContentType])
|
|
} else {
|
|
sampleResponse = schema ? getSampleSchema(
|
|
schema.toJS(),
|
|
activeContentType,
|
|
{
|
|
includeReadOnly: true,
|
|
includeWriteOnly: true // writeOnly has no filtering effect in swagger 2.0
|
|
}
|
|
) : null
|
|
}
|
|
}
|
|
|
|
let example = getExampleComponent( sampleResponse, HighlightCode, getConfigs )
|
|
|
|
return (
|
|
<tr className={ "response " + ( className || "") } data-code={code}>
|
|
<td className="response-col_status">
|
|
{ code }
|
|
</td>
|
|
<td className="response-col_description">
|
|
|
|
<div className="response-col_description__inner">
|
|
<Markdown source={ response.get( "description" ) } />
|
|
</div>
|
|
|
|
{isOAS3 && response.get("content") ? (
|
|
<section className="response-controls">
|
|
<div
|
|
className={cx("response-control-media-type", {
|
|
"response-control-media-type--accept-controller": controlsAcceptHeader
|
|
})}
|
|
>
|
|
<small className="response-control-media-type__title">
|
|
Media type
|
|
</small>
|
|
<ContentType
|
|
value={this.state.responseContentType}
|
|
contentTypes={
|
|
response.get("content")
|
|
? response.get("content").keySeq()
|
|
: Seq()
|
|
}
|
|
onChange={this._onContentTypeChange}
|
|
/>
|
|
{controlsAcceptHeader ? (
|
|
<small className="response-control-media-type__accept-message">
|
|
Controls <code>Accept</code> header.
|
|
</small>
|
|
) : null}
|
|
</div>
|
|
{examplesForMediaType ? (
|
|
<div className="response-control-examples">
|
|
<small className="response-control-examples__title">
|
|
Examples
|
|
</small>
|
|
<ExamplesSelect
|
|
examples={examplesForMediaType}
|
|
currentExampleKey={this.getTargetExamplesKey()}
|
|
onSelect={key =>
|
|
oas3Actions.setActiveExamplesMember({
|
|
name: key,
|
|
pathMethod: [path, method],
|
|
contextType: "responses",
|
|
contextName: code
|
|
})
|
|
}
|
|
showLabels={false}
|
|
/>
|
|
</div>
|
|
) : null}
|
|
</section>
|
|
) : null}
|
|
|
|
{ example || schema ? (
|
|
<ModelExample
|
|
specPath={specPathWithPossibleSchema}
|
|
getComponent={ getComponent }
|
|
getConfigs={ getConfigs }
|
|
specSelectors={ specSelectors }
|
|
schema={ fromJSOrdered(schema) }
|
|
example={ example }
|
|
includeReadOnly={ true }/>
|
|
) : null }
|
|
|
|
{ isOAS3 && examplesForMediaType ? (
|
|
<Example
|
|
example={examplesForMediaType.get(this.getTargetExamplesKey(), Map({}))}
|
|
getComponent={getComponent}
|
|
omitValue={true}
|
|
/>
|
|
) : null}
|
|
|
|
{ headers ? (
|
|
<Headers
|
|
headers={ headers }
|
|
getComponent={ getComponent }
|
|
/>
|
|
) : null}
|
|
|
|
</td>
|
|
{isOAS3 ? <td className="response-col_links">
|
|
{ links ?
|
|
links.toSeq().map((link, key) => {
|
|
return <OperationLink key={key} name={key} link={ link } getComponent={getComponent}/>
|
|
})
|
|
: <i>No links</i>}
|
|
</td> : null}
|
|
</tr>
|
|
)
|
|
}
|
|
}
|