Revert "revert: feat: Allow to skip submitting empty values in form data (#5830)" (#6227)

This reverts commit 1b6cb7d1bf.
This commit is contained in:
Tim Lai
2020-07-15 16:07:32 -07:00
committed by GitHub
parent 1b6cb7d1bf
commit eacc7b92d1
10 changed files with 75 additions and 27 deletions

View File

@@ -1,24 +1,19 @@
import React from "react" import React from "react"
import cx from "classnames" import cx from "classnames"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
export const ParameterIncludeEmpty = ({ param, isIncluded, onChange, isDisabled }) => { export const ParameterIncludeEmpty = ({ isIncluded, onChange, isDisabled }) => {
const onCheckboxChange = e => { const onCheckboxChange = e => {
onChange(e.target.checked) onChange(e.target.checked)
} }
if(!param.get("allowEmptyValue")) { return <label className={cx("parameter__empty_value_toggle", {
return null
}
return <div className={cx("parameter__empty_value_toggle", {
"disabled": isDisabled "disabled": isDisabled
})}> })}>
<input type="checkbox" disabled={isDisabled} checked={!isDisabled && isIncluded} onChange={onCheckboxChange} /> <input type="checkbox" disabled={isDisabled} checked={!isDisabled && isIncluded} onChange={onCheckboxChange} />
Send empty value Send empty value
</div> </label>
} }
ParameterIncludeEmpty.propTypes = { ParameterIncludeEmpty.propTypes = {
param: ImPropTypes.map.isRequired,
isIncluded: PropTypes.bool.isRequired, isIncluded: PropTypes.bool.isRequired,
isDisabled: PropTypes.bool.isRequired, isDisabled: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,

View File

@@ -3,7 +3,7 @@ import { Map, List } from "immutable"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes" import ImPropTypes from "react-immutable-proptypes"
import win from "core/window" import win from "core/window"
import { getSampleSchema, getExtensions, getCommonExtensions, numberToString, stringify } from "core/utils" import { getSampleSchema, getExtensions, getCommonExtensions, numberToString, stringify, isEmptyValue } from "core/utils"
import getParameterSchema from "../../helpers/get-parameter-schema.js" import getParameterSchema from "../../helpers/get-parameter-schema.js"
export default class ParameterRow extends Component { export default class ParameterRow extends Component {
@@ -343,12 +343,11 @@ export default class ParameterRow extends Component {
} }
{ {
!bodyParam && isExecute ? !bodyParam && isExecute && param.get("allowEmptyValue") ?
<ParameterIncludeEmpty <ParameterIncludeEmpty
onChange={this.onChangeIncludeEmpty} onChange={this.onChangeIncludeEmpty}
isIncluded={specSelectors.parameterInclusionSettingFor(pathMethod, param.get("name"), param.get("in"))} isIncluded={specSelectors.parameterInclusionSettingFor(pathMethod, param.get("name"), param.get("in"))}
isDisabled={value && value.size !== 0} isDisabled={!isEmptyValue(value)} />
param={param} />
: null : null
} }

View File

@@ -196,6 +196,7 @@ export default class Parameters extends Component {
specPath={specPath.slice(0, -1).push("requestBody")} specPath={specPath.slice(0, -1).push("requestBody")}
requestBody={requestBody} requestBody={requestBody}
requestBodyValue={oas3Selectors.requestBodyValue(...pathMethod)} requestBodyValue={oas3Selectors.requestBodyValue(...pathMethod)}
requestBodyInclusionSetting={oas3Selectors.requestBodyInclusionSetting(...pathMethod)}
isExecute={isExecute} isExecute={isExecute}
activeExamplesKey={oas3Selectors.activeExamplesMember( activeExamplesKey={oas3Selectors.activeExamplesMember(
...pathMethod, ...pathMethod,
@@ -222,6 +223,13 @@ export default class Parameters extends Component {
} }
oas3Actions.setRequestBodyValue({ value, pathMethod }) oas3Actions.setRequestBodyValue({ value, pathMethod })
}} }}
onChangeIncludeEmpty={(name, value) => {
oas3Actions.setRequestBodyInclusion({
pathMethod,
value,
name,
})
}}
contentType={oas3Selectors.requestContentType(...pathMethod)}/> contentType={oas3Selectors.requestContentType(...pathMethod)}/>
</div> </div>
</div> </div>

View File

@@ -3,6 +3,7 @@
export const UPDATE_SELECTED_SERVER = "oas3_set_servers" export const UPDATE_SELECTED_SERVER = "oas3_set_servers"
export const UPDATE_REQUEST_BODY_VALUE = "oas3_set_request_body_value" export const UPDATE_REQUEST_BODY_VALUE = "oas3_set_request_body_value"
export const UPDATE_REQUEST_BODY_INCLUSION = "oas3_set_request_body_inclusion"
export const UPDATE_ACTIVE_EXAMPLES_MEMBER = "oas3_set_active_examples_member" 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_REQUEST_CONTENT_TYPE = "oas3_set_request_content_type"
export const UPDATE_RESPONSE_CONTENT_TYPE = "oas3_set_response_content_type" export const UPDATE_RESPONSE_CONTENT_TYPE = "oas3_set_response_content_type"
@@ -22,6 +23,13 @@ export function setRequestBodyValue ({ value, pathMethod }) {
} }
} }
export function setRequestBodyInclusion ({ value, pathMethod, name }) {
return {
type: UPDATE_REQUEST_BODY_INCLUSION,
payload: { value, pathMethod, name }
}
}
export function setActiveExamplesMember ({ name, pathMethod, contextType, contextName }) { export function setActiveExamplesMember ({ name, pathMethod, contextType, contextName }) {
return { return {
type: UPDATE_ACTIVE_EXAMPLES_MEMBER, type: UPDATE_ACTIVE_EXAMPLES_MEMBER,

View File

@@ -2,7 +2,7 @@ import React from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes" import ImPropTypes from "react-immutable-proptypes"
import { Map, OrderedMap, List } from "immutable" import { Map, OrderedMap, List } from "immutable"
import { getCommonExtensions, getSampleSchema, stringify } from "core/utils" import { getCommonExtensions, getSampleSchema, stringify, isEmptyValue } from "core/utils"
function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey) { function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey) {
let mediaTypeValue = requestBody.getIn(["content", mediaType]) let mediaTypeValue = requestBody.getIn(["content", mediaType])
@@ -37,6 +37,7 @@ function getDefaultRequestBodyValue(requestBody, mediaType, activeExamplesKey) {
const RequestBody = ({ const RequestBody = ({
requestBody, requestBody,
requestBodyValue, requestBodyValue,
requestBodyInclusionSetting,
getComponent, getComponent,
getConfigs, getConfigs,
specSelectors, specSelectors,
@@ -45,6 +46,7 @@ const RequestBody = ({
isExecute, isExecute,
specPath, specPath,
onChange, onChange,
onChangeIncludeEmpty,
activeExamplesKey, activeExamplesKey,
updateActiveExamplesKey, updateActiveExamplesKey,
}) => { }) => {
@@ -58,6 +60,7 @@ const RequestBody = ({
const HighlightCode = getComponent("highlightCode") const HighlightCode = getComponent("highlightCode")
const ExamplesSelectValueRetainer = getComponent("ExamplesSelectValueRetainer") const ExamplesSelectValueRetainer = getComponent("ExamplesSelectValueRetainer")
const Example = getComponent("Example") const Example = getComponent("Example")
const ParameterIncludeEmpty = getComponent("ParameterIncludeEmpty")
const { showCommonExtensions } = getConfigs() const { showCommonExtensions } = getConfigs()
@@ -155,17 +158,26 @@ const RequestBody = ({
</td> </td>
<td className="parameters-col_description"> <td className="parameters-col_description">
<Markdown source={ description }></Markdown> <Markdown source={ description }></Markdown>
{isExecute ? <div><JsonSchemaForm {isExecute ? <div>
fn={fn} <JsonSchemaForm
dispatchInitialValue={!isFile} fn={fn}
schema={prop} dispatchInitialValue={!isFile}
description={key} schema={prop}
getComponent={getComponent} description={key}
value={currentValue === undefined ? initialValue : currentValue} getComponent={getComponent}
onChange={(value) => { value={currentValue === undefined ? initialValue : currentValue}
onChange(value, [key]) onChange={(value) => {
}} onChange(value, [key])
/></div> : null } }}
/>
{required ? null : (
<ParameterIncludeEmpty
onChange={(value) => onChangeIncludeEmpty(key, value)}
isIncluded={requestBodyInclusionSetting.get(key)}
isDisabled={!isEmptyValue(currentValue)}
/>
)}
</div> : null }
</td> </td>
</tr> </tr>
}) })
@@ -243,6 +255,7 @@ const RequestBody = ({
RequestBody.propTypes = { RequestBody.propTypes = {
requestBody: ImPropTypes.orderedMap.isRequired, requestBody: ImPropTypes.orderedMap.isRequired,
requestBodyValue: ImPropTypes.orderedMap.isRequired, requestBodyValue: ImPropTypes.orderedMap.isRequired,
requestBodyInclusionSetting: ImPropTypes.Map.isRequired,
getComponent: PropTypes.func.isRequired, getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired, getConfigs: PropTypes.func.isRequired,
fn: PropTypes.object.isRequired, fn: PropTypes.object.isRequired,
@@ -250,6 +263,7 @@ RequestBody.propTypes = {
contentType: PropTypes.string, contentType: PropTypes.string,
isExecute: PropTypes.bool.isRequired, isExecute: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
onChangeIncludeEmpty: PropTypes.func.isRequired,
specPath: PropTypes.array.isRequired, specPath: PropTypes.array.isRequired,
activeExamplesKey: PropTypes.string, activeExamplesKey: PropTypes.string,
updateActiveExamplesKey: PropTypes.func, updateActiveExamplesKey: PropTypes.func,

View File

@@ -1,6 +1,7 @@
import { import {
UPDATE_SELECTED_SERVER, UPDATE_SELECTED_SERVER,
UPDATE_REQUEST_BODY_VALUE, UPDATE_REQUEST_BODY_VALUE,
UPDATE_REQUEST_BODY_INCLUSION,
UPDATE_ACTIVE_EXAMPLES_MEMBER, UPDATE_ACTIVE_EXAMPLES_MEMBER,
UPDATE_REQUEST_CONTENT_TYPE, UPDATE_REQUEST_CONTENT_TYPE,
UPDATE_SERVER_VARIABLE_VALUE, UPDATE_SERVER_VARIABLE_VALUE,
@@ -16,6 +17,10 @@ export default {
let [path, method] = pathMethod let [path, method] = pathMethod
return state.setIn( [ "requestData", path, method, "bodyValue" ], value) return state.setIn( [ "requestData", path, method, "bodyValue" ], value)
}, },
[UPDATE_REQUEST_BODY_INCLUSION]: (state, { payload: { value, pathMethod, name } } ) =>{
let [path, method] = pathMethod
return state.setIn( [ "requestData", path, method, "bodyInclusion", name ], value)
},
[UPDATE_ACTIVE_EXAMPLES_MEMBER]: (state, { payload: { name, pathMethod, contextType, contextName } } ) =>{ [UPDATE_ACTIVE_EXAMPLES_MEMBER]: (state, { payload: { name, pathMethod, contextType, contextName } } ) =>{
let [path, method] = pathMethod let [path, method] = pathMethod
return state.setIn( [ "examples", path, method, contextType, contextName, "activeExample" ], name) return state.setIn( [ "examples", path, method, contextType, contextName, "activeExample" ], name)

View File

@@ -1,4 +1,4 @@
import { OrderedMap } from "immutable" import { OrderedMap, Map } from "immutable"
import { isOAS3 as isOAS3Helper } from "./helpers" import { isOAS3 as isOAS3Helper } from "./helpers"
@@ -26,6 +26,11 @@ export const requestBodyValue = onlyOAS3((state, path, method) => {
} }
) )
export const requestBodyInclusionSetting = onlyOAS3((state, path, method) => {
return state.getIn(["requestData", path, method, "bodyInclusion"]) || Map()
}
)
export const activeExamplesMember = onlyOAS3((state, path, method, type, name) => { export const activeExamplesMember = onlyOAS3((state, path, method, type, name) => {
return state.getIn(["examples", path, method, type, name, "activeExample"]) || null return state.getIn(["examples", path, method, type, name, "activeExample"]) || null
} }

View File

@@ -5,7 +5,7 @@ import serializeError from "serialize-error"
import isString from "lodash/isString" import isString from "lodash/isString"
import debounce from "lodash/debounce" import debounce from "lodash/debounce"
import set from "lodash/set" import set from "lodash/set"
import { isJSONObject, paramToValue } from "core/utils" import { isJSONObject, paramToValue, isEmptyValue } from "core/utils"
// Actions conform to FSA (flux-standard-actions) // Actions conform to FSA (flux-standard-actions)
// {type: string,payload: Any|Error, meta: obj, error: bool} // {type: string,payload: Any|Error, meta: obj, error: bool}
@@ -401,11 +401,12 @@ export const executeRequest = (req) =>
req.requestContentType = oas3Selectors.requestContentType(pathName, method) req.requestContentType = oas3Selectors.requestContentType(pathName, method)
req.responseContentType = oas3Selectors.responseContentType(pathName, method) || "*/*" req.responseContentType = oas3Selectors.responseContentType(pathName, method) || "*/*"
const requestBody = oas3Selectors.requestBodyValue(pathName, method) const requestBody = oas3Selectors.requestBodyValue(pathName, method)
const requestBodyInclusionSetting = oas3Selectors.requestBodyInclusionSetting(pathName, method)
if(isJSONObject(requestBody)) { if(isJSONObject(requestBody)) {
req.requestBody = JSON.parse(requestBody) req.requestBody = JSON.parse(requestBody)
} else if(requestBody && requestBody.toJS) { } else if(requestBody && requestBody.toJS) {
req.requestBody = requestBody.toJS() req.requestBody = requestBody.filter((value, key) => !isEmptyValue(value) || requestBodyInclusionSetting.get(key)).toJS()
} else{ } else{
req.requestBody = requestBody req.requestBody = requestBody
} }

View File

@@ -956,3 +956,15 @@ function b64toB64UrlEncoded(str) {
.replace(/\//g, "_") .replace(/\//g, "_")
.replace(/=/g, "") .replace(/=/g, "")
} }
export const isEmptyValue = (value) => {
if (!value) {
return true
}
if (isImmutable(value) && value.isEmpty()) {
return true
}
return false
}

View File

@@ -157,6 +157,7 @@ table
} }
.parameter__empty_value_toggle { .parameter__empty_value_toggle {
display: block;
font-size: 13px; font-size: 13px;
padding-top: 5px; padding-top: 5px;
padding-bottom: 12px; padding-bottom: 12px;