Merge branch 'ft/performance' into bug/3904-operation-not-updating
This commit is contained in:
@@ -8,7 +8,6 @@ export default class Execute extends Component {
|
|||||||
specActions: PropTypes.object.isRequired,
|
specActions: PropTypes.object.isRequired,
|
||||||
operation: PropTypes.object.isRequired,
|
operation: PropTypes.object.isRequired,
|
||||||
path: PropTypes.string.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired,
|
|
||||||
method: PropTypes.string.isRequired,
|
method: PropTypes.string.isRequired,
|
||||||
onExecute: PropTypes.func
|
onExecute: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from "react"
|
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 { Iterable } from "immutable"
|
||||||
|
|
||||||
const Headers = ( { headers } )=>{
|
const Headers = ( { headers } )=>{
|
||||||
return (
|
return (
|
||||||
@@ -28,19 +29,29 @@ Duration.propTypes = {
|
|||||||
|
|
||||||
export default class LiveResponse extends React.Component {
|
export default class LiveResponse extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
response: PropTypes.object.isRequired,
|
response: PropTypes.instanceOf(Iterable).isRequired,
|
||||||
specSelectors: PropTypes.object.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
pathMethod: PropTypes.object.isRequired,
|
method: PropTypes.string.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired,
|
|
||||||
displayRequestDuration: PropTypes.bool.isRequired,
|
displayRequestDuration: PropTypes.bool.isRequired,
|
||||||
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
getComponent: PropTypes.func.isRequired,
|
||||||
getConfigs: PropTypes.func.isRequired
|
getConfigs: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps) {
|
||||||
|
// BUG: props.response is always coming back as a new Immutable instance
|
||||||
|
// same issue as responses.jsx (tryItOutResponse)
|
||||||
|
return this.props.response !== nextProps.response
|
||||||
|
|| this.props.path !== nextProps.path
|
||||||
|
|| this.props.method !== nextProps.method
|
||||||
|
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, pathMethod } = this.props
|
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, path, method } = this.props
|
||||||
const { showMutatedRequest } = getConfigs()
|
const { showMutatedRequest } = getConfigs()
|
||||||
|
|
||||||
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(pathMethod[0], pathMethod[1]) : specSelectors.requestFor(pathMethod[0], pathMethod[1])
|
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(path, method) : specSelectors.requestFor(path, method)
|
||||||
const status = response.get("status")
|
const status = response.get("status")
|
||||||
const url = response.get("url")
|
const url = response.get("url")
|
||||||
const headers = response.get("headers").toJS()
|
const headers = response.get("headers").toJS()
|
||||||
@@ -118,7 +129,6 @@ export default class LiveResponse extends React.Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
request: ImPropTypes.map,
|
|
||||||
response: ImPropTypes.map
|
response: ImPropTypes.map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,22 @@
|
|||||||
import React, { PureComponent } from "react"
|
import React, { PureComponent } from "react"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import { getList } from "core/utils"
|
import { getList } from "core/utils"
|
||||||
import * as CustomPropTypes from "core/proptypes"
|
|
||||||
import { sanitizeUrl } from "core/utils"
|
import { sanitizeUrl } from "core/utils"
|
||||||
|
import { Iterable } from "immutable"
|
||||||
//import "less/opblock"
|
|
||||||
|
|
||||||
export default class Operation extends PureComponent {
|
export default class Operation extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
path: PropTypes.string.isRequired,
|
operation: PropTypes.instanceOf(Iterable).isRequired,
|
||||||
method: PropTypes.string.isRequired,
|
response: PropTypes.instanceOf(Iterable),
|
||||||
operation: PropTypes.object.isRequired,
|
request: PropTypes.instanceOf(Iterable),
|
||||||
showSummary: PropTypes.bool,
|
|
||||||
isShown: PropTypes.bool.isRequired,
|
|
||||||
|
|
||||||
tagKey: PropTypes.string,
|
toggleShown: PropTypes.func.isRequired,
|
||||||
operationKey: PropTypes.string,
|
onTryoutClick: PropTypes.func.isRequired,
|
||||||
jumpToKey: CustomPropTypes.arrayOrString.isRequired,
|
onCancelClick: PropTypes.func.isRequired,
|
||||||
|
onExecute: PropTypes.func.isRequired,
|
||||||
allowTryItOut: PropTypes.bool,
|
|
||||||
|
|
||||||
displayOperationId: PropTypes.bool,
|
|
||||||
displayRequestDuration: PropTypes.bool,
|
|
||||||
|
|
||||||
response: PropTypes.object,
|
|
||||||
request: PropTypes.object,
|
|
||||||
|
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
|
getConfigs: PropTypes.func.isRequired,
|
||||||
authActions: PropTypes.object,
|
authActions: PropTypes.object,
|
||||||
authSelectors: PropTypes.object,
|
authSelectors: PropTypes.object,
|
||||||
specActions: PropTypes.object.isRequired,
|
specActions: PropTypes.object.isRequired,
|
||||||
@@ -34,87 +24,64 @@ export default class Operation extends PureComponent {
|
|||||||
oas3Actions: PropTypes.object.isRequired,
|
oas3Actions: PropTypes.object.isRequired,
|
||||||
layoutActions: PropTypes.object.isRequired,
|
layoutActions: PropTypes.object.isRequired,
|
||||||
layoutSelectors: PropTypes.object.isRequired,
|
layoutSelectors: PropTypes.object.isRequired,
|
||||||
fn: PropTypes.object.isRequired,
|
fn: PropTypes.object.isRequired
|
||||||
getConfigs: PropTypes.func.isRequired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
showSummary: true,
|
operation: null,
|
||||||
response: null,
|
response: null,
|
||||||
allowTryItOut: true,
|
request: null
|
||||||
displayOperationId: false,
|
|
||||||
displayRequestDuration: false
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context)
|
|
||||||
this.state = {
|
|
||||||
tryItOutEnabled: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if(nextProps.response !== this.props.response) {
|
|
||||||
this.setState({ executeInProgress: false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleShown =() => {
|
|
||||||
let { layoutActions, tagKey, operationKey, isShown } = this.props
|
|
||||||
const isShownKey = ["operations", tagKey, operationKey]
|
|
||||||
|
|
||||||
layoutActions.show(isShownKey, !isShown)
|
|
||||||
}
|
|
||||||
|
|
||||||
onTryoutClick =() => {
|
|
||||||
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
|
||||||
}
|
|
||||||
|
|
||||||
onCancelClick =() => {
|
|
||||||
let { specActions, path, method } = this.props
|
|
||||||
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
|
||||||
specActions.clearValidateParams([path, method])
|
|
||||||
}
|
|
||||||
|
|
||||||
onExecute = () => {
|
|
||||||
this.setState({ executeInProgress: true })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {
|
let {
|
||||||
operationKey,
|
|
||||||
tagKey,
|
|
||||||
isShown,
|
|
||||||
jumpToKey,
|
|
||||||
path,
|
|
||||||
method,
|
|
||||||
operation,
|
|
||||||
showSummary,
|
|
||||||
response,
|
response,
|
||||||
request,
|
request,
|
||||||
allowTryItOut,
|
toggleShown,
|
||||||
displayOperationId,
|
onTryoutClick,
|
||||||
displayRequestDuration,
|
onCancelClick,
|
||||||
|
onExecute,
|
||||||
fn,
|
fn,
|
||||||
getComponent,
|
getComponent,
|
||||||
|
getConfigs,
|
||||||
specActions,
|
specActions,
|
||||||
specSelectors,
|
specSelectors,
|
||||||
authActions,
|
authActions,
|
||||||
authSelectors,
|
authSelectors,
|
||||||
getConfigs,
|
|
||||||
oas3Actions
|
oas3Actions
|
||||||
} = this.props
|
} = this.props
|
||||||
|
let operationProps = this.props.operation
|
||||||
|
|
||||||
let summary = operation.get("summary")
|
let {
|
||||||
let description = operation.get("description")
|
isShown,
|
||||||
let deprecated = operation.get("deprecated")
|
isShownKey,
|
||||||
let externalDocs = operation.get("externalDocs")
|
jumpToKey,
|
||||||
|
path,
|
||||||
|
method,
|
||||||
|
op,
|
||||||
|
showSummary,
|
||||||
|
operationId,
|
||||||
|
allowTryItOut,
|
||||||
|
displayOperationId,
|
||||||
|
displayRequestDuration,
|
||||||
|
isDeepLinkingEnabled,
|
||||||
|
tryItOutEnabled,
|
||||||
|
executeInProgress
|
||||||
|
} = operationProps.toJS()
|
||||||
|
|
||||||
|
let {
|
||||||
|
summary,
|
||||||
|
description,
|
||||||
|
deprecated,
|
||||||
|
externalDocs,
|
||||||
|
schemes
|
||||||
|
} = op.operation
|
||||||
|
|
||||||
|
let operation = operationProps.getIn(["op", "operation"])
|
||||||
let responses = operation.get("responses")
|
let responses = operation.get("responses")
|
||||||
let security = operation.get("security") || specSelectors.security()
|
|
||||||
let produces = operation.get("produces")
|
let produces = operation.get("produces")
|
||||||
let schemes = operation.get("schemes")
|
let security = operation.get("security") || specSelectors.security()
|
||||||
let parameters = getList(operation, ["parameters"])
|
let parameters = getList(operation, ["parameters"])
|
||||||
let operationId = operation.get("__originalOperationId")
|
|
||||||
let operationScheme = specSelectors.operationScheme(path, method)
|
let operationScheme = specSelectors.operationScheme(path, method)
|
||||||
|
|
||||||
const Responses = getComponent("responses")
|
const Responses = getComponent("responses")
|
||||||
@@ -127,22 +94,17 @@ export default class Operation extends PureComponent {
|
|||||||
const Markdown = getComponent( "Markdown" )
|
const Markdown = getComponent( "Markdown" )
|
||||||
const Schemes = getComponent( "schemes" )
|
const Schemes = getComponent( "schemes" )
|
||||||
|
|
||||||
const { deepLinking } = getConfigs()
|
|
||||||
|
|
||||||
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false"
|
|
||||||
|
|
||||||
// Merge in Live Response
|
// Merge in Live Response
|
||||||
if(responses && response && response.size > 0) {
|
if(responses && response && response.size > 0) {
|
||||||
let notDocumented = !responses.get(String(response.get("status")))
|
let notDocumented = !responses.get(String(response.get("status")))
|
||||||
response = response.set("notDocumented", notDocumented)
|
response = response.set("notDocumented", notDocumented)
|
||||||
}
|
}
|
||||||
|
|
||||||
let { tryItOutEnabled } = this.state
|
|
||||||
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" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={`operations-${tagKey}-${operationKey}`} >
|
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} >
|
||||||
<div className={`opblock-summary opblock-summary-${method}`} onClick={this.toggleShown} >
|
<div className={`opblock-summary opblock-summary-${method}`} onClick={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
|
||||||
@@ -200,8 +162,8 @@ export default class Operation extends PureComponent {
|
|||||||
parameters={parameters}
|
parameters={parameters}
|
||||||
operation={operation}
|
operation={operation}
|
||||||
onChangeKey={onChangeKey}
|
onChangeKey={onChangeKey}
|
||||||
onTryoutClick = { this.onTryoutClick }
|
onTryoutClick = { onTryoutClick }
|
||||||
onCancelClick = { this.onCancelClick }
|
onCancelClick = { onCancelClick }
|
||||||
tryItOutEnabled = { tryItOutEnabled }
|
tryItOutEnabled = { tryItOutEnabled }
|
||||||
allowTryItOut={allowTryItOut}
|
allowTryItOut={allowTryItOut}
|
||||||
|
|
||||||
@@ -226,25 +188,23 @@ export default class Operation extends PureComponent {
|
|||||||
{ !tryItOutEnabled || !allowTryItOut ? null :
|
{ !tryItOutEnabled || !allowTryItOut ? null :
|
||||||
|
|
||||||
<Execute
|
<Execute
|
||||||
getComponent={getComponent}
|
|
||||||
operation={ operation }
|
operation={ operation }
|
||||||
specActions={ specActions }
|
specActions={ specActions }
|
||||||
specSelectors={ specSelectors }
|
specSelectors={ specSelectors }
|
||||||
path={ path }
|
path={ path }
|
||||||
method={ method }
|
method={ method }
|
||||||
onExecute={ this.onExecute } />
|
onExecute={ onExecute } />
|
||||||
}
|
}
|
||||||
|
|
||||||
{ (!tryItOutEnabled || !response || !allowTryItOut) ? null :
|
{ (!tryItOutEnabled || !response || !allowTryItOut) ? null :
|
||||||
<Clear
|
<Clear
|
||||||
onClick={ this.onClearClick }
|
|
||||||
specActions={ specActions }
|
specActions={ specActions }
|
||||||
path={ path }
|
path={ path }
|
||||||
method={ method }/>
|
method={ method }/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.state.executeInProgress ? <div className="loading-container"><div className="loading"></div></div> : null}
|
{executeInProgress ? <div className="loading-container"><div className="loading"></div></div> : null}
|
||||||
|
|
||||||
{ !responses ? null :
|
{ !responses ? null :
|
||||||
<Responses
|
<Responses
|
||||||
@@ -258,7 +218,8 @@ export default class Operation extends PureComponent {
|
|||||||
specActions={ specActions }
|
specActions={ specActions }
|
||||||
produces={ produces }
|
produces={ produces }
|
||||||
producesValue={ operation.get("produces_value") }
|
producesValue={ operation.get("produces_value") }
|
||||||
pathMethod={ [path, method] }
|
path={ path }
|
||||||
|
method={ method }
|
||||||
displayRequestDuration={ displayRequestDuration }
|
displayRequestDuration={ displayRequestDuration }
|
||||||
fn={fn} />
|
fn={fn} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,15 +34,12 @@ export default class Operations extends React.Component {
|
|||||||
|
|
||||||
let taggedOps = specSelectors.taggedOperations()
|
let taggedOps = specSelectors.taggedOperations()
|
||||||
|
|
||||||
const Operation = getComponent("operation")
|
const OperationContainer = getComponent("OperationContainer", true)
|
||||||
const Collapse = getComponent("Collapse")
|
const Collapse = getComponent("Collapse")
|
||||||
const Markdown = getComponent("Markdown")
|
const Markdown = getComponent("Markdown")
|
||||||
|
|
||||||
let showSummary = layoutSelectors.showSummary()
|
|
||||||
let {
|
let {
|
||||||
docExpansion,
|
docExpansion,
|
||||||
displayOperationId,
|
|
||||||
displayRequestDuration,
|
|
||||||
maxDisplayedTags,
|
maxDisplayedTags,
|
||||||
deepLinking
|
deepLinking
|
||||||
} = getConfigs()
|
} = getConfigs()
|
||||||
@@ -120,46 +117,23 @@ export default class Operations extends React.Component {
|
|||||||
<Collapse isOpened={showTag}>
|
<Collapse isOpened={showTag}>
|
||||||
{
|
{
|
||||||
operations.map( op => {
|
operations.map( op => {
|
||||||
|
const path = op.get("path")
|
||||||
|
const method = op.get("method")
|
||||||
|
|
||||||
const path = op.get("path", "")
|
return <OperationContainer
|
||||||
const method = op.get("method", "")
|
key={`${path}-${method}`}
|
||||||
const jumpToKey = `paths.${path}.${method}`
|
op={op}
|
||||||
|
path={path}
|
||||||
const operationId =
|
method={method}
|
||||||
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id")
|
tag={tag}
|
||||||
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"))
|
|
||||||
const request = specSelectors.requestFor(op.get("path"), op.get("method"))
|
|
||||||
|
|
||||||
return <Operation
|
|
||||||
{...op.toObject()}
|
|
||||||
tagKey={tagKey}
|
|
||||||
operationKey={operationKey}
|
|
||||||
isShown={layoutSelectors.isShown(["operations", tagKey, operationKey], docExpansion === "full")}
|
|
||||||
jumpToKey={jumpToKey}
|
|
||||||
showSummary={showSummary}
|
|
||||||
key={tagKey + operationKey}
|
|
||||||
response={ response }
|
|
||||||
request={ request }
|
|
||||||
allowTryItOut={allowTryItOut}
|
|
||||||
|
|
||||||
displayOperationId={displayOperationId}
|
|
||||||
displayRequestDuration={displayRequestDuration}
|
|
||||||
|
|
||||||
specActions={ specActions }
|
specActions={ specActions }
|
||||||
specSelectors={ specSelectors }
|
specSelectors={ specSelectors }
|
||||||
|
|
||||||
oas3Actions={oas3Actions}
|
oas3Actions={oas3Actions}
|
||||||
|
|
||||||
layoutActions={ layoutActions }
|
layoutActions={ layoutActions }
|
||||||
layoutSelectors={ layoutSelectors }
|
layoutSelectors={ layoutSelectors }
|
||||||
|
|
||||||
authActions={ authActions }
|
authActions={ authActions }
|
||||||
authSelectors={ authSelectors }
|
authSelectors={ authSelectors }
|
||||||
|
|
||||||
getComponent={ getComponent }
|
getComponent={ getComponent }
|
||||||
fn={fn}
|
fn={fn}
|
||||||
getConfigs={ getConfigs }
|
getConfigs={ getConfigs }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import cx from "classnames"
|
import cx from "classnames"
|
||||||
import { fromJS, Seq } from "immutable"
|
import { fromJS, Seq, Iterable } from "immutable"
|
||||||
import { getSampleSchema, fromJSOrdered } from "core/utils"
|
import { getSampleSchema, fromJSOrdered } from "core/utils"
|
||||||
|
|
||||||
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
||||||
@@ -42,7 +42,7 @@ export default class Response extends React.Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
code: PropTypes.string.isRequired,
|
code: PropTypes.string.isRequired,
|
||||||
response: PropTypes.object,
|
response: PropTypes.instanceOf(Iterable),
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
getConfigs: PropTypes.func.isRequired,
|
getConfigs: PropTypes.func.isRequired,
|
||||||
@@ -58,6 +58,12 @@ export default class Response extends React.Component {
|
|||||||
onContentTypeChange: () => {}
|
onContentTypeChange: () => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps) {
|
||||||
|
return this.props.code !== nextProps.code
|
||||||
|
|| this.props.response !== nextProps.response
|
||||||
|
|| this.props.className !== nextProps.className
|
||||||
|
}
|
||||||
|
|
||||||
_onContentTypeChange = (value) => {
|
_onContentTypeChange = (value) => {
|
||||||
const { onContentTypeChange, controlsAcceptHeader } = this.props
|
const { onContentTypeChange, controlsAcceptHeader } = this.props
|
||||||
this.setState({ responseContentType: value })
|
this.setState({ responseContentType: value })
|
||||||
|
|||||||
@@ -1,41 +1,52 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import { fromJS } from "immutable"
|
import { fromJS, Iterable } from "immutable"
|
||||||
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils"
|
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils"
|
||||||
|
|
||||||
export default class Responses extends React.Component {
|
export default class Responses extends React.Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
request: PropTypes.object,
|
tryItOutResponse: PropTypes.instanceOf(Iterable),
|
||||||
tryItOutResponse: PropTypes.object,
|
responses: PropTypes.instanceOf(Iterable).isRequired,
|
||||||
responses: PropTypes.object.isRequired,
|
produces: PropTypes.instanceOf(Iterable),
|
||||||
produces: PropTypes.object,
|
|
||||||
producesValue: PropTypes.any,
|
producesValue: PropTypes.any,
|
||||||
|
displayRequestDuration: PropTypes.bool.isRequired,
|
||||||
|
path: PropTypes.string.isRequired,
|
||||||
|
method: PropTypes.string.isRequired,
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
getConfigs: PropTypes.func.isRequired,
|
getConfigs: PropTypes.func.isRequired,
|
||||||
specSelectors: PropTypes.object.isRequired,
|
specSelectors: PropTypes.object.isRequired,
|
||||||
specActions: PropTypes.object.isRequired,
|
specActions: PropTypes.object.isRequired,
|
||||||
oas3Actions: PropTypes.object.isRequired,
|
oas3Actions: PropTypes.object.isRequired,
|
||||||
pathMethod: PropTypes.array.isRequired,
|
|
||||||
displayRequestDuration: PropTypes.bool.isRequired,
|
|
||||||
fn: PropTypes.object.isRequired
|
fn: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
request: null,
|
|
||||||
tryItOutResponse: null,
|
tryItOutResponse: null,
|
||||||
produces: fromJS(["application/json"]),
|
produces: fromJS(["application/json"]),
|
||||||
displayRequestDuration: false
|
displayRequestDuration: false
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.pathMethod, val)
|
shouldComponentUpdate(nextProps) {
|
||||||
|
// BUG: props.tryItOutResponse is always coming back as a new Immutable instance
|
||||||
|
let render = this.props.tryItOutResponse !== nextProps.tryItOutResponse
|
||||||
|
|| this.props.responses !== nextProps.responses
|
||||||
|
|| this.props.produces !== nextProps.produces
|
||||||
|
|| this.props.producesValue !== nextProps.producesValue
|
||||||
|
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
|
||||||
|
|| this.props.path !== nextProps.path
|
||||||
|
|| this.props.method !== nextProps.method
|
||||||
|
return render
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.path, this.props.method, val)
|
||||||
|
|
||||||
onResponseContentTypeChange = ({ controlsAcceptHeader, value }) => {
|
onResponseContentTypeChange = ({ controlsAcceptHeader, value }) => {
|
||||||
const { oas3Actions, pathMethod } = this.props
|
const { oas3Actions, path, method } = this.props
|
||||||
if(controlsAcceptHeader) {
|
if(controlsAcceptHeader) {
|
||||||
oas3Actions.setResponseContentType({
|
oas3Actions.setResponseContentType({
|
||||||
value,
|
value,
|
||||||
pathMethod
|
path,
|
||||||
|
method
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +54,6 @@ export default class Responses extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
let {
|
let {
|
||||||
responses,
|
responses,
|
||||||
request,
|
|
||||||
tryItOutResponse,
|
tryItOutResponse,
|
||||||
getComponent,
|
getComponent,
|
||||||
getConfigs,
|
getConfigs,
|
||||||
@@ -81,12 +91,12 @@ export default class Responses extends React.Component {
|
|||||||
{
|
{
|
||||||
!tryItOutResponse ? null
|
!tryItOutResponse ? null
|
||||||
: <div>
|
: <div>
|
||||||
<LiveResponse request={ request }
|
<LiveResponse response={ tryItOutResponse }
|
||||||
response={ tryItOutResponse }
|
|
||||||
getComponent={ getComponent }
|
getComponent={ getComponent }
|
||||||
getConfigs={ getConfigs }
|
getConfigs={ getConfigs }
|
||||||
specSelectors={ specSelectors }
|
specSelectors={ specSelectors }
|
||||||
pathMethod={ this.props.pathMethod }
|
path={ this.props.path }
|
||||||
|
method={ this.props.method }
|
||||||
displayRequestDuration={ displayRequestDuration } />
|
displayRequestDuration={ displayRequestDuration } />
|
||||||
<h4>Responses</h4>
|
<h4>Responses</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
212
src/core/containers/OperationContainer.jsx
Normal file
212
src/core/containers/OperationContainer.jsx
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
import React, { PureComponent } from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { helpers } from "swagger-client"
|
||||||
|
import { Iterable, fromJS } from "immutable"
|
||||||
|
|
||||||
|
const { opId } = helpers
|
||||||
|
|
||||||
|
export default class OperationContainer extends PureComponent {
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context)
|
||||||
|
this.state = {
|
||||||
|
tryItOutEnabled: false,
|
||||||
|
executeInProgress: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
op: PropTypes.instanceOf(Iterable).isRequired,
|
||||||
|
tag: PropTypes.string.isRequired,
|
||||||
|
path: PropTypes.string.isRequired,
|
||||||
|
method: PropTypes.string.isRequired,
|
||||||
|
operationId: PropTypes.string.isRequired,
|
||||||
|
showSummary: PropTypes.bool.isRequired,
|
||||||
|
isShown: PropTypes.bool.isRequired,
|
||||||
|
isShownKey: PropTypes.instanceOf(Iterable).isRequired,
|
||||||
|
jumpToKey: PropTypes.string.isRequired,
|
||||||
|
allowTryItOut: PropTypes.bool,
|
||||||
|
displayOperationId: PropTypes.bool,
|
||||||
|
displayRequestDuration: PropTypes.bool,
|
||||||
|
response: PropTypes.instanceOf(Iterable),
|
||||||
|
request: PropTypes.instanceOf(Iterable),
|
||||||
|
isDeepLinkingEnabled: PropTypes.bool.isRequired,
|
||||||
|
|
||||||
|
getComponent: PropTypes.func.isRequired,
|
||||||
|
authActions: PropTypes.object,
|
||||||
|
authSelectors: PropTypes.object,
|
||||||
|
specActions: PropTypes.object.isRequired,
|
||||||
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
layoutActions: PropTypes.object.isRequired,
|
||||||
|
layoutSelectors: PropTypes.object.isRequired,
|
||||||
|
fn: PropTypes.object.isRequired,
|
||||||
|
getConfigs: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
showSummary: true,
|
||||||
|
response: null,
|
||||||
|
allowTryItOut: true,
|
||||||
|
displayOperationId: false,
|
||||||
|
displayRequestDuration: false
|
||||||
|
}
|
||||||
|
|
||||||
|
mapStateToProps(nextState, props) {
|
||||||
|
const { op, layoutSelectors, getConfigs } = props
|
||||||
|
const { docExpansion, deepLinking, displayOperationId, displayRequestDuration } = getConfigs()
|
||||||
|
const showSummary = layoutSelectors.showSummary()
|
||||||
|
const operationId = op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), props.path, props.method) || op.get("id")
|
||||||
|
const isShownKey = fromJS(["operations", props.tag, operationId])
|
||||||
|
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false"
|
||||||
|
|
||||||
|
return {
|
||||||
|
operationId,
|
||||||
|
isDeepLinkingEnabled,
|
||||||
|
isShownKey,
|
||||||
|
showSummary,
|
||||||
|
displayOperationId,
|
||||||
|
displayRequestDuration,
|
||||||
|
isShown: layoutSelectors.isShown(isShownKey, docExpansion === "full" ),
|
||||||
|
jumpToKey: `paths.${props.path}.${props.method}`,
|
||||||
|
allowTryItOut: props.specSelectors.allowTryItOutFor(props.path, props.method),
|
||||||
|
response: props.specSelectors.responseFor(props.path, props.method),
|
||||||
|
request: props.specSelectors.requestFor(props.path, props.method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const defaultContentType = "application/json"
|
||||||
|
let { specActions, path, method, op } = nextProps
|
||||||
|
let operation = op.get("operation")
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
const render = this.state.tryItOutEnabled !== nextState.tryItOutEnabled
|
||||||
|
|| this.state.executeInProgress !== nextState.executeInProgress
|
||||||
|
|| this.props.op !== nextProps.op
|
||||||
|
|| this.props.tag !== nextProps.tag
|
||||||
|
|| this.props.path !== nextProps.path
|
||||||
|
|| this.props.method !== nextProps.method
|
||||||
|
|| this.props.operationId !== nextProps.operationId
|
||||||
|
|| this.props.showSummary !== nextProps.showSummary
|
||||||
|
|| this.props.isShown !== nextProps.isShown
|
||||||
|
|| this.props.jumpToKey !== nextProps.jumpToKey
|
||||||
|
|| this.props.allowTryItOut !== nextProps.allowTryItOut
|
||||||
|
|| this.props.displayOperationId !== nextProps.displayOperationId
|
||||||
|
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
|
||||||
|
|| this.props.response !== nextProps.response
|
||||||
|
|| this.props.request !== nextProps.request
|
||||||
|
|| this.props.isDeepLinkingEnabled !== nextProps.isDeepLinkingEnabled
|
||||||
|
return render
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleShown =() => {
|
||||||
|
let { layoutActions, isShownKey, isShown } = this.props
|
||||||
|
layoutActions.show(isShownKey, !isShown)
|
||||||
|
}
|
||||||
|
|
||||||
|
onTryoutClick =() => {
|
||||||
|
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelClick =() => {
|
||||||
|
let { specActions, path, method } = this.props
|
||||||
|
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
|
||||||
|
specActions.clearValidateParams([path, method])
|
||||||
|
}
|
||||||
|
|
||||||
|
onExecute = () => {
|
||||||
|
this.setState({ executeInProgress: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let {
|
||||||
|
op,
|
||||||
|
tag,
|
||||||
|
path,
|
||||||
|
method,
|
||||||
|
operationId,
|
||||||
|
showSummary,
|
||||||
|
isShown,
|
||||||
|
isShownKey,
|
||||||
|
jumpToKey,
|
||||||
|
allowTryItOut,
|
||||||
|
response,
|
||||||
|
request,
|
||||||
|
displayOperationId,
|
||||||
|
displayRequestDuration,
|
||||||
|
isDeepLinkingEnabled,
|
||||||
|
specSelectors,
|
||||||
|
specActions,
|
||||||
|
getComponent,
|
||||||
|
getConfigs,
|
||||||
|
layoutSelectors,
|
||||||
|
layoutActions,
|
||||||
|
authActions,
|
||||||
|
authSelectors,
|
||||||
|
fn
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const Operation = getComponent( "operation" )
|
||||||
|
|
||||||
|
const operationProps = fromJS({
|
||||||
|
op,
|
||||||
|
tag,
|
||||||
|
path,
|
||||||
|
method,
|
||||||
|
operationId,
|
||||||
|
showSummary,
|
||||||
|
isShown,
|
||||||
|
isShownKey,
|
||||||
|
jumpToKey,
|
||||||
|
allowTryItOut,
|
||||||
|
request,
|
||||||
|
displayOperationId,
|
||||||
|
displayRequestDuration,
|
||||||
|
isDeepLinkingEnabled,
|
||||||
|
executeInProgress: this.state.executeInProgress,
|
||||||
|
tryItOutEnabled: this.state.tryItOutEnabled
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Operation
|
||||||
|
operation={operationProps}
|
||||||
|
response={response}
|
||||||
|
request={request}
|
||||||
|
|
||||||
|
toggleShown={this.toggleShown}
|
||||||
|
onTryoutClick={this.onTryoutClick}
|
||||||
|
onCancelClick={this.onCancelClick}
|
||||||
|
onExecute={this.onExecute}
|
||||||
|
|
||||||
|
specActions={ specActions }
|
||||||
|
specSelectors={ specSelectors }
|
||||||
|
layoutActions={ layoutActions }
|
||||||
|
layoutSelectors={ layoutSelectors }
|
||||||
|
authActions={ authActions }
|
||||||
|
authSelectors={ authSelectors }
|
||||||
|
getComponent={ getComponent }
|
||||||
|
getConfigs={ getConfigs }
|
||||||
|
fn={fn}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,8 +7,7 @@ import * as AllPlugins from "core/plugins/all"
|
|||||||
import { parseSearch } from "core/utils"
|
import { parseSearch } from "core/utils"
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== "production") {
|
if (process.env.NODE_ENV !== "production") {
|
||||||
const Perf = require("react-addons-perf")
|
window.Perf = require("react-addons-perf")
|
||||||
window.Perf = Perf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ export function setRequestContentType ({ value, pathMethod }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setResponseContentType ({ value, pathMethod }) {
|
export function setResponseContentType ({ value, path, method }) {
|
||||||
return {
|
return {
|
||||||
type: UPDATE_RESPONSE_CONTENT_TYPE,
|
type: UPDATE_RESPONSE_CONTENT_TYPE,
|
||||||
payload: { value, pathMethod }
|
payload: { value, path, method }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ export default {
|
|||||||
let [path, method] = pathMethod
|
let [path, method] = pathMethod
|
||||||
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
|
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
|
||||||
},
|
},
|
||||||
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
|
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, path, method } } ) =>{
|
||||||
let [path, method] = pathMethod
|
|
||||||
return state.setIn( [ "requestData", path, method, "responseContentType" ], value)
|
return state.setIn( [ "requestData", path, method, "responseContentType" ], value)
|
||||||
},
|
},
|
||||||
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
|
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ class Parameters extends Component {
|
|||||||
operation
|
operation
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
|
console.log('rendering Parameters')
|
||||||
|
|
||||||
const ParameterRow = getComponent("parameterRow")
|
const ParameterRow = getComponent("parameterRow")
|
||||||
const TryItOutButton = getComponent("TryItOutButton")
|
const TryItOutButton = getComponent("TryItOutButton")
|
||||||
const ContentType = getComponent("contentType")
|
const ContentType = getComponent("contentType")
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ const RootWrapper = (reduxStore, ComponentToWrap) => class extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const makeContainer = (getSystem, component, reduxStore) => {
|
const makeContainer = (getSystem, component, reduxStore) => {
|
||||||
|
const mapStateToProps = component.prototype.mapStateToProps || function(state) {
|
||||||
|
return {state}
|
||||||
|
}
|
||||||
let wrappedWithSystem = SystemWrapper(getSystem, component, reduxStore)
|
let wrappedWithSystem = SystemWrapper(getSystem, component, reduxStore)
|
||||||
let connected = connect(state => ({state}))(wrappedWithSystem)
|
let connected = connect( mapStateToProps )(wrappedWithSystem)
|
||||||
if(reduxStore)
|
if(reduxStore)
|
||||||
return RootWrapper(reduxStore, connected)
|
return RootWrapper(reduxStore, connected)
|
||||||
return connected
|
return connected
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import downloadUrlPlugin from "core/plugins/download-url"
|
|||||||
import configsPlugin from "plugins/configs"
|
import configsPlugin from "plugins/configs"
|
||||||
import deepLinkingPlugin from "core/plugins/deep-linking"
|
import deepLinkingPlugin from "core/plugins/deep-linking"
|
||||||
|
|
||||||
|
import OperationContainer from "core/containers/OperationContainer"
|
||||||
|
|
||||||
import App from "core/components/app"
|
import App from "core/components/app"
|
||||||
import AuthorizationPopup from "core/components/auth/authorization-popup"
|
import AuthorizationPopup from "core/components/auth/authorization-popup"
|
||||||
import AuthorizeBtn from "core/components/auth/authorize-btn"
|
import AuthorizeBtn from "core/components/auth/authorize-btn"
|
||||||
@@ -112,7 +114,8 @@ export default function() {
|
|||||||
TryItOutButton,
|
TryItOutButton,
|
||||||
Markdown,
|
Markdown,
|
||||||
BaseLayout,
|
BaseLayout,
|
||||||
VersionStamp
|
VersionStamp,
|
||||||
|
OperationContainer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -289,8 +289,7 @@ export default class Store {
|
|||||||
|
|
||||||
getMapStateToProps() {
|
getMapStateToProps() {
|
||||||
return () => {
|
return () => {
|
||||||
let obj = Object.assign({}, this.getSystem())
|
return Object.assign({}, this.getSystem())
|
||||||
return obj
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
|
import React, { PureComponent } from "react"
|
||||||
import expect from "expect"
|
import expect from "expect"
|
||||||
import System from "core/system"
|
import System from "core/system"
|
||||||
import { fromJS } from "immutable"
|
import { fromJS } from "immutable"
|
||||||
|
import { render } from "enzyme"
|
||||||
|
import ViewPlugin from "core/plugins/view/index.js"
|
||||||
|
import { connect, Provider } from "react-redux"
|
||||||
|
|
||||||
describe("bound system", function(){
|
describe("bound system", function(){
|
||||||
|
|
||||||
@@ -444,4 +448,66 @@ describe("bound system", function(){
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("getComponent", function() {
|
||||||
|
it("returns a component from the system", function() {
|
||||||
|
const system = new System({
|
||||||
|
plugins: [
|
||||||
|
ViewPlugin,
|
||||||
|
{
|
||||||
|
components: {
|
||||||
|
test: ({ name }) => <div>{name} component</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// When
|
||||||
|
var Component = system.getSystem().getComponent("test")
|
||||||
|
const renderedComponent = render(<Component name="Test" />)
|
||||||
|
expect(renderedComponent.text()).toEqual("Test component")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("allows container components to provide their own `mapStateToProps` function", function() {
|
||||||
|
// Given
|
||||||
|
class ContainerComponent extends PureComponent {
|
||||||
|
mapStateToProps(nextState, props) {
|
||||||
|
return {
|
||||||
|
"abc": "This came from mapStateToProps"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
"abc" : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>{ this.props.abc }</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const system = new System({
|
||||||
|
plugins: [
|
||||||
|
ViewPlugin,
|
||||||
|
{
|
||||||
|
components: {
|
||||||
|
ContainerComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// When
|
||||||
|
var Component = system.getSystem().getComponent("ContainerComponent", true)
|
||||||
|
const renderedComponent = render(
|
||||||
|
<Provider store={system.getStore()}>
|
||||||
|
<Component />
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(renderedComponent.text()).toEqual("This came from mapStateToProps")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user