Merge branch 'master' into feature/spec-path

This commit is contained in:
kyle
2017-12-07 16:49:34 -08:00
committed by GitHub
105 changed files with 3313 additions and 746 deletions

View File

@@ -7,10 +7,10 @@ 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_SERVER_VARIABLE_VALUE = "oas3_set_server_variable_value"
export function setSelectedServer (selectedServerUrl) {
export function setSelectedServer (selectedServerUrl, namespace) {
return {
type: UPDATE_SELECTED_SERVER,
payload: selectedServerUrl
payload: {selectedServerUrl, namespace}
}
}
@@ -28,16 +28,16 @@ export function setRequestContentType ({ value, pathMethod }) {
}
}
export function setResponseContentType ({ value, pathMethod }) {
export function setResponseContentType ({ value, path, method }) {
return {
type: UPDATE_RESPONSE_CONTENT_TYPE,
payload: { value, pathMethod }
payload: { value, path, method }
}
}
export function setServerVariableValue ({ server, key, val }) {
export function setServerVariableValue ({ server, namespace, key, val }) {
return {
type: UPDATE_SERVER_VARIABLE_VALUE,
payload: { server, key, val }
payload: { server, namespace, key, val }
}
}

View File

@@ -1,10 +1,12 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { fromJS } from "immutable"
const Callbacks = (props) => {
let { callbacks, getComponent } = props
// const Markdown = getComponent("Markdown")
const Operation = getComponent("operation", true)
const OperationContainer = getComponent("OperationContainer", true)
if(!callbacks) {
return <span>No callbacks</span>
@@ -16,24 +18,22 @@ const Callbacks = (props) => {
{ callback.map((pathItem, pathItemName) => {
return <div key={pathItemName}>
{ pathItem.map((operation, method) => {
return <Operation
operation={operation}
let op = fromJS({
operation
})
return <OperationContainer
{...props}
op={op}
key={method}
tag={""}
method={method}
isShownKey={["callbacks", operation.get("id"), callbackName]}
path={pathItemName}
allowTryItOut={false}
{...props}></Operation>
// return <pre>{JSON.stringify(operation)}</pre>
/>
}) }
</div>
}) }
</div>
// return <div>
// <h2>{name}</h2>
// {callback.description && <Markdown source={callback.description}/>}
// <pre>{JSON.stringify(callback)}</pre>
// </div>
})
return <div>
{callbackElements}
@@ -42,7 +42,7 @@ const Callbacks = (props) => {
Callbacks.propTypes = {
getComponent: PropTypes.func.isRequired,
callbacks: PropTypes.array.isRequired
callbacks: ImPropTypes.iterable.isRequired
}

View File

@@ -4,6 +4,7 @@ import OperationLink from "./operation-link.jsx"
import Servers from "./servers"
import RequestBodyEditor from "./request-body-editor"
import HttpAuth from "./http-auth"
import OperationServers from "./operation-servers"
export default {
Callbacks,
@@ -11,5 +12,6 @@ export default {
RequestBody,
Servers,
RequestBodyEditor,
OperationServers,
operationLink: OperationLink
}

View File

@@ -0,0 +1,102 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
export default class OperationServers extends React.Component {
static propTypes = {
// for self
path: PropTypes.string.isRequired,
method: PropTypes.string.isRequired,
operationServers: ImPropTypes.list,
pathServers: ImPropTypes.list,
setSelectedServer: PropTypes.func.isRequired,
setServerVariableValue: PropTypes.func.isRequired,
getSelectedServer: PropTypes.func.isRequired,
getServerVariable: PropTypes.func.isRequired,
getEffectiveServerValue: PropTypes.func.isRequired,
// utils
getComponent: PropTypes.func.isRequired
}
setSelectedServer = (server) => {
const { path, method } = this.props
// FIXME: we should be keeping up with this in props/state upstream of us
// instead of cheating™ with `forceUpdate`
this.forceUpdate()
return this.props.setSelectedServer(server, `${path}:${method}`)
}
setServerVariableValue = (obj) => {
const { path, method } = this.props
// FIXME: we should be keeping up with this in props/state upstream of us
// instead of cheating™ with `forceUpdate`
this.forceUpdate()
return this.props.setServerVariableValue({
...obj,
namespace: `${path}:${method}`
})
}
getSelectedServer = () => {
const { path, method } = this.props
return this.props.getSelectedServer(`${path}:${method}`)
}
getServerVariable = (server, key) => {
const { path, method } = this.props
return this.props.getServerVariable({
namespace: `${path}:${method}`,
server
}, key)
}
getEffectiveServerValue = (server) => {
const { path, method } = this.props
return this.props.getEffectiveServerValue({
server,
namespace: `${path}:${method}`
})
}
render() {
const {
// for self
operationServers,
pathServers,
// util
getComponent
} = this.props
if(!operationServers && !pathServers) {
return null
}
const Servers = getComponent("Servers")
const serversToDisplay = operationServers || pathServers
const displaying = operationServers ? "operation" : "path"
return <div className="opblock-section operation-servers">
<div className="opblock-section-header">
<div className="tab-header">
<h4 className="opblock-title">Servers</h4>
</div>
</div>
<div className="opblock-description-wrapper">
<h4 className="message">
These {displaying}-level options override the global server options.
</h4>
<Servers
servers={serversToDisplay}
currentServer={this.getSelectedServer()}
setSelectedServer={this.setSelectedServer}
setServerVariableValue={this.setServerVariableValue}
getServerVariable={this.getServerVariable}
getEffectiveServerValue={this.getEffectiveServerValue}
/>
</div>
</div>
}
}

View File

@@ -48,6 +48,13 @@ export default class RequestBodyEditor extends PureComponent {
}
}
componentDidUpdate(prevProps) {
if(this.props.requestBody !== prevProps.requestBody) {
// force recalc of value if the request body definition has changed
this.setValueToSample(this.props.mediaType)
}
}
setValueToSample = (explicitMediaType) => {
this.onChange(this.sample(explicitMediaType))
}

View File

@@ -23,6 +23,10 @@ const RequestBody = ({
const mediaTypeValue = requestBodyContent.get(contentType)
if(!mediaTypeValue) {
return null
}
return <div>
{ requestBodyDescription &&
<Markdown source={requestBodyDescription} />
@@ -52,7 +56,7 @@ RequestBody.propTypes = {
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
contentType: PropTypes.string.isRequired,
contentType: PropTypes.string,
isExecute: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired,
specPath: PropTypes.array.isRequired

View File

@@ -15,7 +15,11 @@ export default class Servers extends React.Component {
}
componentDidMount() {
let { servers } = this.props
let { servers, currentServer } = this.props
if(currentServer) {
return
}
//fire 'change' event to set default 'value' of select
this.setServer(servers.first().get("url"))
@@ -93,9 +97,8 @@ export default class Servers extends React.Component {
let shouldShowVariableUI = currentServerVariableDefs.size !== 0
return (
<div>
<div className="servers">
<label htmlFor="servers">
<span className="servers-title">Servers</span>
<select onChange={ this.onServerChange }>
{ servers.valueSeq().map(
( server ) =>
@@ -109,13 +112,14 @@ export default class Servers extends React.Component {
</label>
{ shouldShowVariableUI ?
<div>
<h4>Server variables</h4>
<div className={"computed-url"}>
Computed URL:
<code>
{getEffectiveServerValue(currentServer)}
</code>
</div>
<h4>Server variables</h4>
<table>
<tbody>
{

View File

@@ -7,8 +7,9 @@ import {
} from "./actions"
export default {
[UPDATE_SELECTED_SERVER]: (state, { payload: selectedServerUrl } ) =>{
return state.setIn( [ "selectedServer" ], selectedServerUrl)
[UPDATE_SELECTED_SERVER]: (state, { payload: { selectedServerUrl, namespace } } ) =>{
const path = namespace ? [ namespace, "selectedServer"] : [ "selectedServer"]
return state.setIn( path, selectedServerUrl)
},
[UPDATE_REQUEST_BODY_VALUE]: (state, { payload: { value, pathMethod } } ) =>{
let [path, method] = pathMethod
@@ -18,11 +19,11 @@ export default {
let [path, method] = pathMethod
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
},
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
let [path, method] = pathMethod
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, path, method } } ) =>{
return state.setIn( [ "requestData", path, method, "responseContentType" ], value)
},
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
return state.setIn( [ "serverVariableValues", server, key ], val)
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, namespace, key, val } } ) =>{
const path = namespace ? [ namespace, "serverVariableValues", server, key ] : [ "serverVariableValues", server, key ]
return state.setIn(path, val)
},
}

View File

@@ -15,8 +15,9 @@ function onlyOAS3(selector) {
}
}
export const selectedServer = onlyOAS3(state => {
return state.getIn(["selectedServer"]) || ""
export const selectedServer = onlyOAS3((state, namespace) => {
const path = namespace ? [namespace, "selectedServer"] : ["selectedServer"]
return state.getIn(path) || ""
}
)
@@ -35,19 +36,68 @@ export const responseContentType = onlyOAS3((state, path, method) => {
}
)
export const serverVariableValue = onlyOAS3((state, server, key) => {
return state.getIn(["serverVariableValues", server, key]) || null
export const serverVariableValue = onlyOAS3((state, locationData, key) => {
let path
// locationData may take one of two forms, for backwards compatibility
// Object: ({server, namespace?}) or String:(server)
if(typeof locationData !== "string") {
const { server, namespace } = locationData
if(namespace) {
path = [namespace, "serverVariableValues", server, key]
} else {
path = ["serverVariableValues", server, key]
}
} else {
const server = locationData
path = ["serverVariableValues", server, key]
}
return state.getIn(path) || null
}
)
export const serverVariables = onlyOAS3((state, server) => {
return state.getIn(["serverVariableValues", server]) || OrderedMap()
export const serverVariables = onlyOAS3((state, locationData) => {
let path
// locationData may take one of two forms, for backwards compatibility
// Object: ({server, namespace?}) or String:(server)
if(typeof locationData !== "string") {
const { server, namespace } = locationData
if(namespace) {
path = [namespace, "serverVariableValues", server]
} else {
path = ["serverVariableValues", server]
}
} else {
const server = locationData
path = ["serverVariableValues", server]
}
return state.getIn(path) || OrderedMap()
}
)
export const serverEffectiveValue = onlyOAS3((state, server) => {
let varValues = state.getIn(["serverVariableValues", server]) || OrderedMap()
let str = server
export const serverEffectiveValue = onlyOAS3((state, locationData) => {
var varValues, serverValue
// locationData may take one of two forms, for backwards compatibility
// Object: ({server, namespace?}) or String:(server)
if(typeof locationData !== "string") {
const { server, namespace } = locationData
serverValue = server
if(namespace) {
varValues = state.getIn([namespace, "serverVariableValues", serverValue])
} else {
varValues = state.getIn(["serverVariableValues", serverValue])
}
} else {
serverValue = locationData
varValues = state.getIn(["serverVariableValues", serverValue])
}
varValues = varValues || OrderedMap()
let str = serverValue
varValues.map((val, key) => {
str = str.replace(new RegExp(`{${key}}`, "g"), val)

View File

@@ -48,6 +48,10 @@ export const definitions = onlyOAS3(createSelector(
spec => spec.getIn(["components", "schemas"]) || Map()
))
export const hasHost = onlyOAS3((state) => {
return spec(state).hasIn(["servers", 0])
})
export const securityDefinitions = onlyOAS3(createSelector(
spec,
spec => spec.getIn(["components", "securitySchemes"]) || null

View File

@@ -8,12 +8,13 @@ class ModelComponent extends Component {
schema: PropTypes.object.isRequired,
name: PropTypes.string,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
expandDepth: PropTypes.number
}
render(){
let { schema } = this.props
let { getConfigs, schema } = this.props
let classes = ["model-box"]
let isDeprecated = schema.get("deprecated") === true
let message = null
@@ -26,6 +27,7 @@ class ModelComponent extends Component {
return <div className={classes.join(" ")}>
{message}
<Model { ...this.props }
getConfigs={ getConfigs }
depth={ 1 }
expandDepth={ this.props.expandDepth || 0 }
/>

View File

@@ -22,6 +22,7 @@ class Parameters extends Component {
specActions: PropTypes.object.isRequired,
operation: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
oas3Actions: PropTypes.object.isRequired,
oas3Selectors: PropTypes.object.isRequired,
@@ -87,6 +88,7 @@ class Parameters extends Component {
fn,
getComponent,
getConfigs,
specSelectors,
oas3Actions,
oas3Selectors,
@@ -142,6 +144,7 @@ class Parameters extends Component {
<ParameterRow fn={ fn }
getComponent={ getComponent }
specPath={[...specPath, i]}
getConfigs={ getConfigs }
param={ parameter }
key={ parameter.get( "name" ) }
onChange={ this.onChange }