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 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 ```javascript
const MyWrapBuiltinComponentPlugin = function(system) { const MyWrapBuiltinComponentPlugin = function(system) {
@@ -310,9 +310,12 @@ const MyWrapBuiltinComponentPlugin = function(system) {
} }
``` ```
```javascript Here's another example that includes a code sample of a component that will be wrapped:
// Overriding a component from a plugin
```javascript
///// Overriding a component from a plugin
// Here's our normal, unmodified component.
const MyNumberDisplayPlugin = function(system) { const MyNumberDisplayPlugin = function(system) {
return { return {
components: { components: {
@@ -321,6 +324,7 @@ const MyNumberDisplayPlugin = function(system) {
} }
} }
// Here's a component wrapper defined as a function.
const MyWrapComponentPlugin = function(system) { const MyWrapComponentPlugin = function(system) {
return { return {
wrapComponents: { wrapComponents: {
@@ -328,6 +332,7 @@ const MyWrapComponentPlugin = function(system) {
if(props.number > 10) { if(props.number > 10) {
return <div> return <div>
<h3>Warning! Big number ahead.</h3> <h3>Warning! Big number ahead.</h3>
<OriginalComponent {...props} />
</div> </div>
} else { } else {
return <Original {...props} /> 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 ##### fn
The fn interface allows you to add helper functions to the system for use elsewhere. 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: [ presets: [
SwaggerUIBundle.presets.apis, SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset SwaggerUIBundle.SwaggerUIStandalonePreset
] ],
layout: "StandaloneLayout" 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: You can embed Swagger-UI's code directly in your HTML by using unkpg's interface:
```html ```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 --> <!-- `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 Schemes = getComponent( "schemes" )
const OperationServers = getComponent( "OperationServers" ) const OperationServers = getComponent( "OperationServers" )
const OperationExt = getComponent( "OperationExt" ) const OperationExt = getComponent( "OperationExt" )
const DeepLink = getComponent( "DeepLink" )
const { showExtensions } = getConfigs() const { showExtensions } = getConfigs()
// 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"))) && !responses.get("default")
response = response.set("notDocumented", notDocumented) response = response.set("notDocumented", notDocumented)
} }
@@ -120,12 +121,11 @@ export default class Operation extends PureComponent {
and pulled in with getComponent */} and pulled in with getComponent */}
<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 <DeepLink
className="nostyle" enabled={isDeepLinkingEnabled}
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null} isShown={isShown}
href={isDeepLinkingEnabled ? `#/${isShownKey.join("/")}` : null}> path={`${isShownKey.join("/")}`}
<span>{path}</span> text={path} />
</a>
<JumpToPath path={specPath} /> {/*TODO: use wrapComponents here, swagger-ui doesn't care about jumpToPath */} <JumpToPath path={specPath} /> {/*TODO: use wrapComponents here, swagger-ui doesn't care about jumpToPath */}
</span> </span>

View File

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

View File

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

View File

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

View File

@@ -46,7 +46,7 @@ export default function authorize ( { auth, authActions, errActions, configs, au
authId: name, authId: name,
source: "validation", source: "validation",
level: "error", 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 return
} }

View File

@@ -103,30 +103,30 @@ export function positionRangeForPath(yaml, path) {
let ast = cachedCompose(yaml) 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. // path is empty.
return find(ast) return find(ast)
function find(current) { function find(astValue, astKeyValue) {
if (current.tag === MAP_TAG) { if (astValue.tag === MAP_TAG) {
for (i = 0; i < current.value.length; i++) { for (i = 0; i < astValue.value.length; i++) {
var pair = current.value[i] var pair = astValue.value[i]
var key = pair[0] var key = pair[0]
var value = pair[1] var value = pair[1]
if (key.value === path[0]) { if (key.value === path[0]) {
path.shift() path.shift()
return find(value) return find(value, key)
} }
} }
} }
if (current.tag === SEQ_TAG) { if (astValue.tag === SEQ_TAG) {
var item = current.value[path[0]] var item = astValue.value[path[0]]
if (item && item.tag) { if (item && item.tag) {
path.shift() path.shift()
return find(item) return find(item, astKeyValue)
} }
} }
@@ -135,17 +135,35 @@ export function positionRangeForPath(yaml, path) {
return invalidRange return invalidRange
} }
return { const range = {
/* jshint camelcase: false */
start: { start: {
line: current.start_mark.line, line: astValue.start_mark.line,
column: current.start_mark.column column: astValue.start_mark.column,
pointer: astValue.start_mark.pointer,
}, },
end: { end: {
line: current.end_mark.line, line: astValue.end_mark.line,
column: current.end_mark.column 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 YAML from "js-yaml"
import parseUrl from "url-parse" import parseUrl from "url-parse"
import serializeError from "serialize-error" import serializeError from "serialize-error"
import isString from "lodash/isString"
import { isJSONObject } from "core/utils" import { isJSONObject } from "core/utils"
// Actions conform to FSA (flux-standard-actions) // 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 UPDATE_RESOLVED = "spec_update_resolved"
export const SET_SCHEME = "set_scheme" export const SET_SCHEME = "set_scheme"
export function updateSpec(spec) { const toStr = (str) => isString(str) ? str : ""
if(spec instanceof Error) {
return {type: UPDATE_SPEC, error: true, payload: spec}
}
export function updateSpec(spec) {
const cleanSpec = (toStr(spec)).replace(/\t/g, " ")
if(typeof spec === "string") { if(typeof spec === "string") {
return { return {
type: UPDATE_SPEC, type: UPDATE_SPEC,
payload: spec.replace(/\t/g, " ") || "" payload: cleanSpec
} }
} }
return {
type: UPDATE_SPEC,
payload: ""
}
} }
export function updateResolved(spec) { export function updateResolved(spec) {
@@ -52,9 +47,6 @@ export function updateUrl(url) {
} }
export function updateJsonSpec(json) { 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} return {type: UPDATE_JSON, payload: json}
} }
@@ -76,7 +68,10 @@ export const parseToJson = (str) => ({specActions, specSelectors, errActions}) =
line: e.mark && e.mark.line ? e.mark.line + 1 : undefined line: e.mark && e.mark.line ? e.mark.line + 1 : undefined
}) })
} }
return specActions.updateJsonSpec(json) if(json) {
return specActions.updateJsonSpec(json)
}
return {}
} }
export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => { export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => {
@@ -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 ){ export function changeParam( path, paramName, paramIn, value, isXml ){
return { return {
type: UPDATE_PARAM, type: UPDATE_PARAM,

View File

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

View File

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

View File

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