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:
kyle
2019-06-29 19:52:51 +01:00
committed by GitHub
parent 332ddaedcd
commit 23d7260f92
34 changed files with 3148 additions and 653 deletions

View File

@@ -4,7 +4,6 @@ import { List, fromJS } from "immutable"
import cx from "classnames"
import ImPropTypes from "react-immutable-proptypes"
import DebounceInput from "react-debounce-input"
import { getSampleSchema } from "core/utils"
//import "less/json-schema-form"
const noop = ()=> {}
@@ -18,7 +17,8 @@ const JsonSchemaPropShape = {
errors: ImPropTypes.list,
required: PropTypes.bool,
dispatchInitialValue: PropTypes.bool,
description: PropTypes.any
description: PropTypes.any,
disabled: PropTypes.bool,
}
const JsonSchemaDefaultProps = {
@@ -43,7 +43,7 @@ export class JsonSchemaForm extends Component {
}
render() {
let { schema, errors, value, onChange, getComponent, fn } = this.props
let { schema, errors, value, onChange, getComponent, fn, disabled } = this.props
if(schema.toJS)
schema = schema.toJS()
@@ -51,7 +51,7 @@ export class JsonSchemaForm extends Component {
let { type, format="" } = schema
let Comp = (format ? getComponent(`JsonSchema_${type}_${format}`) : getComponent(`JsonSchema_${type}`)) || getComponent("JsonSchema_string")
return <Comp { ...this.props } errors={errors} fn={fn} getComponent={getComponent} value={value} onChange={onChange} schema={schema}/>
return <Comp { ...this.props } errors={errors} fn={fn} getComponent={getComponent} value={value} onChange={onChange} schema={schema} disabled={disabled}/>
}
}
@@ -65,7 +65,7 @@ export class JsonSchema_string extends Component {
}
onEnumChange = (val) => this.props.onChange(val)
render() {
let { getComponent, value, schema, errors, required, description } = this.props
let { getComponent, value, schema, errors, required, description, disabled } = this.props
let enumValue = schema["enum"]
errors = errors.toJS ? errors.toJS() : []
@@ -80,7 +80,7 @@ export class JsonSchema_string extends Component {
onChange={ this.onEnumChange }/>)
}
const isDisabled = schema["in"] === "formData" && !("FormData" in window)
const isDisabled = disabled || (schema["in"] === "formData" && !("FormData" in window))
const Input = getComponent("Input")
if (schema["type"] === "file") {
return (<Input type="file"
@@ -149,7 +149,7 @@ export class JsonSchema_array extends PureComponent {
}
render() {
let { getComponent, required, schema, errors, fn } = this.props
let { getComponent, required, schema, errors, fn, disabled } = this.props
errors = errors.toJS ? errors.toJS() : []
@@ -167,13 +167,14 @@ export class JsonSchema_array extends PureComponent {
title={ errors.length ? errors : ""}
multiple={ true }
value={ value }
disabled={disabled}
allowedValues={ enumValue }
allowEmptyValue={ !required }
onChange={ this.onEnumChange }/>)
}
return (
<div>
<div className="json-schema-array">
{ !value || !value.count || value.count() < 1 ? null :
value.map( (item,i) => {
let schema = Object.assign({}, itemSchema)
@@ -183,13 +184,32 @@ export class JsonSchema_array extends PureComponent {
}
return (
<div key={i} className="json-schema-form-item">
<JsonSchemaForm fn={fn} getComponent={getComponent} value={item} onChange={(val) => this.onItemChange(val, i)} schema={schema} />
<Button className="btn btn-sm json-schema-form-item-remove" onClick={()=> this.removeItem(i)} > - </Button>
<JsonSchemaForm
fn={fn}
getComponent={getComponent}
value={item}
onChange={(val) => this.onItemChange(val, i)}
schema={schema}
disabled={disabled}
/>
{ !disabled ? (
<Button
className="btn btn-sm json-schema-form-item-remove"
onClick={()=> this.removeItem(i)}
> - </Button>
) : null }
</div>
)
}).toArray()
}
<Button className={`btn btn-sm json-schema-form-item-add ${errors.length ? "invalid" : null}`} onClick={this.addItem}> Add item </Button>
{ !disabled ? (
<Button
className={`btn btn-sm json-schema-form-item-add ${errors.length ? "invalid" : null}`}
onClick={this.addItem}
>
Add item
</Button>
) : null }
</div>
)
}
@@ -201,7 +221,7 @@ export class JsonSchema_boolean extends Component {
onEnumChange = (val) => this.props.onChange(val)
render() {
let { getComponent, value, errors, schema, required } = this.props
let { getComponent, value, errors, schema, required, disabled } = this.props
errors = errors.toJS ? errors.toJS() : []
const Select = getComponent("Select")
@@ -209,6 +229,7 @@ export class JsonSchema_boolean extends Component {
return (<Select className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
value={ String(value) }
disabled={disabled}
allowedValues={ fromJS(schema.enum || ["true", "false"]) }
allowEmptyValue={ !schema.enum || !required }
onChange={ this.onEnumChange }/>)
@@ -223,16 +244,6 @@ export class JsonSchema_object extends PureComponent {
static propTypes = JsonSchemaPropShape
static defaultProps = JsonSchemaDefaultProps
componentDidMount() {
if(!this.props.value && this.props.schema) {
this.resetValueToSample()
}
}
resetValueToSample = () => {
this.onChange(getSampleSchema(this.props.schema) )
}
onChange = (value) => {
this.props.onChange(value)
}
@@ -247,7 +258,8 @@ export class JsonSchema_object extends PureComponent {
let {
getComponent,
value,
errors
errors,
disabled
} = this.props
const TextArea = getComponent("TextArea")
@@ -258,6 +270,7 @@ export class JsonSchema_object extends PureComponent {
className={cx({ invalid: errors.size })}
title={ errors.size ? errors.join(", ") : ""}
value={value}
disabled={disabled}
onChange={ this.handleOnChange }/>
</div>
)
@@ -267,4 +280,4 @@ export class JsonSchema_object extends PureComponent {
function valueOrEmptyList(value) {
return List.isList(value) ? value : List()
}
}