feat: Multiple Examples for OpenAPI 3 Parameters, Request Bodies, and Responses (via #5427)
* add opt-in Prettier config * remove legacy `examples` implementation * create ExamplesSelect * support `Response.examples` in OpenAPI 3 * create response controls group * prettier reformat * prepare to break up Parameters * reunify Parameters and OAS3 Parameters * Parameter Examples * Example component * handle parameter value stringification correctly * FOR REVIEW: add prop for controlling Select * use regular header for param examples in Try-It-Out * manage active examples member via Redux * Request Body Try-It-Out examples * remove special Response description styling * omit Example value display in Try-It-Out * support disabled text inputs in JsonSchemaForm * Example.omitValue => Example.showValue * ExamplesSelectValueRetainer * styling for disabled inputs * remove console.log * support "Modified Values" in ExamplesSelect * remove Examples component (wasn't used anywhere) * use ParameterRow.getParamKey for active examples member keying * split-rendering of examples in ParameterRow * send disabled prop to JsonSchemaForm * use content type to key request body active examples members * remove debugger * rewire RequestBodyEditor to be a controlled component REVIEW: does this have perf implications? * trigger synthetic onSelect events in ExamplesSelect * prettier updates * remove outdated Examples usage in RequestBody * don't handle examples changes in ESVR * make RequestBodyEditor semi-controlled * don't default to an empty Map for request bodies * add namespaceKey to ESVR for state mgmt * don't key RequestBody activeExampleKeys on media type * tweak ESVR isModifiedValueSelected calculation * add trace class to ExamplesSelect * remove usage of ESVR.currentNamespace * reset to first example if currentExampleKey is invalid * add default values to RequestBody rendering * stringify things in ESVR * avoid null select value (silences React warning) * detect user inputs that match any examples member's value * add trace class for json-schema-array * shallowly convert namespace state, to preserve Immutable stucts in state * stringify RBE values; don't trim JSON in editor * match user input to an example when non-primitives are expressed in state as strings * update Cypress * don't apply sample values in JsonSchema_Object * support disabling all JsonSchemaForm subcomponents * Core tests * style changes to accomodate Examples * fix version-checking error in Response * disable SCU for Responses * don't stringify Select values * ModelExample: default to Model tab if no example is available; provide a default no example message * don't trim JSON ParamBody inputs * read directly from 2.0 Response.schema instead of inferring a value * show current Example information in RequestBody * show label for Examples dropdown by default * rework Response content ordering * style disabled textareas like other read-only blocks * meta: fix sourcemaps * refactor ESVR setNameForNamespace * protect second half of ternary expession * cypress: `select.examples-select` => `.examples-select > select` * clarify ModelExample.componentWillReceiveProps * add gates/defaults to prevent issues in very bare-boned documents * fix test block organization problem * simplify RequestBodyEditor interface * linter fixes * prettier updates * use plugin system for new components * move ME Cypress helpers to other file
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
export const UPDATE_SELECTED_SERVER = "oas3_set_servers"
|
||||
export const UPDATE_REQUEST_BODY_VALUE = "oas3_set_request_body_value"
|
||||
export const UPDATE_ACTIVE_EXAMPLES_MEMBER = "oas3_set_active_examples_member"
|
||||
export const UPDATE_REQUEST_CONTENT_TYPE = "oas3_set_request_content_type"
|
||||
export const UPDATE_RESPONSE_CONTENT_TYPE = "oas3_set_response_content_type"
|
||||
export const UPDATE_SERVER_VARIABLE_VALUE = "oas3_set_server_variable_value"
|
||||
@@ -21,6 +22,13 @@ export function setRequestBodyValue ({ value, pathMethod }) {
|
||||
}
|
||||
}
|
||||
|
||||
export function setActiveExamplesMember ({ name, pathMethod, contextType, contextName }) {
|
||||
return {
|
||||
type: UPDATE_ACTIVE_EXAMPLES_MEMBER,
|
||||
payload: { name, pathMethod, contextType, contextName }
|
||||
}
|
||||
}
|
||||
|
||||
export function setRequestContentType ({ value, pathMethod }) {
|
||||
return {
|
||||
type: UPDATE_REQUEST_CONTENT_TYPE,
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
import React, { PureComponent } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { fromJS } from "immutable"
|
||||
import { getSampleSchema, stringify } from "core/utils"
|
||||
import { stringify } from "core/utils"
|
||||
|
||||
const NOOP = Function.prototype
|
||||
|
||||
export default class RequestBodyEditor extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
requestBody: PropTypes.object.isRequired,
|
||||
mediaType: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
isExecute: PropTypes.bool,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
value: PropTypes.string,
|
||||
defaultValue: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
mediaType: "application/json",
|
||||
requestBody: fromJS({}),
|
||||
onChange: NOOP,
|
||||
};
|
||||
|
||||
@@ -26,108 +21,75 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
super(props, context)
|
||||
|
||||
this.state = {
|
||||
isEditBox: false,
|
||||
userDidModify: false,
|
||||
value: ""
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setValueToSample.call(this)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(this.props.mediaType !== nextProps.mediaType) {
|
||||
// media type was changed
|
||||
this.setValueToSample(nextProps.mediaType)
|
||||
value: stringify(props.value) || props.defaultValue
|
||||
}
|
||||
|
||||
if(!this.props.isExecute && nextProps.isExecute) {
|
||||
// we just entered execute mode,
|
||||
// so enable editing for convenience
|
||||
this.setState({ isEditBox: true })
|
||||
}
|
||||
// this is the glue that makes sure our initial value gets set as the
|
||||
// current request body value
|
||||
// TODO: achieve this in a selector instead
|
||||
props.onChange(props.value)
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if(this.props.requestBody !== prevProps.requestBody) {
|
||||
// force recalc of value if the request body definition has changed
|
||||
this.setValueToSample(this.props.mediaType)
|
||||
}
|
||||
}
|
||||
applyDefaultValue = (nextProps) => {
|
||||
const { onChange, defaultValue } = (nextProps ? nextProps : this.props)
|
||||
|
||||
setValueToSample = (explicitMediaType) => {
|
||||
this.onChange(this.sample(explicitMediaType))
|
||||
}
|
||||
|
||||
resetValueToSample = (explicitMediaType) => {
|
||||
this.setState({ userDidModify: false })
|
||||
this.setValueToSample(explicitMediaType)
|
||||
}
|
||||
|
||||
sample = (explicitMediaType) => {
|
||||
let { requestBody, mediaType } = this.props
|
||||
let mediaTypeValue = requestBody.getIn(["content", explicitMediaType || mediaType])
|
||||
let schema = mediaTypeValue.get("schema").toJS()
|
||||
let mediaTypeExample = mediaTypeValue.get("example") !== undefined ? stringify(mediaTypeValue.get("example")) : null
|
||||
|
||||
return mediaTypeExample || getSampleSchema(schema, explicitMediaType || mediaType, {
|
||||
includeWriteOnly: true
|
||||
this.setState({
|
||||
value: defaultValue
|
||||
})
|
||||
|
||||
return onChange(defaultValue)
|
||||
}
|
||||
|
||||
onChange = (value) => {
|
||||
this.setState({value})
|
||||
this.props.onChange(value)
|
||||
this.props.onChange(stringify(value))
|
||||
}
|
||||
|
||||
handleOnChange = e => {
|
||||
const { mediaType } = this.props
|
||||
const isJson = /json/i.test(mediaType)
|
||||
const inputValue = isJson ? e.target.value.trim() : e.target.value
|
||||
onDomChange = e => {
|
||||
const inputValue = e.target.value
|
||||
|
||||
this.setState({ userDidModify: true })
|
||||
this.onChange(inputValue)
|
||||
this.setState({
|
||||
value: inputValue,
|
||||
}, () => this.onChange(inputValue))
|
||||
}
|
||||
|
||||
toggleIsEditBox = () => this.setState( state => ({isEditBox: !state.isEditBox}))
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(
|
||||
this.props.value !== nextProps.value &&
|
||||
nextProps.value !== this.state.value
|
||||
) {
|
||||
|
||||
this.setState({
|
||||
value: stringify(nextProps.value)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(!nextProps.value && nextProps.defaultValue && !!this.state.value) {
|
||||
// if new value is falsy, we have a default, AND the falsy value didn't
|
||||
// come from us originally
|
||||
this.applyDefaultValue(nextProps)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
isExecute,
|
||||
getComponent,
|
||||
mediaType,
|
||||
getComponent
|
||||
} = this.props
|
||||
|
||||
const Button = getComponent("Button")
|
||||
const TextArea = getComponent("TextArea")
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
let {
|
||||
value
|
||||
} = this.state
|
||||
|
||||
let { value, isEditBox, userDidModify } = this.state
|
||||
const TextArea = getComponent("TextArea")
|
||||
|
||||
return (
|
||||
<div className="body-param">
|
||||
{
|
||||
isEditBox && isExecute
|
||||
? <TextArea className={"body-param__text"} value={value} onChange={ this.handleOnChange }/>
|
||||
: (value && <HighlightCode className="body-param__example"
|
||||
value={ value }/>)
|
||||
}
|
||||
<div className="body-param-options">
|
||||
<div className="body-param-edit">
|
||||
{
|
||||
!isExecute ? null
|
||||
: <Button className={isEditBox ? "btn cancel body-param__example-edit" : "btn edit body-param__example-edit"}
|
||||
onClick={this.toggleIsEditBox}>{ isEditBox ? "Cancel" : "Edit"}
|
||||
</Button>
|
||||
|
||||
}
|
||||
{ userDidModify &&
|
||||
<Button className="btn ml3" onClick={() => { this.resetValueToSample(mediaType) }}>Reset</Button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TextArea
|
||||
className={"body-param__text"}
|
||||
value={value}
|
||||
onChange={ this.onDomChange }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
@@ -4,6 +4,36 @@ import ImPropTypes from "react-immutable-proptypes"
|
||||
import { Map, OrderedMap, List } from "immutable"
|
||||
import { getCommonExtensions, getSampleSchema, stringify } from "core/utils"
|
||||
|
||||
function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey) {
|
||||
let mediaTypeValue = requestBody.getIn(["content", mediaType])
|
||||
let schema = mediaTypeValue.get("schema").toJS()
|
||||
let example =
|
||||
mediaTypeValue.get("example") !== undefined
|
||||
? stringify(mediaTypeValue.get("example"))
|
||||
: null
|
||||
let currentExamplesValue = mediaTypeValue.getIn([
|
||||
"examples",
|
||||
activeExamplesKey,
|
||||
"value"
|
||||
])
|
||||
|
||||
if (mediaTypeValue.get("examples")) {
|
||||
// the media type DOES have examples
|
||||
return stringify(currentExamplesValue) || ""
|
||||
} else {
|
||||
// the media type DOES NOT have examples
|
||||
return stringify(
|
||||
example ||
|
||||
getSampleSchema(schema, mediaType, {
|
||||
includeWriteOnly: true
|
||||
}) ||
|
||||
""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const RequestBody = ({
|
||||
requestBody,
|
||||
requestBodyValue,
|
||||
@@ -14,7 +44,9 @@ const RequestBody = ({
|
||||
contentType,
|
||||
isExecute,
|
||||
specPath,
|
||||
onChange
|
||||
onChange,
|
||||
activeExamplesKey,
|
||||
updateActiveExamplesKey,
|
||||
}) => {
|
||||
const handleFile = (e) => {
|
||||
onChange(e.target.files[0])
|
||||
@@ -23,6 +55,9 @@ const RequestBody = ({
|
||||
const Markdown = getComponent("Markdown")
|
||||
const ModelExample = getComponent("modelExample")
|
||||
const RequestBodyEditor = getComponent("RequestBodyEditor")
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
const ExamplesSelectValueRetainer = getComponent("ExamplesSelectValueRetainer")
|
||||
const Example = getComponent("Example")
|
||||
|
||||
const { showCommonExtensions } = getConfigs()
|
||||
|
||||
@@ -32,6 +67,11 @@ const RequestBody = ({
|
||||
|
||||
const mediaTypeValue = requestBodyContent.get(contentType, OrderedMap())
|
||||
const schemaForMediaType = mediaTypeValue.get("schema", OrderedMap())
|
||||
const examplesForMediaType = mediaTypeValue.get("examples", OrderedMap())
|
||||
|
||||
const handleExamplesSelect = (key /*, { isSyntheticChange } */) => {
|
||||
updateActiveExamplesKey(key)
|
||||
}
|
||||
|
||||
if(!mediaTypeValue.size) {
|
||||
return null
|
||||
@@ -83,7 +123,7 @@ const RequestBody = ({
|
||||
const format = prop.get("format")
|
||||
const description = prop.get("description")
|
||||
const currentValue = requestBodyValue.get(key)
|
||||
|
||||
|
||||
let initialValue = prop.get("default") || prop.get("example") || ""
|
||||
|
||||
if (initialValue === "" && type === "object") {
|
||||
@@ -139,23 +179,63 @@ const RequestBody = ({
|
||||
{ requestBodyDescription &&
|
||||
<Markdown source={requestBodyDescription} />
|
||||
}
|
||||
<ModelExample
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }
|
||||
expandDepth={1}
|
||||
isExecute={isExecute}
|
||||
schema={mediaTypeValue.get("schema")}
|
||||
specPath={specPath.push("content", contentType)}
|
||||
example={<RequestBodyEditor
|
||||
requestBody={requestBody}
|
||||
onChange={onChange}
|
||||
mediaType={contentType}
|
||||
getComponent={getComponent}
|
||||
isExecute={isExecute}
|
||||
specSelectors={specSelectors}
|
||||
/>}
|
||||
/>
|
||||
{
|
||||
examplesForMediaType ? (
|
||||
<ExamplesSelectValueRetainer
|
||||
examples={examplesForMediaType}
|
||||
currentKey={activeExamplesKey}
|
||||
currentUserInputValue={requestBodyValue}
|
||||
onSelect={handleExamplesSelect}
|
||||
updateValue={onChange}
|
||||
defaultToFirstExample={true}
|
||||
getComponent={getComponent}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
isExecute ? (
|
||||
<div>
|
||||
<RequestBodyEditor
|
||||
value={requestBodyValue}
|
||||
defaultValue={getDefaultRequestBodyValue(
|
||||
requestBody,
|
||||
contentType,
|
||||
activeExamplesKey,
|
||||
)}
|
||||
onChange={onChange}
|
||||
getComponent={getComponent}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<ModelExample
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }
|
||||
expandDepth={1}
|
||||
isExecute={isExecute}
|
||||
schema={mediaTypeValue.get("schema")}
|
||||
specPath={specPath.push("content", contentType)}
|
||||
example={
|
||||
<HighlightCode
|
||||
className="body-param__example"
|
||||
value={stringify(requestBodyValue) || getDefaultRequestBodyValue(
|
||||
requestBody,
|
||||
contentType,
|
||||
activeExamplesKey,
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
examplesForMediaType ? (
|
||||
<Example
|
||||
example={examplesForMediaType.get(activeExamplesKey)}
|
||||
getComponent={getComponent}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -169,7 +249,9 @@ RequestBody.propTypes = {
|
||||
contentType: PropTypes.string,
|
||||
isExecute: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
specPath: PropTypes.array.isRequired
|
||||
specPath: PropTypes.array.isRequired,
|
||||
activeExamplesKey: PropTypes.string,
|
||||
updateActiveExamplesKey: PropTypes.func,
|
||||
}
|
||||
|
||||
export default RequestBody
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
UPDATE_SELECTED_SERVER,
|
||||
UPDATE_REQUEST_BODY_VALUE,
|
||||
UPDATE_ACTIVE_EXAMPLES_MEMBER,
|
||||
UPDATE_REQUEST_CONTENT_TYPE,
|
||||
UPDATE_SERVER_VARIABLE_VALUE,
|
||||
UPDATE_RESPONSE_CONTENT_TYPE
|
||||
@@ -15,6 +16,10 @@ export default {
|
||||
let [path, method] = pathMethod
|
||||
return state.setIn( [ "requestData", path, method, "bodyValue" ], value)
|
||||
},
|
||||
[UPDATE_ACTIVE_EXAMPLES_MEMBER]: (state, { payload: { name, pathMethod, contextType, contextName } } ) =>{
|
||||
let [path, method] = pathMethod
|
||||
return state.setIn( [ "examples", path, method, contextType, contextName, "activeExample" ], name)
|
||||
},
|
||||
[UPDATE_REQUEST_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
|
||||
let [path, method] = pathMethod
|
||||
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
|
||||
|
||||
@@ -26,6 +26,11 @@ export const requestBodyValue = onlyOAS3((state, path, method) => {
|
||||
}
|
||||
)
|
||||
|
||||
export const activeExamplesMember = onlyOAS3((state, path, method, type, name) => {
|
||||
return state.getIn(["examples", path, method, type, name, "activeExample"]) || null
|
||||
}
|
||||
)
|
||||
|
||||
export const requestContentType = onlyOAS3((state, path, method) => {
|
||||
return state.getIn(["requestData", path, method, "requestContentType"]) || null
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 (
|
||||
<div className="opblock-section">
|
||||
<div className="opblock-section-header">
|
||||
<div className="tab-header">
|
||||
<div onClick={() => this.toggleTab("parameters")} className={`tab-item ${this.state.parametersVisible && "active"}`}>
|
||||
<h4 className="opblock-title"><span>Parameters</span></h4>
|
||||
</div>
|
||||
{ operation.get("callbacks") ?
|
||||
(
|
||||
<div onClick={() => this.toggleTab("callbacks")} className={`tab-item ${this.state.callbackVisible && "active"}`}>
|
||||
<h4 className="opblock-title"><span>Callbacks</span></h4>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
</div>
|
||||
{ allowTryItOut ? (
|
||||
<TryItOutButton enabled={ tryItOutEnabled } onCancelClick={ onCancelClick } onTryoutClick={ onTryoutClick } />
|
||||
) : null }
|
||||
</div>
|
||||
{this.state.parametersVisible ? <div className="parameters-container">
|
||||
{ !parameters.count() ? <div className="opblock-description-wrapper"><p>No parameters</p></div> :
|
||||
<div className="table-container">
|
||||
<table className="parameters">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="col col_header parameters-col_name">Name</th>
|
||||
<th className="col col_header parameters-col_description">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
eachMap(parameters, (parameter, i) => (
|
||||
<ParameterRow fn={ fn }
|
||||
getComponent={ getComponent }
|
||||
specPath={specPath.push(i)}
|
||||
getConfigs={ getConfigs }
|
||||
rawParam={ parameter }
|
||||
param={ specSelectors.parameterWithMetaByIdentity(pathMethod, parameter) }
|
||||
key={ parameter.get( "name" ) }
|
||||
onChange={ this.onChange }
|
||||
onChangeConsumes={this.onChangeConsumesWrapper}
|
||||
specSelectors={ specSelectors }
|
||||
specActions={ specActions }
|
||||
pathMethod={ pathMethod }
|
||||
isExecute={ isExecute }/>
|
||||
)).toArray()
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div> : "" }
|
||||
|
||||
{this.state.callbackVisible ? <div className="callbacks-container opblock-description-wrapper">
|
||||
<Callbacks
|
||||
callbacks={Map(operation.get("callbacks"))}
|
||||
specPath={specPath.slice(0, -1).push("callbacks")}
|
||||
/>
|
||||
</div> : "" }
|
||||
{
|
||||
isOAS3() && requestBody && this.state.parametersVisible &&
|
||||
<div className="opblock-section opblock-section-request-body">
|
||||
<div className="opblock-section-header">
|
||||
<h4 className={`opblock-title parameter__name ${requestBody.get("required") && "required"}`}>Request body</h4>
|
||||
<label>
|
||||
<ContentType
|
||||
value={oas3Selectors.requestContentType(...pathMethod)}
|
||||
contentTypes={ requestBody.get("content", List()).keySeq() }
|
||||
onChange={(value) => {
|
||||
oas3Actions.setRequestContentType({ value, pathMethod })
|
||||
}}
|
||||
className="body-param-content-type" />
|
||||
</label>
|
||||
</div>
|
||||
<div className="opblock-description-wrapper">
|
||||
<RequestBody
|
||||
specPath={requestBodySpecPath}
|
||||
requestBody={requestBody}
|
||||
requestBodyValue={oas3Selectors.requestBodyValue(...pathMethod) || Map()}
|
||||
isExecute={isExecute}
|
||||
onChange={(value, path) => {
|
||||
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)}/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default OAS3ComponentWrapFactory(Parameters)
|
||||
Reference in New Issue
Block a user