diff --git a/src/core/components/errors.jsx b/src/core/components/errors.jsx index c72dd2fd..c3d6cf93 100644 --- a/src/core/components/errors.jsx +++ b/src/core/components/errors.jsx @@ -113,7 +113,7 @@ const SpecErrorItem = ( { error, jumpToLine } ) => { } function toTitleCase(str) { - return str + return (str || "") .split(" ") .map(substr => substr[0].toUpperCase() + substr.slice(1)) .join(" ") diff --git a/src/core/components/object-model.jsx b/src/core/components/object-model.jsx index 9ab4e99a..db8adfd5 100644 --- a/src/core/components/object-model.jsx +++ b/src/core/components/object-model.jsx @@ -21,6 +21,10 @@ export default class ObjectModel extends Component { let { specSelectors } = otherProps let { isOAS3 } = specSelectors + if(!schema) { + return null + } + let description = schema.get("description") let properties = schema.get("properties") let additionalProperties = schema.get("additionalProperties") diff --git a/src/core/components/operation.jsx b/src/core/components/operation.jsx index d1cc6786..457ee863 100644 --- a/src/core/components/operation.jsx +++ b/src/core/components/operation.jsx @@ -12,8 +12,10 @@ export default class Operation extends PureComponent { method: PropTypes.string.isRequired, operation: PropTypes.object.isRequired, showSummary: PropTypes.bool, + isShown: PropTypes.bool.isRequired, - isShownKey: CustomPropTypes.arrayOrString.isRequired, + tagKey: PropTypes.string, + operationKey: PropTypes.string, jumpToKey: CustomPropTypes.arrayOrString.isRequired, allowTryItOut: PropTypes.bool, @@ -52,38 +54,16 @@ export default class Operation extends PureComponent { } componentWillReceiveProps(nextProps) { - const defaultContentType = "application/json" - let { specActions, path, method, operation } = nextProps - let producesValue = operation.get("produces_value") - let produces = operation.get("produces") - let consumes = operation.get("consumes") - let consumesValue = operation.get("consumes_value") - if(nextProps.response !== this.props.response) { this.setState({ executeInProgress: false }) } - - if (producesValue === undefined) { - producesValue = produces && produces.size ? produces.first() : defaultContentType - specActions.changeProducesValue([path, method], producesValue) - } - - if (consumesValue === undefined) { - consumesValue = consumes && consumes.size ? consumes.first() : defaultContentType - specActions.changeConsumesValue([path, method], consumesValue) - } } toggleShown =() => { - let { layoutActions, isShownKey } = this.props - layoutActions.show(isShownKey, !this.isShown()) - } + let { layoutActions, tagKey, operationKey, isShown } = this.props + const isShownKey = ["operations", tagKey, operationKey] - isShown =() => { - let { layoutSelectors, isShownKey, getConfigs } = this.props - let { docExpansion } = getConfigs() - - return layoutSelectors.isShown(isShownKey, docExpansion === "full" ) // Here is where we set the default + layoutActions.show(isShownKey, !isShown) } onTryoutClick =() => { @@ -102,7 +82,9 @@ export default class Operation extends PureComponent { render() { let { - isShownKey, + operationKey, + tagKey, + isShown, jumpToKey, path, method, @@ -156,18 +138,17 @@ export default class Operation extends PureComponent { } let { tryItOutEnabled } = this.state - let shown = this.isShown() let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method ) return ( -
+
{method.toUpperCase()} e.preventDefault() : null} - href={isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : null}> + href={isDeepLinkingEnabled ? `#/${tagKey}/${operationKey}` : null}> {path} @@ -193,7 +174,7 @@ export default class Operation extends PureComponent { }
- +
{ deprecated &&

Warning: Deprecated

} { description && diff --git a/src/core/components/operations.jsx b/src/core/components/operations.jsx index 6d760d53..b4958884 100644 --- a/src/core/components/operations.jsx +++ b/src/core/components/operations.jsx @@ -127,7 +127,8 @@ export default class Operations extends React.Component { const operationId = op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id") - const isShownKey = ["operations", createDeepLinkPath(tag), createDeepLinkPath(operationId)] + const tagKey = createDeepLinkPath(tag) + const operationKey = createDeepLinkPath(operationId) const allowTryItOut = specSelectors.allowTryItOutFor(op.get("path"), op.get("method")) const response = specSelectors.responseFor(op.get("path"), op.get("method")) @@ -135,11 +136,12 @@ export default class Operations extends React.Component { return transformErrors(errors, system.getSystem())) }, + [NEW_SPEC_ERR_BATCH]: (state, { payload }) => { + payload = payload.map(err => { + return fromJS(Object.assign(DEFAULT_ERROR_STRUCTURE, err, { type: "spec" })) + }) + return state + .update("errors", errors => (errors || List()).concat( fromJS( payload )) ) + .update("errors", errors => transformErrors(errors, system.getSystem())) + }, + [NEW_AUTH_ERR]: (state, { payload }) => { let error = fromJS(Object.assign({}, payload)) diff --git a/src/core/utils.js b/src/core/utils.js index 4595c798..8babdbd8 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -494,8 +494,8 @@ export const validateParam = (param, isXml, isOAS3 = false) => { let listCheck = type === "array" && Im.List.isList(value) && value.count() let fileCheck = type === "file" && value instanceof win.File let booleanCheck = type === "boolean" && (value || value === false) - let numberCheck = type === "number" && value - let integerCheck = type === "integer" && value + let numberCheck = type === "number" && (value || value === 0) + let integerCheck = type === "integer" && (value || value === 0) if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) { errors.push("Required field is not provided") diff --git a/src/style/_models.scss b/src/style/_models.scss index 23b349d6..feb46a87 100644 --- a/src/style/_models.scss +++ b/src/style/_models.scss @@ -3,14 +3,16 @@ font-size: 12px; font-weight: 300; + @include text_code(); + .deprecated { - span, td { - color: $model-deprecated-font-color !important; - } + span, + td + { + color: $model-deprecated-font-color !important; + } } - - @include text_code(); &-toggle { font-size: 10px; @@ -87,7 +89,8 @@ background: rgba($model-hint-background-color,.7); } - p { + p + { margin: 0 0 1em 0; } } @@ -106,6 +109,7 @@ section.models h4 { margin: 0 0 5px 0; + border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3); } } @@ -114,6 +118,7 @@ section.models font-size: 16px; display: flex; + align-items: center; margin: 0; padding: 10px 20px 10px 10px; @@ -122,7 +127,6 @@ section.models transition: all .2s; @include text_headline($section-models-h4-font-color); - align-items: center; svg { @@ -202,7 +206,7 @@ section.models &.deprecated { - opacity: .5; + opacity: .5; } } @@ -218,14 +222,16 @@ section.models { font-size: 16px; font-weight: 600; + margin-right: 1em; + @include text_headline($_color-delete); } span { - > span.model + > span.model { .brace-close { @@ -237,8 +243,8 @@ span .prop-name { display: inline-block; + margin-right: 1em; - width: 8em; } .prop-type diff --git a/test/core/utils.js b/test/core/utils.js index 918d8431..73861845 100644 --- a/test/core/utils.js +++ b/test/core/utils.js @@ -700,6 +700,14 @@ describe("utils", function() { } assertValidateParam(param, ["Required field is not provided"]) + // valid integer, but 0 is falsy in JS + param = { + required: true, + type: "integer", + value: 0 + } + assertValidateParam(param, []) + // valid integer param = { required: true,