Merge branch 'master' into master

This commit is contained in:
kyle
2017-12-15 18:22:07 -08:00
committed by GitHub
14 changed files with 127 additions and 65 deletions

1
.agignore Normal file
View File

@@ -0,0 +1 @@
dist/

View File

@@ -293,7 +293,7 @@ const MyWrapSelectorsPlugin = function(system) {
Wrap Components allow you to override a component registered within the system.
Wrap Components are function factories with the signature `(OriginalComponent, system) => props => ReactElement`.
Wrap Components are function factories with the signature `(OriginalComponent, system) => props => ReactElement`. If you'd prefer to provide a React component class, `(OriginalComponent, system) => ReactClass` works as well.
```javascript
const MyWrapBuiltinComponentPlugin = function(system) {
@@ -310,9 +310,12 @@ const MyWrapBuiltinComponentPlugin = function(system) {
}
```
```javascript
// Overriding a component from a plugin
Here's another example that includes a code sample of a component that will be wrapped:
```javascript
///// Overriding a component from a plugin
// Here's our normal, unmodified component.
const MyNumberDisplayPlugin = function(system) {
return {
components: {
@@ -321,6 +324,7 @@ const MyNumberDisplayPlugin = function(system) {
}
}
// Here's a component wrapper defined as a function.
const MyWrapComponentPlugin = function(system) {
return {
wrapComponents: {
@@ -328,6 +332,7 @@ const MyWrapComponentPlugin = function(system) {
if(props.number > 10) {
return <div>
<h3>Warning! Big number ahead.</h3>
<OriginalComponent {...props} />
</div>
} else {
return <Original {...props} />
@@ -336,8 +341,30 @@ const MyWrapComponentPlugin = function(system) {
}
}
}
// Alternatively, here's the same component wrapper defined as a class.
const MyWrapComponentPlugin = function(system) {
return {
wrapComponents: {
NumberDisplay: (Original, system) => class WrappedNumberDisplay extends React.component {
render() {
if(props.number > 10) {
return <div>
<h3>Warning! Big number ahead.</h3>
<OriginalComponent {...props} />
</div>
} else {
return <Original {...props} />
}
}
}
}
}
}
```
##### fn
The fn interface allows you to add helper functions to the system for use elsewhere.

View File

@@ -49,7 +49,7 @@ const ui = SwaggerUIBundle({
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
]
],
layout: "StandaloneLayout"
})
```
@@ -86,7 +86,7 @@ This will serve Swagger UI at `/swagger` instead of `/`.
You can embed Swagger-UI's code directly in your HTML by using unkpg's interface:
```html
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js">
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
<!-- `SwaggerUIBundle` is now available on the page -->
```

View File

@@ -0,0 +1,20 @@
import React from "react"
import PropTypes from "prop-types"
export const DeepLink = ({ enabled, path, text }) => {
return (
<a className="nostyle"
onClick={enabled ? (e) => e.preventDefault() : null}
href={enabled ? `#/${path}` : null}>
<span>{text}</span>
</a>
)
}
DeepLink.propTypes = {
enabled: PropTypes.bool,
isShown: PropTypes.bool,
path: PropTypes.string,
text: PropTypes.string
}
export default DeepLink

View File

@@ -102,12 +102,13 @@ export default class Operation extends PureComponent {
const Schemes = getComponent( "schemes" )
const OperationServers = getComponent( "OperationServers" )
const OperationExt = getComponent( "OperationExt" )
const DeepLink = getComponent( "DeepLink" )
const { showExtensions } = getConfigs()
// Merge in Live Response
if(responses && response && response.size > 0) {
let notDocumented = !responses.get(String(response.get("status")))
let notDocumented = !responses.get(String(response.get("status"))) && !responses.get("default")
response = response.set("notDocumented", notDocumented)
}
@@ -120,12 +121,11 @@ export default class Operation extends PureComponent {
and pulled in with getComponent */}
<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 ? `#/${isShownKey.join("/")}` : null}>
<span>{path}</span>
</a>
<DeepLink
enabled={isDeepLinkingEnabled}
isShown={isShown}
path={`${isShownKey.join("/")}`}
text={path} />
<JumpToPath path={specPath} /> {/*TODO: use wrapComponents here, swagger-ui doesn't care about jumpToPath */}
</span>

View File

@@ -37,6 +37,7 @@ export default class Operations extends React.Component {
const OperationContainer = getComponent("OperationContainer", true)
const Collapse = getComponent("Collapse")
const Markdown = getComponent("Markdown")
const DeepLink = getComponent("DeepLink")
let {
docExpansion,
@@ -79,12 +80,11 @@ export default class Operations extends React.Component {
onClick={() => layoutActions.show(isShownKey, !showTag)}
className={!tagDescription ? "opblock-tag no-desc" : "opblock-tag" }
id={isShownKey.join("-")}>
<a
className="nostyle"
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
href= {isDeepLinkingEnabled ? `#/${tag}` : null}>
<span>{tag}</span>
</a>
<DeepLink
enabled={isDeepLinkingEnabled}
isShown={showTag}
path={tag}
text={tag} />
{ !tagDescription ? null :
<small>
<Markdown source={tagDescription} />

View File

@@ -47,7 +47,7 @@ export default class ParamBody extends PureComponent {
updateValues = (props) => {
let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) : {}
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) : fromJS({})
let isXml = /xml/i.test(consumesValue)
let isJson = /json/i.test(consumesValue)
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")

View File

@@ -43,7 +43,11 @@ export default class ResponseBody extends React.Component {
// Image
} else if (/^image\//i.test(contentType)) {
if(contentType.includes("svg")) {
bodyEl = <div> { content } </div>
} else {
bodyEl = <img style={{ maxWidth: "100%" }} src={ window.URL.createObjectURL(content) } />
}
// Audio
} else if (/^audio\//i.test(contentType)) {

View File

@@ -46,7 +46,7 @@ export default function authorize ( { auth, authActions, errActions, configs, au
authId: name,
source: "validation",
level: "error",
message: "oauth2RedirectUri configuration is not passed. Oauth2 authorization cannot be performed."
message: "oauth2RedirectUrl configuration is not passed. Oauth2 authorization cannot be performed."
})
return
}

View File

@@ -103,30 +103,30 @@ export function positionRangeForPath(yaml, path) {
let ast = cachedCompose(yaml)
// simply walks the tree using current path recursively to the point that
// simply walks the tree using astValue path recursively to the point that
// path is empty.
return find(ast)
function find(current) {
if (current.tag === MAP_TAG) {
for (i = 0; i < current.value.length; i++) {
var pair = current.value[i]
function find(astValue, astKeyValue) {
if (astValue.tag === MAP_TAG) {
for (i = 0; i < astValue.value.length; i++) {
var pair = astValue.value[i]
var key = pair[0]
var value = pair[1]
if (key.value === path[0]) {
path.shift()
return find(value)
return find(value, key)
}
}
}
if (current.tag === SEQ_TAG) {
var item = current.value[path[0]]
if (astValue.tag === SEQ_TAG) {
var item = astValue.value[path[0]]
if (item && item.tag) {
path.shift()
return find(item)
return find(item, astKeyValue)
}
}
@@ -135,17 +135,35 @@ export function positionRangeForPath(yaml, path) {
return invalidRange
}
return {
/* jshint camelcase: false */
const range = {
start: {
line: current.start_mark.line,
column: current.start_mark.column
line: astValue.start_mark.line,
column: astValue.start_mark.column,
pointer: astValue.start_mark.pointer,
},
end: {
line: current.end_mark.line,
column: current.end_mark.column
line: astValue.end_mark.line,
column: astValue.end_mark.column,
pointer: astValue.end_mark.pointer,
}
}
if(astKeyValue) {
// eslint-disable-next-line camelcase
range.key_start = {
line: astKeyValue.start_mark.line,
column: astKeyValue.start_mark.column,
pointer: astKeyValue.start_mark.pointer,
}
// eslint-disable-next-line camelcase
range.key_end = {
line: astKeyValue.end_mark.line,
column: astKeyValue.end_mark.column,
pointer: astKeyValue.end_mark.pointer,
}
}
return range
}
}

View File

@@ -1,6 +1,7 @@
import YAML from "js-yaml"
import parseUrl from "url-parse"
import serializeError from "serialize-error"
import isString from "lodash/isString"
import { isJSONObject } from "core/utils"
// Actions conform to FSA (flux-standard-actions)
@@ -22,22 +23,16 @@ export const UPDATE_OPERATION_VALUE = "spec_update_operation_value"
export const UPDATE_RESOLVED = "spec_update_resolved"
export const SET_SCHEME = "set_scheme"
export function updateSpec(spec) {
if(spec instanceof Error) {
return {type: UPDATE_SPEC, error: true, payload: spec}
}
const toStr = (str) => isString(str) ? str : ""
export function updateSpec(spec) {
const cleanSpec = (toStr(spec)).replace(/\t/g, " ")
if(typeof spec === "string") {
return {
type: UPDATE_SPEC,
payload: spec.replace(/\t/g, " ") || ""
payload: cleanSpec
}
}
return {
type: UPDATE_SPEC,
payload: ""
}
}
export function updateResolved(spec) {
@@ -52,9 +47,6 @@ export function updateUrl(url) {
}
export function updateJsonSpec(json) {
if(!json || typeof json !== "object") {
throw new Error("updateJson must only accept a simple JSON object")
}
return {type: UPDATE_JSON, payload: json}
}
@@ -76,8 +68,11 @@ export const parseToJson = (str) => ({specActions, specSelectors, errActions}) =
line: e.mark && e.mark.line ? e.mark.line + 1 : undefined
})
}
if(json) {
return specActions.updateJsonSpec(json)
}
return {}
}
export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => {
const {
@@ -130,18 +125,6 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio
})
}
export const formatIntoYaml = () => ({specActions, specSelectors}) => {
let { specStr } = specSelectors
let { updateSpec } = specActions
try {
let yaml = YAML.safeDump(YAML.safeLoad(specStr()), {indent: 2})
updateSpec(yaml)
} catch(e) {
updateSpec(e)
}
}
export function changeParam( path, paramName, paramIn, value, isXml ){
return {
type: UPDATE_PARAM,

View File

@@ -256,10 +256,11 @@ export const allowTryItOutFor = () => {
// Get the parameter value by parameter name
export function getParameter(state, pathMethod, name, inType) {
pathMethod = pathMethod || []
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([]))
return params.filter( (p) => {
return params.find( (p) => {
return Map.isMap(p) && p.get("name") === name && p.get("in") === inType
}).first()
}) || Map() // Always return a map
}
export const hasHost = createSelector(
@@ -272,6 +273,7 @@ export const hasHost = createSelector(
// Get the parameter values, that the user filled out
export function parameterValues(state, pathMethod, isXml) {
pathMethod = pathMethod || []
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([]))
return params.reduce( (hash, p) => {
let value = isXml && p.get("in") === "body" ? p.get("value_xml") : p.get("value")
@@ -295,6 +297,7 @@ export function parametersIncludeType(parameters, typeValue="") {
// Get the consumes/produces value that the user selected
export function contentTypeValues(state, pathMethod) {
pathMethod = pathMethod || []
let op = spec(state).getIn(["paths", ...pathMethod], fromJS({}))
const parameters = op.get("parameters") || new List()
@@ -313,6 +316,7 @@ export function contentTypeValues(state, pathMethod) {
// Get the consumes/produces by path
export function operationConsumes(state, pathMethod) {
pathMethod = pathMethod || []
return spec(state).getIn(["paths", ...pathMethod, "consumes"], fromJS({}))
}
@@ -329,6 +333,7 @@ export const canExecuteScheme = ( state, path, method ) => {
}
export const validateBeforeExecute = ( state, pathMethod ) => {
pathMethod = pathMethod || []
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([]))
let isValid = true

View File

@@ -61,6 +61,7 @@ import PrimitiveModel from "core/components/primitive-model"
import Property from "core/components/property"
import TryItOutButton from "core/components/try-it-out-button"
import VersionStamp from "core/components/version-stamp"
import DeepLink from "core/components/deep-link"
import Markdown from "core/components/providers/markdown"
@@ -121,7 +122,8 @@ export default function() {
OperationExt,
OperationExtRow,
ParameterExt,
OperationContainer
OperationContainer,
DeepLink
}
}

View File

@@ -3,11 +3,13 @@ import React from "react"
import expect, { createSpy } from "expect"
import { render } from "enzyme"
import { fromJS } from "immutable"
import DeepLink from "components/deep-link"
import Operations from "components/operations"
import {Collapse} from "components/layout-utils"
const components = {
Collapse,
DeepLink,
OperationContainer: ({ path, method }) => <span className="mocked-op" id={`${path}-${method}`} />
}