未验证 提交 7254e8b3 编写于 作者: K kyle 提交者: GitHub

Merge branch 'master' into feature/add-type-example-for-headers

......@@ -94,8 +94,9 @@ export default class BaseLayout extends React.Component {
) : null }
{ servers && servers.size ? (
<div className="server-container">
<div className="global-server-container">
<Col className="servers wrapper" mobile={12}>
<span className="servers-title">Server</span>
<Servers
servers={servers}
currentServer={oas3Selectors.selectedServer()}
......
......@@ -22,6 +22,7 @@ export default class Operation extends PureComponent {
specActions: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired,
oas3Actions: PropTypes.object.isRequired,
oas3Selectors: PropTypes.object.isRequired,
layoutActions: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object.isRequired,
fn: PropTypes.object.isRequired
......@@ -48,7 +49,8 @@ export default class Operation extends PureComponent {
specSelectors,
authActions,
authSelectors,
oas3Actions
oas3Actions,
oas3Selectors
} = this.props
let operationProps = this.props.operation
......@@ -96,6 +98,7 @@ export default class Operation extends PureComponent {
const Collapse = getComponent( "Collapse" )
const Markdown = getComponent( "Markdown" )
const Schemes = getComponent( "schemes" )
const OperationServers = getComponent( "OperationServers" )
const OperationExt = getComponent( "OperationExt" )
const { showExtensions } = getConfigs()
......@@ -182,6 +185,21 @@ export default class Operation extends PureComponent {
getConfigs={ getConfigs }
/>
{ !tryItOutEnabled ? null :
<OperationServers
getComponent={getComponent}
path={path}
method={method}
operationServers={operation.get("servers")}
pathServers={specSelectors.paths().getIn([path, "servers"])}
getSelectedServer={oas3Selectors.selectedServer}
setSelectedServer={oas3Actions.setSelectedServer}
setServerVariableValue={oas3Actions.setServerVariableValue}
getServerVariable={oas3Selectors.serverVariableValue}
getEffectiveServerValue={oas3Selectors.serverEffectiveValue}
/>
}
{!tryItOutEnabled || !allowTryItOut ? null : schemes && schemes.size ? <div className="opblock-schemes">
<Schemes schemes={ schemes }
path={ path }
......
......@@ -35,6 +35,7 @@ export default class OperationContainer extends PureComponent {
getComponent: PropTypes.func.isRequired,
authActions: PropTypes.object,
oas3Actions: PropTypes.object,
oas3Selectors: PropTypes.object,
authSelectors: PropTypes.object,
specActions: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired,
......@@ -149,6 +150,7 @@ export default class OperationContainer extends PureComponent {
authActions,
authSelectors,
oas3Actions,
oas3Selectors,
fn
} = this.props
......@@ -189,6 +191,7 @@ export default class OperationContainer extends PureComponent {
specActions={ specActions }
specSelectors={ specSelectors }
oas3Actions={oas3Actions}
oas3Selectors={oas3Selectors}
layoutActions={ layoutActions }
layoutSelectors={ layoutSelectors }
authActions={ authActions }
......
......@@ -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}
}
}
......@@ -35,9 +35,9 @@ export function setResponseContentType ({ 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 }
}
}
......@@ -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
}
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>
}
}
......@@ -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>
{
......
......@@ -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
......@@ -21,7 +22,8 @@ export default {
[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)
},
}
......@@ -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)
......
......@@ -228,9 +228,18 @@ export const executeRequest = (req) =>
}
if(specSelectors.isOAS3()) {
// OAS3 request feature support
req.server = oas3Selectors.selectedServer()
req.serverVariables = oas3Selectors.serverVariables(req.server).toJS()
const namespace = `${pathName}:${method}`
req.server = oas3Selectors.selectedServer(namespace) || oas3Selectors.selectedServer()
const namespaceVariables = oas3Selectors.serverVariables({
server: req.server,
namespace
}).toJS()
const globalVariables = oas3Selectors.serverVariables({ server: req.server }).toJS()
req.serverVariables = Object.keys(namespaceVariables).length ? namespaceVariables : globalVariables
req.requestContentType = oas3Selectors.requestContentType(pathName, method)
req.responseContentType = oas3Selectors.responseContentType(pathName, method) || "*/*"
const requestBody = oas3Selectors.requestBodyValue(pathName, method)
......
......@@ -650,78 +650,6 @@
}
}
.server-container
{
margin: 0 0 20px 0;
padding: 30px 0;
background: $server-container-background-color;
box-shadow: 0 1px 2px 0 rgba($server-container-box-shadow-color,.15);
.computed-url {
margin: 2em 0;
code {
color: $server-container-computed-url-code-font-color;
display: inline-block;
padding: 4px;
font-size: 16px;
margin: 0 1em;
font-style: italic;
}
}
.servers
{
display: flex;
align-items: center;
.servers-title {
margin-right: 1em;
}
> label
{
font-size: 12px;
display: flex;
flex-direction: column;
margin: -20px 15px 0 0;
@include text_headline();
select
{
min-width: 130px;
}
}
table {
tr {
width: 30em;
}
td {
display: inline-block;
max-width: 15em;
vertical-align: middle;
padding-top: 10px;
padding-bottom: 10px;
&:first-of-type {
padding-right: 2em;
}
input {
width: 100%;
height: 100%;
}
}
}
}
}
.loading-container
{
padding: 40px 0 60px;
......
.servers
{
> label
{
font-size: 12px;
margin: -20px 15px 0 0;
@include text_headline();
select
{
min-width: 130px;
}
}
h4.message {
padding-bottom: 2em;
}
table {
tr {
width: 30em;
}
td {
display: inline-block;
max-width: 15em;
vertical-align: middle;
padding-top: 10px;
padding-bottom: 10px;
&:first-of-type {
padding-right: 2em;
}
input {
width: 100%;
height: 100%;
}
}
}
.computed-url {
margin: 2em 0;
code {
display: inline-block;
padding: 4px;
font-size: 16px;
margin: 0 1em;
}
}
}
.global-server-container
{
margin: 0 0 20px 0;
padding: 30px 0;
background: $server-container-background-color;
box-shadow: 0 1px 2px 0 rgba($server-container-box-shadow-color,.15);
.servers-title {
line-height: 2em;
font-weight: bold;
}
}
.operation-servers {
h4.message {
margin-bottom: 2em;
}
}
......@@ -9,6 +9,7 @@
@import 'form';
@import 'modal';
@import 'models';
@import 'servers';
@import 'table';
@import 'topbar';
@import 'information';
......
import expect from "expect"
import { fromJS, OrderedMap } from "immutable"
import {
selectedServer,
serverVariableValue,
serverVariables,
serverEffectiveValue
} from "corePlugins/oas3/selectors"
import reducers from "corePlugins/oas3/reducers"
import {
setSelectedServer,
setServerVariableValue,
} from "corePlugins/oas3/actions"
describe("OAS3 plugin - state", function() {
describe("action + reducer + selector integration", function() {
describe("selectedServer", function() {
it("should set and get a global selectedServer", function() {
const state = new OrderedMap()
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setSelectedServer("http://google.com")
// Collect the new state
const newState = reducers["oas3_set_servers"](state, action)
// Get the value with the selector
const res = selectedServer(newState)(system)
expect(res).toEqual("http://google.com")
})
it("should set and get a namespaced selectedServer", function() {
const state = fromJS({
selectedServer: "http://yahoo.com"
})
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setSelectedServer("http://google.com", "myOperation")
// Collect the new state
const newState = reducers["oas3_set_servers"](state, action)
// Get the value with the selector
const res = selectedServer(newState, "myOperation")(system)
// Get the global selected server
const globalRes = selectedServer(newState)(system)
expect(res).toEqual("http://google.com")
expect(globalRes).toEqual("http://yahoo.com")
})
})
describe("serverVariableValue", function() {
it("should set and get a global serverVariableValue", function() {
const state = new OrderedMap()
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setServerVariableValue({
server: "google.com",
key: "foo",
val: "bar"
})
// Collect the new state
const newState = reducers["oas3_set_server_variable_value"](state, action)
// Get the value with the selector
const res = serverVariableValue(newState, "google.com", "foo")(system)
expect(res).toEqual("bar")
})
it("should set and get a namespaced serverVariableValue", function() {
const state = fromJS({
serverVariableValues: {
"google.com": {
foo: "123"
}
}
})
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setServerVariableValue({
namespace: "myOperation",
server: "google.com",
key: "foo",
val: "bar"
})
// Collect the new state
const newState = reducers["oas3_set_server_variable_value"](state, action)
// Get the value with the selector
const res = serverVariableValue(newState, {
namespace: "myOperation",
server: "google.com"
}, "foo")(system)
// Get the global value, to cross-check
const globalRes = serverVariableValue(newState, {
server: "google.com"
}, "foo")(system)
expect(res).toEqual("bar")
expect(globalRes).toEqual("123")
})
})
describe("serverVariables", function() {
it("should set and get global serverVariables", function() {
const state = new OrderedMap()
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setServerVariableValue({
server: "google.com",
key: "foo",
val: "bar"
})
// Collect the new state
const newState = reducers["oas3_set_server_variable_value"](state, action)
// Get the value with the selector
const res = serverVariables(newState, "google.com", "foo")(system)
expect(res.toJS()).toEqual({
foo: "bar"
})
})
it("should set and get namespaced serverVariables", function() {
const state = fromJS({
serverVariableValues: {
"google.com": {
foo: "123"
}
}
})
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setServerVariableValue({
namespace: "myOperation",
server: "google.com",
key: "foo",
val: "bar"
})
// Collect the new state
const newState = reducers["oas3_set_server_variable_value"](state, action)
// Get the value with the selector
const res = serverVariables(newState, {
namespace: "myOperation",
server: "google.com"
}, "foo")(system)
// Get the global value, to cross-check
const globalRes = serverVariables(newState, {
server: "google.com"
}, "foo")(system)
expect(res.toJS()).toEqual({
foo: "bar"
})
expect(globalRes.toJS()).toEqual({
foo: "123"
})
})
})
describe("serverEffectiveValue", function() {
it("should set variable values and compute a URL for a namespaced server", function() {
const state = fromJS({
serverVariableValues: {
"google.com/{foo}": {
foo: "123"
}
}
})
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Create the action
const action = setServerVariableValue({
namespace: "myOperation",
server: "google.com/{foo}",
key: "foo",
val: "bar"
})
// Collect the new state
const newState = reducers["oas3_set_server_variable_value"](state, action)
// Get the value with the selector
const res = serverEffectiveValue(newState, {
namespace: "myOperation",
server: "google.com/{foo}"
})(system)
// Get the global value, to cross-check
const globalRes = serverEffectiveValue(newState, {
server: "google.com/{foo}"
})(system)
expect(res).toEqual("google.com/bar")
expect(globalRes).toEqual("google.com/123")
})
})
})
describe("selectors", function() {
describe("serverEffectiveValue", function() {
it("should compute global serverEffectiveValues", function() {
const state = fromJS({
serverVariableValues: {
"google.com/{foo}/{bar}": {
foo: "123",
bar: "456"
}
}
})
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Get the value with the selector
const res = serverEffectiveValue(state, "google.com/{foo}/{bar}")(system)
expect(res).toEqual("google.com/123/456")
})
it("should handle multiple variable instances", function() {
const state = fromJS({
serverVariableValues: {
"google.com/{foo}/{foo}/{bar}": {
foo: "123",
bar: "456"
}
}
})
const system = {
// needed to handle `onlyOAS3` wrapper
getSystem() {
return {
specSelectors: {
specJson: () => {
return fromJS({ openapi: "3.0.0" })
}
}
}
}
}
// Get the value with the selector
const res = serverEffectiveValue(state, "google.com/{foo}/{foo}/{bar}")(system)
expect(res).toEqual("google.com/123/123/456")
})
})
})
})
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册