Update Operation content correctlybubble
@@ -45,6 +45,7 @@ | |||
"brace": "0.7.0", | |||
"classnames": "^2.2.5", | |||
"commonmark": "^0.28.1", | |||
"core-js": "^2.5.1", | |||
"css.escape": "1.5.1", | |||
"deep-extend": "0.4.1", | |||
"expect": "1.20.2", | |||
@@ -8,7 +8,6 @@ export default class Execute extends Component { | |||
specActions: PropTypes.object.isRequired, | |||
operation: PropTypes.object.isRequired, | |||
path: PropTypes.string.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
method: PropTypes.string.isRequired, | |||
onExecute: PropTypes.func | |||
} | |||
@@ -1,6 +1,7 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import ImPropTypes from "react-immutable-proptypes" | |||
import { Iterable } from "immutable" | |||
const Headers = ( { headers } )=>{ | |||
return ( | |||
@@ -28,19 +29,29 @@ Duration.propTypes = { | |||
export default class LiveResponse extends React.Component { | |||
static propTypes = { | |||
response: PropTypes.object.isRequired, | |||
response: PropTypes.instanceOf(Iterable).isRequired, | |||
path: PropTypes.string.isRequired, | |||
method: PropTypes.string.isRequired, | |||
displayRequestDuration: PropTypes.bool.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
pathMethod: PropTypes.object.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
displayRequestDuration: PropTypes.bool.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() { | |||
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, pathMethod } = this.props | |||
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, path, method } = this.props | |||
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 url = response.get("url") | |||
const headers = response.get("headers").toJS() | |||
@@ -118,7 +129,6 @@ export default class LiveResponse extends React.Component { | |||
static propTypes = { | |||
getComponent: PropTypes.func.isRequired, | |||
request: ImPropTypes.map, | |||
response: ImPropTypes.map | |||
} | |||
} |
@@ -1,32 +1,22 @@ | |||
import React, { PureComponent } from "react" | |||
import PropTypes from "prop-types" | |||
import { getList } from "core/utils" | |||
import * as CustomPropTypes from "core/proptypes" | |||
import { sanitizeUrl } from "core/utils" | |||
//import "less/opblock" | |||
import { Iterable } from "immutable" | |||
export default class Operation extends PureComponent { | |||
static propTypes = { | |||
path: PropTypes.string.isRequired, | |||
method: PropTypes.string.isRequired, | |||
operation: PropTypes.object.isRequired, | |||
showSummary: PropTypes.bool, | |||
isShown: PropTypes.bool.isRequired, | |||
tagKey: PropTypes.string, | |||
operationKey: PropTypes.string, | |||
jumpToKey: CustomPropTypes.arrayOrString.isRequired, | |||
allowTryItOut: PropTypes.bool, | |||
operation: PropTypes.instanceOf(Iterable).isRequired, | |||
response: PropTypes.instanceOf(Iterable), | |||
request: PropTypes.instanceOf(Iterable), | |||
displayOperationId: PropTypes.bool, | |||
displayRequestDuration: PropTypes.bool, | |||
response: PropTypes.object, | |||
request: PropTypes.object, | |||
toggleShown: PropTypes.func.isRequired, | |||
onTryoutClick: PropTypes.func.isRequired, | |||
onCancelClick: PropTypes.func.isRequired, | |||
onExecute: PropTypes.func.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
authActions: PropTypes.object, | |||
authSelectors: PropTypes.object, | |||
specActions: PropTypes.object.isRequired, | |||
@@ -34,88 +24,66 @@ export default class Operation extends PureComponent { | |||
oas3Actions: PropTypes.object.isRequired, | |||
layoutActions: PropTypes.object.isRequired, | |||
layoutSelectors: PropTypes.object.isRequired, | |||
fn: PropTypes.object.isRequired, | |||
getConfigs: PropTypes.func.isRequired | |||
fn: PropTypes.object.isRequired | |||
} | |||
static defaultProps = { | |||
showSummary: true, | |||
operation: null, | |||
response: null, | |||
allowTryItOut: true, | |||
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 }) | |||
request: null | |||
} | |||
render() { | |||
let { | |||
operationKey, | |||
tagKey, | |||
isShown, | |||
jumpToKey, | |||
path, | |||
method, | |||
operation, | |||
showSummary, | |||
response, | |||
request, | |||
allowTryItOut, | |||
displayOperationId, | |||
displayRequestDuration, | |||
toggleShown, | |||
onTryoutClick, | |||
onCancelClick, | |||
onExecute, | |||
fn, | |||
getComponent, | |||
getConfigs, | |||
specActions, | |||
specSelectors, | |||
authActions, | |||
authSelectors, | |||
getConfigs, | |||
oas3Actions | |||
} = this.props | |||
let operationProps = this.props.operation | |||
let summary = operation.get("summary") | |||
let description = operation.get("description") | |||
let deprecated = operation.get("deprecated") | |||
let externalDocs = operation.get("externalDocs") | |||
let { | |||
isShown, | |||
jumpToKey, | |||
path, | |||
method, | |||
op, | |||
tag, | |||
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 security = operation.get("security") || specSelectors.security() | |||
let produces = operation.get("produces") | |||
let schemes = operation.get("schemes") | |||
let security = operation.get("security") || specSelectors.security() | |||
let parameters = getList(operation, ["parameters"]) | |||
let operationId = operation.get("__originalOperationId") | |||
let operationScheme = specSelectors.operationScheme(path, method) | |||
let isShownKey = ["operations", tag, operationId] | |||
const Responses = getComponent("responses") | |||
const Parameters = getComponent( "parameters" ) | |||
@@ -127,28 +95,23 @@ export default class Operation extends PureComponent { | |||
const Markdown = getComponent( "Markdown" ) | |||
const Schemes = getComponent( "schemes" ) | |||
const { deepLinking } = getConfigs() | |||
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false" | |||
// Merge in Live Response | |||
if(responses && response && response.size > 0) { | |||
let notDocumented = !responses.get(String(response.get("status"))) | |||
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 ) | |||
return ( | |||
<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={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} > | |||
<div className={`opblock-summary opblock-summary-${method}`} onClick={toggleShown} > | |||
<span className="opblock-summary-method">{method.toUpperCase()}</span> | |||
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } > | |||
<a | |||
className="nostyle" | |||
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null} | |||
href={isDeepLinkingEnabled ? `#/${tagKey}/${operationKey}` : null}> | |||
href={isDeepLinkingEnabled ? `#/${isShownKey.join("/")}` : null}> | |||
<span>{path}</span> | |||
</a> | |||
<JumpToPath path={jumpToKey} /> | |||
@@ -200,8 +163,8 @@ export default class Operation extends PureComponent { | |||
parameters={parameters} | |||
operation={operation} | |||
onChangeKey={onChangeKey} | |||
onTryoutClick = { this.onTryoutClick } | |||
onCancelClick = { this.onCancelClick } | |||
onTryoutClick = { onTryoutClick } | |||
onCancelClick = { onCancelClick } | |||
tryItOutEnabled = { tryItOutEnabled } | |||
allowTryItOut={allowTryItOut} | |||
@@ -226,25 +189,23 @@ export default class Operation extends PureComponent { | |||
{ !tryItOutEnabled || !allowTryItOut ? null : | |||
<Execute | |||
getComponent={getComponent} | |||
operation={ operation } | |||
specActions={ specActions } | |||
specSelectors={ specSelectors } | |||
path={ path } | |||
method={ method } | |||
onExecute={ this.onExecute } /> | |||
onExecute={ onExecute } /> | |||
} | |||
{ (!tryItOutEnabled || !response || !allowTryItOut) ? null : | |||
<Clear | |||
onClick={ this.onClearClick } | |||
specActions={ specActions } | |||
path={ path } | |||
method={ method }/> | |||
} | |||
</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 | |||
@@ -258,7 +219,8 @@ export default class Operation extends PureComponent { | |||
specActions={ specActions } | |||
produces={ produces } | |||
producesValue={ operation.get("produces_value") } | |||
pathMethod={ [path, method] } | |||
path={ path } | |||
method={ method } | |||
displayRequestDuration={ displayRequestDuration } | |||
fn={fn} /> | |||
} | |||
@@ -1,8 +1,6 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import { helpers } from "swagger-client" | |||
import { createDeepLinkPath, sanitizeUrl } from "core/utils" | |||
const { opId } = helpers | |||
export default class Operations extends React.Component { | |||
@@ -21,28 +19,20 @@ export default class Operations extends React.Component { | |||
render() { | |||
let { | |||
specSelectors, | |||
specActions, | |||
oas3Actions, | |||
getComponent, | |||
layoutSelectors, | |||
layoutActions, | |||
authActions, | |||
authSelectors, | |||
getConfigs, | |||
fn | |||
getConfigs | |||
} = this.props | |||
let taggedOps = specSelectors.taggedOperations() | |||
const Operation = getComponent("operation") | |||
const OperationContainer = getComponent("OperationContainer", true) | |||
const Collapse = getComponent("Collapse") | |||
const Markdown = getComponent("Markdown") | |||
let showSummary = layoutSelectors.showSummary() | |||
let { | |||
docExpansion, | |||
displayOperationId, | |||
displayRequestDuration, | |||
maxDisplayedTags, | |||
deepLinking | |||
} = getConfigs() | |||
@@ -120,49 +110,15 @@ export default class Operations extends React.Component { | |||
<Collapse isOpened={showTag}> | |||
{ | |||
operations.map( op => { | |||
const path = op.get("path", "") | |||
const method = op.get("method", "") | |||
const jumpToKey = `paths.${path}.${method}` | |||
const operationId = | |||
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id") | |||
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 } | |||
specSelectors={ specSelectors } | |||
oas3Actions={oas3Actions} | |||
layoutActions={ layoutActions } | |||
layoutSelectors={ layoutSelectors } | |||
authActions={ authActions } | |||
authSelectors={ authSelectors } | |||
getComponent={ getComponent } | |||
fn={fn} | |||
getConfigs={ getConfigs } | |||
const path = op.get("path") | |||
const method = op.get("method") | |||
return <OperationContainer | |||
key={`${path}-${method}`} | |||
op={op} | |||
path={path} | |||
method={method} | |||
tag={tag} | |||
/> | |||
}).toArray() | |||
} | |||
@@ -1,7 +1,7 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import cx from "classnames" | |||
import { fromJS, Seq } from "immutable" | |||
import { fromJS, Seq, Iterable } from "immutable" | |||
import { getSampleSchema, fromJSOrdered } from "core/utils" | |||
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => { | |||
@@ -42,7 +42,7 @@ export default class Response extends React.Component { | |||
static propTypes = { | |||
code: PropTypes.string.isRequired, | |||
response: PropTypes.object, | |||
response: PropTypes.instanceOf(Iterable), | |||
className: PropTypes.string, | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
@@ -1,41 +1,52 @@ | |||
import React from "react" | |||
import PropTypes from "prop-types" | |||
import { fromJS } from "immutable" | |||
import { fromJS, Iterable } from "immutable" | |||
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils" | |||
export default class Responses extends React.Component { | |||
static propTypes = { | |||
request: PropTypes.object, | |||
tryItOutResponse: PropTypes.object, | |||
responses: PropTypes.object.isRequired, | |||
produces: PropTypes.object, | |||
tryItOutResponse: PropTypes.instanceOf(Iterable), | |||
responses: PropTypes.instanceOf(Iterable).isRequired, | |||
produces: PropTypes.instanceOf(Iterable), | |||
producesValue: PropTypes.any, | |||
displayRequestDuration: PropTypes.bool.isRequired, | |||
path: PropTypes.string.isRequired, | |||
method: PropTypes.string.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
getConfigs: PropTypes.func.isRequired, | |||
specSelectors: PropTypes.object.isRequired, | |||
specActions: PropTypes.object.isRequired, | |||
oas3Actions: PropTypes.object.isRequired, | |||
pathMethod: PropTypes.array.isRequired, | |||
displayRequestDuration: PropTypes.bool.isRequired, | |||
fn: PropTypes.object.isRequired | |||
} | |||
static defaultProps = { | |||
request: null, | |||
tryItOutResponse: null, | |||
produces: fromJS(["application/json"]), | |||
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 }) => { | |||
const { oas3Actions, pathMethod } = this.props | |||
const { oas3Actions, path, method } = this.props | |||
if(controlsAcceptHeader) { | |||
oas3Actions.setResponseContentType({ | |||
value, | |||
pathMethod | |||
path, | |||
method | |||
}) | |||
} | |||
} | |||
@@ -43,7 +54,6 @@ export default class Responses extends React.Component { | |||
render() { | |||
let { | |||
responses, | |||
request, | |||
tryItOutResponse, | |||
getComponent, | |||
getConfigs, | |||
@@ -81,12 +91,12 @@ export default class Responses extends React.Component { | |||
{ | |||
!tryItOutResponse ? null | |||
: <div> | |||
<LiveResponse request={ request } | |||
response={ tryItOutResponse } | |||
<LiveResponse response={ tryItOutResponse } | |||
getComponent={ getComponent } | |||
getConfigs={ getConfigs } | |||
specSelectors={ specSelectors } | |||
pathMethod={ this.props.pathMethod } | |||
path={ this.props.path } | |||
method={ this.props.method } | |||
displayRequestDuration={ displayRequestDuration } /> | |||
<h4>Responses</h4> | |||
</div> | |||
@@ -0,0 +1,192 @@ | |||
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, | |||
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, | |||
oas3Actions: 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 = ["operations", props.tag, operationId] | |||
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false" | |||
return { | |||
operationId, | |||
isDeepLinkingEnabled, | |||
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) | |||
} | |||
} | |||
toggleShown =() => { | |||
let { layoutActions, tag, operationId, isShown } = this.props | |||
layoutActions.show(["operations", tag, operationId], !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, | |||
jumpToKey, | |||
allowTryItOut, | |||
response, | |||
request, | |||
displayOperationId, | |||
displayRequestDuration, | |||
isDeepLinkingEnabled, | |||
specSelectors, | |||
specActions, | |||
getComponent, | |||
getConfigs, | |||
layoutSelectors, | |||
layoutActions, | |||
authActions, | |||
authSelectors, | |||
oas3Actions, | |||
fn | |||
} = this.props | |||
const Operation = getComponent( "operation" ) | |||
const operationProps = fromJS({ | |||
op, | |||
tag, | |||
path, | |||
method, | |||
operationId, | |||
showSummary, | |||
isShown, | |||
jumpToKey, | |||
allowTryItOut, | |||
request, | |||
displayOperationId, | |||
displayRequestDuration, | |||
isDeepLinkingEnabled, | |||
executeInProgress: this.state.executeInProgress, | |||
tryItOutEnabled: this.state.tryItOutEnabled | |||
}) | |||
return ( | |||
<Operation | |||
operation={operationProps} | |||
response={response} | |||
request={request} | |||
isShown={isShown} | |||
toggleShown={this.toggleShown} | |||
onTryoutClick={this.onTryoutClick} | |||
onCancelClick={this.onCancelClick} | |||
onExecute={this.onExecute} | |||
specActions={ specActions } | |||
specSelectors={ specSelectors } | |||
oas3Actions={oas3Actions} | |||
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" | |||
if (process.env.NODE_ENV !== "production") { | |||
const Perf = require("react-addons-perf") | |||
window.Perf = Perf | |||
window.Perf = require("react-addons-perf") | |||
} | |||
// 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 { | |||
type: UPDATE_RESPONSE_CONTENT_TYPE, | |||
payload: { value, pathMethod } | |||
payload: { value, path, method } | |||
} | |||
} | |||
@@ -18,8 +18,7 @@ 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 } } ) =>{ | |||
@@ -20,8 +20,14 @@ const RootWrapper = (reduxStore, ComponentToWrap) => class extends Component { | |||
} | |||
const makeContainer = (getSystem, component, reduxStore) => { | |||
const mapStateToProps = function(state, ownProps) { | |||
const propsForContainerComponent = Object.assign({}, ownProps, getSystem()) | |||
const ori = component.prototype.mapStateToProps || (state => { return {state} }) | |||
return ori(state, propsForContainerComponent) | |||
} | |||
let wrappedWithSystem = SystemWrapper(getSystem, component, reduxStore) | |||
let connected = connect(state => ({state}))(wrappedWithSystem) | |||
let connected = connect( mapStateToProps )(wrappedWithSystem) | |||
if(reduxStore) | |||
return RootWrapper(reduxStore, connected) | |||
return connected | |||
@@ -13,6 +13,8 @@ import downloadUrlPlugin from "core/plugins/download-url" | |||
import configsPlugin from "plugins/configs" | |||
import deepLinkingPlugin from "core/plugins/deep-linking" | |||
import OperationContainer from "core/containers/OperationContainer" | |||
import App from "core/components/app" | |||
import AuthorizationPopup from "core/components/auth/authorization-popup" | |||
import AuthorizeBtn from "core/components/auth/authorize-btn" | |||
@@ -112,7 +114,8 @@ export default function() { | |||
TryItOutButton, | |||
Markdown, | |||
BaseLayout, | |||
VersionStamp | |||
VersionStamp, | |||
OperationContainer | |||
} | |||
} | |||
@@ -289,8 +289,7 @@ export default class Store { | |||
getMapStateToProps() { | |||
return () => { | |||
let obj = Object.assign({}, this.getSystem()) | |||
return obj | |||
return Object.assign({}, this.getSystem()) | |||
} | |||
} | |||
@@ -1,7 +1,11 @@ | |||
/* eslint-env mocha */ | |||
import React, { PureComponent } from "react" | |||
import expect from "expect" | |||
import System from "core/system" | |||
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(){ | |||
@@ -444,4 +448,129 @@ 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 { | |||
"fromMapState": "This came from mapStateToProps" | |||
} | |||
} | |||
static defaultProps = { | |||
"fromMapState" : "" | |||
} | |||
render() { | |||
const { exampleSelectors, fromMapState, fromOwnProps } = this.props | |||
return ( | |||
<div>{ fromMapState } {exampleSelectors.foo()} {fromOwnProps}</div> | |||
) | |||
} | |||
} | |||
const system = new System({ | |||
plugins: [ | |||
ViewPlugin, | |||
{ | |||
components: { | |||
ContainerComponent | |||
} | |||
}, | |||
{ | |||
statePlugins: { | |||
example: { | |||
selectors: { | |||
foo() { return "and this came from the system" } | |||
} | |||
} | |||
} | |||
} | |||
] | |||
}) | |||
// When | |||
var Component = system.getSystem().getComponent("ContainerComponent", true) | |||
const renderedComponent = render( | |||
<Provider store={system.getStore()}> | |||
<Component fromOwnProps="and this came from my own props" /> | |||
</Provider> | |||
) | |||
// Then | |||
expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props") | |||
}) | |||
it("gives the system and own props as props to a container's `mapStateToProps` function", function() { | |||
// Given | |||
class ContainerComponent extends PureComponent { | |||
mapStateToProps(nextState, props) { | |||
const { exampleSelectors, fromMapState, fromOwnProps } = props | |||
return { | |||
"fromMapState": `This came from mapStateToProps ${exampleSelectors.foo()} ${fromOwnProps}` | |||
} | |||
} | |||
static defaultProps = { | |||
"fromMapState" : "" | |||
} | |||
render() { | |||
const { fromMapState } = this.props | |||
return ( | |||
<div>{ fromMapState }</div> | |||
) | |||
} | |||
} | |||
const system = new System({ | |||
plugins: [ | |||
ViewPlugin, | |||
{ | |||
components: { | |||
ContainerComponent | |||
} | |||
}, | |||
{ | |||
statePlugins: { | |||
example: { | |||
selectors: { | |||
foo() { return "and this came from the system" } | |||
} | |||
} | |||
} | |||
} | |||
] | |||
}) | |||
// When | |||
var Component = system.getSystem().getComponent("ContainerComponent", true) | |||
const renderedComponent = render( | |||
<Provider store={system.getStore()}> | |||
<Component fromOwnProps="and this came from my own props" /> | |||
</Provider> | |||
) | |||
// Then | |||
expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props") | |||
}) | |||
}) | |||
}) |