Merge branch 'master' into master
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 -->
|
||||
```
|
||||
|
||||
|
||||
20
src/core/components/deep-link.jsx
Normal file
20
src/core/components/deep-link.jsx
Normal 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
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,7 +68,10 @@ 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}) => {
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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}`} />
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user