Merge branch 'master' into feature/validation_tooltips

This commit is contained in:
kyle
2017-11-10 18:40:14 -08:00
committed by GitHub
9 changed files with 67 additions and 48 deletions

View File

@@ -113,7 +113,7 @@ const SpecErrorItem = ( { error, jumpToLine } ) => {
} }
function toTitleCase(str) { function toTitleCase(str) {
return str return (str || "")
.split(" ") .split(" ")
.map(substr => substr[0].toUpperCase() + substr.slice(1)) .map(substr => substr[0].toUpperCase() + substr.slice(1))
.join(" ") .join(" ")

View File

@@ -21,6 +21,10 @@ export default class ObjectModel extends Component {
let { specSelectors } = otherProps let { specSelectors } = otherProps
let { isOAS3 } = specSelectors let { isOAS3 } = specSelectors
if(!schema) {
return null
}
let description = schema.get("description") let description = schema.get("description")
let properties = schema.get("properties") let properties = schema.get("properties")
let additionalProperties = schema.get("additionalProperties") let additionalProperties = schema.get("additionalProperties")

View File

@@ -12,8 +12,10 @@ export default class Operation extends PureComponent {
method: PropTypes.string.isRequired, method: PropTypes.string.isRequired,
operation: PropTypes.object.isRequired, operation: PropTypes.object.isRequired,
showSummary: PropTypes.bool, showSummary: PropTypes.bool,
isShown: PropTypes.bool.isRequired,
isShownKey: CustomPropTypes.arrayOrString.isRequired, tagKey: PropTypes.string,
operationKey: PropTypes.string,
jumpToKey: CustomPropTypes.arrayOrString.isRequired, jumpToKey: CustomPropTypes.arrayOrString.isRequired,
allowTryItOut: PropTypes.bool, allowTryItOut: PropTypes.bool,
@@ -52,38 +54,16 @@ export default class Operation extends PureComponent {
} }
componentWillReceiveProps(nextProps) { 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) { if(nextProps.response !== this.props.response) {
this.setState({ executeInProgress: false }) 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 =() => { toggleShown =() => {
let { layoutActions, isShownKey } = this.props let { layoutActions, tagKey, operationKey, isShown } = this.props
layoutActions.show(isShownKey, !this.isShown()) const isShownKey = ["operations", tagKey, operationKey]
}
isShown =() => { layoutActions.show(isShownKey, !isShown)
let { layoutSelectors, isShownKey, getConfigs } = this.props
let { docExpansion } = getConfigs()
return layoutSelectors.isShown(isShownKey, docExpansion === "full" ) // Here is where we set the default
} }
onTryoutClick =() => { onTryoutClick =() => {
@@ -102,7 +82,9 @@ export default class Operation extends PureComponent {
render() { render() {
let { let {
isShownKey, operationKey,
tagKey,
isShown,
jumpToKey, jumpToKey,
path, path,
method, method,
@@ -156,18 +138,17 @@ export default class Operation extends PureComponent {
} }
let { tryItOutEnabled } = this.state let { tryItOutEnabled } = this.state
let shown = this.isShown()
let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method ) let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method )
return ( return (
<div className={deprecated ? "opblock opblock-deprecated" : shown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} > <div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={`operations-${tagKey}-${operationKey}`} >
<div className={`opblock-summary opblock-summary-${method}`} onClick={this.toggleShown} > <div className={`opblock-summary opblock-summary-${method}`} onClick={this.toggleShown} >
<span className="opblock-summary-method">{method.toUpperCase()}</span> <span className="opblock-summary-method">{method.toUpperCase()}</span>
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } > <span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } >
<a <a
className="nostyle" className="nostyle"
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null} onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
href={isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : null}> href={isDeepLinkingEnabled ? `#/${tagKey}/${operationKey}` : null}>
<span>{path}</span> <span>{path}</span>
</a> </a>
<JumpToPath path={jumpToKey} /> <JumpToPath path={jumpToKey} />
@@ -193,7 +174,7 @@ export default class Operation extends PureComponent {
} }
</div> </div>
<Collapse isOpened={shown}> <Collapse isOpened={isShown}>
<div className="opblock-body"> <div className="opblock-body">
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>} { deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>}
{ description && { description &&

View File

@@ -127,7 +127,8 @@ export default class Operations extends React.Component {
const operationId = const operationId =
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id") 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 allowTryItOut = specSelectors.allowTryItOutFor(op.get("path"), op.get("method"))
const response = specSelectors.responseFor(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 <Operation return <Operation
{...op.toObject()} {...op.toObject()}
tagKey={tagKey}
isShownKey={isShownKey} operationKey={operationKey}
isShown={layoutSelectors.isShown(["operations", tagKey, operationKey])}
jumpToKey={jumpToKey} jumpToKey={jumpToKey}
showSummary={showSummary} showSummary={showSummary}
key={isShownKey} key={tagKey + operationKey}
response={ response } response={ response }
request={ request } request={ request }
allowTryItOut={allowTryItOut} allowTryItOut={allowTryItOut}

View File

@@ -3,6 +3,7 @@ import serializeError from "serialize-error"
export const NEW_THROWN_ERR = "err_new_thrown_err" export const NEW_THROWN_ERR = "err_new_thrown_err"
export const NEW_THROWN_ERR_BATCH = "err_new_thrown_err_batch" 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 = "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 NEW_AUTH_ERR = "err_new_auth_err"
export const CLEAR = "err_clear" 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) { export function newAuthErr(err) {
return { return {
type: NEW_AUTH_ERR, type: NEW_AUTH_ERR,

View File

@@ -2,6 +2,7 @@ import {
NEW_THROWN_ERR, NEW_THROWN_ERR,
NEW_THROWN_ERR_BATCH, NEW_THROWN_ERR_BATCH,
NEW_SPEC_ERR, NEW_SPEC_ERR,
NEW_SPEC_ERR_BATCH,
NEW_AUTH_ERR, NEW_AUTH_ERR,
CLEAR CLEAR
} from "./actions" } from "./actions"
@@ -45,6 +46,15 @@ export default function(system) {
.update("errors", errors => transformErrors(errors, system.getSystem())) .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 }) => { [NEW_AUTH_ERR]: (state, { payload }) => {
let error = fromJS(Object.assign({}, payload)) let error = fromJS(Object.assign({}, payload))

View File

@@ -494,8 +494,8 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
let listCheck = type === "array" && Im.List.isList(value) && value.count() let listCheck = type === "array" && Im.List.isList(value) && value.count()
let fileCheck = type === "file" && value instanceof win.File let fileCheck = type === "file" && value instanceof win.File
let booleanCheck = type === "boolean" && (value || value === false) let booleanCheck = type === "boolean" && (value || value === false)
let numberCheck = type === "number" && value let numberCheck = type === "number" && (value || value === 0)
let integerCheck = type === "integer" && value let integerCheck = type === "integer" && (value || value === 0)
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) { if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) {
errors.push("Required field is not provided") errors.push("Required field is not provided")

View File

@@ -3,14 +3,16 @@
font-size: 12px; font-size: 12px;
font-weight: 300; font-weight: 300;
@include text_code();
.deprecated .deprecated
{ {
span, td { span,
td
{
color: $model-deprecated-font-color !important; color: $model-deprecated-font-color !important;
} }
} }
@include text_code();
&-toggle &-toggle
{ {
font-size: 10px; font-size: 10px;
@@ -87,7 +89,8 @@
background: rgba($model-hint-background-color,.7); background: rgba($model-hint-background-color,.7);
} }
p { p
{
margin: 0 0 1em 0; margin: 0 0 1em 0;
} }
} }
@@ -106,6 +109,7 @@ section.models
h4 h4
{ {
margin: 0 0 5px 0; margin: 0 0 5px 0;
border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3); border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3);
} }
} }
@@ -114,6 +118,7 @@ section.models
font-size: 16px; font-size: 16px;
display: flex; display: flex;
align-items: center;
margin: 0; margin: 0;
padding: 10px 20px 10px 10px; padding: 10px 20px 10px 10px;
@@ -122,7 +127,6 @@ section.models
transition: all .2s; transition: all .2s;
@include text_headline($section-models-h4-font-color); @include text_headline($section-models-h4-font-color);
align-items: center;
svg svg
{ {
@@ -218,7 +222,9 @@ section.models
{ {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
margin-right: 1em; margin-right: 1em;
@include text_headline($_color-delete); @include text_headline($_color-delete);
} }
@@ -237,8 +243,8 @@ span
.prop-name .prop-name
{ {
display: inline-block; display: inline-block;
margin-right: 1em; margin-right: 1em;
width: 8em;
} }
.prop-type .prop-type

View File

@@ -700,6 +700,14 @@ describe("utils", function() {
} }
assertValidateParam(param, ["Required field is not provided"]) 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 // valid integer
param = { param = {
required: true, required: true,