From 5b6cd88557fd6fd5acf837e30be4110eae6ee084 Mon Sep 17 00:00:00 2001 From: Minasokoni Date: Thu, 9 Nov 2017 12:18:10 -0800 Subject: [PATCH 1/7] removed set width --- src/style/_models.scss | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) 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 From e33de3049f93e8534de7095a3a0a7b1796e215e6 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Thu, 9 Nov 2017 16:28:53 -0800 Subject: [PATCH 2/7] Refactor Operation component to not trigger its own re-render --- src/core/components/object-model.jsx | 4 +++ src/core/components/operation.jsx | 43 ++++++++-------------------- src/core/components/operations.jsx | 11 ++++--- 3 files changed, 23 insertions(+), 35 deletions(-) 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..67cbbabe 100644 --- a/src/core/components/operations.jsx +++ b/src/core/components/operations.jsx @@ -1,4 +1,5 @@ import React from "react" +import { List } from "immutable" import PropTypes from "prop-types" import { helpers } from "swagger-client" import { createDeepLinkPath, sanitizeUrl } from "core/utils" @@ -127,7 +128,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 +137,12 @@ export default class Operations extends React.Component { return Date: Thu, 9 Nov 2017 16:48:22 -0800 Subject: [PATCH 3/7] Create newSpecErrBatch for more wealth and prosperity --- src/core/plugins/err/actions.js | 8 ++++++++ src/core/plugins/err/reducers.js | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/core/plugins/err/actions.js b/src/core/plugins/err/actions.js index d7051b74..40fd1121 100644 --- a/src/core/plugins/err/actions.js +++ b/src/core/plugins/err/actions.js @@ -3,6 +3,7 @@ import serializeError from "serialize-error" export const NEW_THROWN_ERR = "err_new_thrown_err" export const NEW_THROWN_ERR_BATCH = "err_new_thrown_err_batch" export const NEW_SPEC_ERR = "err_new_spec_err" +export const NEW_SPEC_ERR_BATCH = "err_new_spec_err_batch" export const NEW_AUTH_ERR = "err_new_auth_err" export const CLEAR = "err_clear" @@ -27,6 +28,13 @@ export function newSpecErr(err) { } } +export function newSpecErrBatch(errArray) { + return { + type: NEW_SPEC_ERR_BATCH, + payload: errArray + } +} + export function newAuthErr(err) { return { type: NEW_AUTH_ERR, diff --git a/src/core/plugins/err/reducers.js b/src/core/plugins/err/reducers.js index 6b0c5d2e..795f5dd5 100644 --- a/src/core/plugins/err/reducers.js +++ b/src/core/plugins/err/reducers.js @@ -2,6 +2,7 @@ import { NEW_THROWN_ERR, NEW_THROWN_ERR_BATCH, NEW_SPEC_ERR, + NEW_SPEC_ERR_BATCH, NEW_AUTH_ERR, CLEAR } from "./actions" @@ -45,6 +46,15 @@ export default function(system) { .update("errors", errors => 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)) From bfe266732663ba2a5dd25d8d7694cf7aa92cc2f1 Mon Sep 17 00:00:00 2001 From: kyle Date: Thu, 9 Nov 2017 19:28:20 -0800 Subject: [PATCH 4/7] Remove unused `Immutable.List` import --- src/core/components/operations.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/components/operations.jsx b/src/core/components/operations.jsx index 67cbbabe..b4958884 100644 --- a/src/core/components/operations.jsx +++ b/src/core/components/operations.jsx @@ -1,5 +1,4 @@ import React from "react" -import { List } from "immutable" import PropTypes from "prop-types" import { helpers } from "swagger-client" import { createDeepLinkPath, sanitizeUrl } from "core/utils" From d92a27bdabff1a1c560a6d1014f531dba9636d1d Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 10 Nov 2017 10:40:03 -0800 Subject: [PATCH 5/7] Add failing tests --- test/core/utils.js | 8 ++++++++ 1 file changed, 8 insertions(+) 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, From 365585ceeab78cb962f4907b72f2494c5a244198 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 10 Nov 2017 10:45:19 -0800 Subject: [PATCH 6/7] Add check for `0` value for number and integer parameter values --- src/core/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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") From 82a2ee9a3479689b48226df1eb53c3d931d21066 Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Fri, 10 Nov 2017 16:56:38 -0800 Subject: [PATCH 7/7] Add safe string method access for toTitleCase --- src/core/components/errors.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(" ")