Skip to content

Commit 3f9b999

Browse files
authored
Merge pull request #3648 from swagger-api/ft/oas3-tio
OAS3: Try-It-Out
2 parents f618ed6 + a2b5728 commit 3f9b999

File tree

19 files changed

+659
-59
lines changed

19 files changed

+659
-59
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"scroll-to-element": "^2.0.0",
7676
"serialize-error": "2.0.0",
7777
"shallowequal": "0.2.2",
78-
"swagger-client": "3.0.20",
78+
"swagger-client": "swagger-api/swagger-js#ft/oas3-tio",
7979
"url-parse": "^1.1.8",
8080
"whatwg-fetch": "0.11.1",
8181
"worker-loader": "^0.7.1",

src/core/components/layouts/base.jsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export default class BaseLayout extends React.Component {
88
errActions: PropTypes.object.isRequired,
99
specActions: PropTypes.object.isRequired,
1010
specSelectors: PropTypes.object.isRequired,
11+
oas3Selectors: PropTypes.object.isRequired,
12+
oas3Actions: PropTypes.object.isRequired,
1113
layoutSelectors: PropTypes.object.isRequired,
1214
layoutActions: PropTypes.object.isRequired,
1315
getComponent: PropTypes.func.isRequired
@@ -19,7 +21,14 @@ export default class BaseLayout extends React.Component {
1921
}
2022

2123
render() {
22-
let { specSelectors, specActions, getComponent, layoutSelectors } = this.props
24+
let {
25+
specSelectors,
26+
specActions,
27+
getComponent,
28+
layoutSelectors,
29+
oas3Selectors,
30+
oas3Actions
31+
} = this.props
2332

2433
let info = specSelectors.info()
2534
let url = specSelectors.url()
@@ -28,13 +37,15 @@ export default class BaseLayout extends React.Component {
2837
let securityDefinitions = specSelectors.securityDefinitions()
2938
let externalDocs = specSelectors.externalDocs()
3039
let schemes = specSelectors.schemes()
40+
let servers = specSelectors.servers()
3141

3242
let Info = getComponent("info")
3343
let Operations = getComponent("operations", true)
3444
let Models = getComponent("Models", true)
3545
let AuthorizeBtn = getComponent("authorizeBtn", true)
3646
let Row = getComponent("Row")
3747
let Col = getComponent("Col")
48+
let Servers = getComponent("Servers")
3849
let Errors = getComponent("errors", true)
3950

4051
let isLoading = specSelectors.loadingStatus() === "loading"
@@ -82,6 +93,22 @@ export default class BaseLayout extends React.Component {
8293
</div>
8394
) : null }
8495

96+
{ servers && servers.size ? (
97+
<div className="server-container">
98+
<Col className="servers wrapper" mobile={12}>
99+
<Servers
100+
servers={servers}
101+
currentServer={oas3Selectors.selectedServer()}
102+
setSelectedServer={oas3Actions.setSelectedServer}
103+
setServerVariableValue={oas3Actions.setServerVariableValue}
104+
getServerVariable={oas3Selectors.serverVariableValue}
105+
getEffectiveServerValue={oas3Selectors.serverEffectiveValue}
106+
/>
107+
</Col>
108+
</div>
109+
110+
) : null}
111+
85112
{
86113
filter === null || filter === false ? null :
87114
<div className="filter-container">

src/core/plugins/oas3/actions.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Actions conform to FSA (flux-standard-actions)
2+
// {type: string,payload: Any|Error, meta: obj, error: bool}
3+
4+
export const UPDATE_SELECTED_SERVER = "oas3_set_servers"
5+
export const UPDATE_REQUEST_BODY_VALUE = "oas3_set_request_body_value"
6+
export const UPDATE_REQUEST_CONTENT_TYPE = "oas3_set_request_content_type"
7+
export const UPDATE_SERVER_VARIABLE_VALUE = "oas3_set_server_variable_value"
8+
9+
export function setSelectedServer (selectedServerUrl) {
10+
return {
11+
type: UPDATE_SELECTED_SERVER,
12+
payload: selectedServerUrl
13+
}
14+
}
15+
16+
export function setRequestBodyValue ({ value, pathMethod }) {
17+
return {
18+
type: UPDATE_REQUEST_BODY_VALUE,
19+
payload: { value, pathMethod }
20+
}
21+
}
22+
23+
export function setRequestContentType ({ value, pathMethod }) {
24+
return {
25+
type: UPDATE_REQUEST_CONTENT_TYPE,
26+
payload: { value, pathMethod }
27+
}
28+
}
29+
30+
export function setServerVariableValue ({ server, key, val }) {
31+
return {
32+
type: UPDATE_SERVER_VARIABLE_VALUE,
33+
payload: { server, key, val }
34+
}
35+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import Callbacks from "./callbacks"
22
import RequestBody from "./request-body"
33
import OperationLink from "./operation-link.jsx"
4+
import Servers from "./servers"
5+
import RequestBodyEditor from "./request-body-editor"
46

57
export default {
68
Callbacks,
79
RequestBody,
10+
Servers,
11+
RequestBodyEditor,
812
operationLink: OperationLink
913
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import React, { PureComponent } from "react"
2+
import PropTypes from "prop-types"
3+
import { fromJS } from "immutable"
4+
import { getSampleSchema } from "core/utils"
5+
6+
const NOOP = Function.prototype
7+
8+
export default class RequestBodyEditor extends PureComponent {
9+
10+
static propTypes = {
11+
requestBody: PropTypes.object.isRequired,
12+
mediaType: PropTypes.string.isRequired,
13+
onChange: PropTypes.func,
14+
getComponent: PropTypes.func.isRequired,
15+
isExecute: PropTypes.bool,
16+
specSelectors: PropTypes.object.isRequired,
17+
};
18+
19+
static defaultProps = {
20+
mediaType: "application/json",
21+
requestBody: fromJS({}),
22+
onChange: NOOP,
23+
};
24+
25+
constructor(props, context) {
26+
super(props, context)
27+
28+
this.state = {
29+
isEditBox: false,
30+
value: ""
31+
}
32+
}
33+
34+
componentDidMount() {
35+
this.setValueToSample.call(this)
36+
}
37+
38+
componentWillReceiveProps(nextProps) {
39+
if(this.props.mediaType !== nextProps.mediaType) {
40+
// media type was changed
41+
this.setValueToSample(nextProps.mediaType)
42+
}
43+
44+
if(!this.props.isExecute && nextProps.isExecute) {
45+
// we just entered execute mode,
46+
// so enable editing for convenience
47+
this.setState({ isEditBox: true })
48+
}
49+
}
50+
51+
setValueToSample = (explicitMediaType) => {
52+
this.onChange(this.sample(explicitMediaType))
53+
}
54+
55+
sample = (explicitMediaType) => {
56+
let { requestBody, mediaType } = this.props
57+
let schema = requestBody.getIn(["content", explicitMediaType || mediaType, "schema"]).toJS()
58+
59+
return getSampleSchema(schema, explicitMediaType || mediaType, {
60+
includeWriteOnly: true
61+
})
62+
}
63+
64+
onChange = (value) => {
65+
this.setState({value})
66+
this.props.onChange(value)
67+
}
68+
69+
handleOnChange = e => {
70+
const { mediaType } = this.props
71+
const isJson = /json/i.test(mediaType)
72+
const inputValue = isJson ? e.target.value.trim() : e.target.value
73+
74+
this.onChange(inputValue)
75+
}
76+
77+
toggleIsEditBox = () => this.setState( state => ({isEditBox: !state.isEditBox}))
78+
79+
render() {
80+
let {
81+
isExecute,
82+
getComponent,
83+
} = this.props
84+
85+
const Button = getComponent("Button")
86+
const TextArea = getComponent("TextArea")
87+
const HighlightCode = getComponent("highlightCode")
88+
89+
let { value, isEditBox } = this.state
90+
91+
return (
92+
<div className="body-param">
93+
{
94+
isEditBox && isExecute
95+
? <TextArea className={"body-param__text"} value={value} onChange={ this.handleOnChange }/>
96+
: (value && <HighlightCode className="body-param__example"
97+
value={ value }/>)
98+
}
99+
<div className="body-param-options">
100+
{
101+
!isExecute ? null
102+
: <div className="body-param-edit">
103+
<Button className={isEditBox ? "btn cancel body-param__example-edit" : "btn edit body-param__example-edit"}
104+
onClick={this.toggleIsEditBox}>{ isEditBox ? "Cancel" : "Edit"}
105+
</Button>
106+
</div>
107+
}
108+
</div>
109+
110+
</div>
111+
)
112+
113+
}
114+
}

src/core/plugins/oas3/components/request-body.jsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@ import React from "react"
22
import PropTypes from "prop-types"
33
import ImPropTypes from "react-immutable-proptypes"
44
import { OrderedMap } from "immutable"
5-
import { getSampleSchema } from "core/utils"
65

7-
8-
const RequestBody = ({ requestBody, getComponent, specSelectors, contentType }) => {
6+
const RequestBody = ({
7+
requestBody,
8+
getComponent,
9+
specSelectors,
10+
contentType,
11+
isExecute,
12+
onChange
13+
}) => {
914
const Markdown = getComponent("Markdown")
1015
const ModelExample = getComponent("modelExample")
11-
const HighlightCode = getComponent("highlightCode")
16+
const RequestBodyEditor = getComponent("RequestBodyEditor")
1217

1318
const requestBodyDescription = (requestBody && requestBody.get("description")) || null
1419
const requestBodyContent = (requestBody && requestBody.get("content")) || new OrderedMap()
1520
contentType = contentType || requestBodyContent.keySeq().first()
1621

1722
const mediaTypeValue = requestBodyContent.get(contentType)
1823

19-
const sampleSchema = getSampleSchema(mediaTypeValue.get("schema").toJS(), contentType, {
20-
includeWriteOnly: true
21-
})
22-
2324
return <div>
2425
{ requestBodyDescription &&
2526
<Markdown source={requestBodyDescription} />
@@ -28,8 +29,16 @@ const RequestBody = ({ requestBody, getComponent, specSelectors, contentType })
2829
getComponent={ getComponent }
2930
specSelectors={ specSelectors }
3031
expandDepth={1}
32+
isExecute={isExecute}
3133
schema={mediaTypeValue.get("schema")}
32-
example={<HighlightCode value={sampleSchema} />}
34+
example={<RequestBodyEditor
35+
requestBody={requestBody}
36+
onChange={onChange}
37+
mediaType={contentType}
38+
getComponent={getComponent}
39+
isExecute={isExecute}
40+
specSelectors={specSelectors}
41+
/>}
3342
/>
3443
</div>
3544
}
@@ -38,7 +47,9 @@ RequestBody.propTypes = {
3847
requestBody: ImPropTypes.orderedMap.isRequired,
3948
getComponent: PropTypes.func.isRequired,
4049
specSelectors: PropTypes.object.isRequired,
41-
contentType: PropTypes.string.isRequired
50+
contentType: PropTypes.string.isRequired,
51+
isExecute: PropTypes.bool.isRequired,
52+
onChange: PropTypes.func.isRequired
4253
}
4354

4455
export default RequestBody

0 commit comments

Comments
 (0)