Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1646b270f8 | ||
|
|
03f80dcc70 | ||
|
|
f982eb4894 | ||
|
|
10b4f5d8a7 | ||
|
|
9c2f9d2059 | ||
|
|
7469705bef | ||
|
|
57db23ed1f | ||
|
|
135fc34077 | ||
|
|
ca0b248df2 | ||
|
|
27156bb79d | ||
|
|
b03bf90664 | ||
|
|
a9ebdb8a7a | ||
|
|
68c689e491 | ||
|
|
150ebf3bc0 | ||
|
|
e07b105b29 | ||
|
|
022b660b8c | ||
|
|
7693dfe5bc | ||
|
|
7faf79ae38 | ||
|
|
9b5accc17f | ||
|
|
d0ffb2bb9d | ||
|
|
87572a856b | ||
|
|
292639de57 | ||
|
|
15dbc20efd | ||
|
|
5e72f68738 | ||
|
|
2b3a590e29 | ||
|
|
0413410a1d | ||
|
|
49333dfadc | ||
|
|
d65d7b3dd7 | ||
|
|
e594392920 | ||
|
|
48fd8f7689 | ||
|
|
a2f8d289a0 | ||
|
|
2dd25abbdd | ||
|
|
c1ae4c133d | ||
|
|
85c83931c4 | ||
|
|
b5c713a72b | ||
|
|
ca7f7ea78b | ||
|
|
bb54eaa127 | ||
|
|
a41cdfd650 | ||
|
|
4320118f17 | ||
|
|
7f19d791f8 | ||
|
|
9147d2eac2 | ||
|
|
1613455bc4 | ||
|
|
6ba6039eb7 | ||
|
|
f3cb0d7195 | ||
|
|
9034e3fcdf | ||
|
|
a9ee23413d | ||
|
|
9a7ef85aa4 | ||
|
|
1b5c060834 | ||
|
|
dfa96e66a4 | ||
|
|
00f4fb3326 | ||
|
|
3db4f6c93a | ||
|
|
0864ca849f | ||
|
|
faa9ada6b8 | ||
|
|
0e883d4a7a | ||
|
|
b2a435afdc | ||
|
|
5c17153df1 | ||
|
|
a967be9438 | ||
|
|
aaf62a4e60 | ||
|
|
91ed3baae7 | ||
|
|
2f32056fae | ||
|
|
af14cc9e78 | ||
|
|
a94c6c0e7f | ||
|
|
f819612144 | ||
|
|
d2e931f3e1 | ||
|
|
8becc9a9a7 | ||
|
|
a5d1853557 | ||
|
|
fb8c3e46e7 | ||
|
|
58b64294c8 | ||
|
|
d7857052c7 | ||
|
|
040d648e64 | ||
|
|
67b2b716e4 | ||
|
|
28c706c70a | ||
|
|
05fd5b354d | ||
|
|
f21601b0e8 | ||
|
|
08b8f9c35a | ||
|
|
5bc8ba3694 | ||
|
|
661b60fade | ||
|
|
780c5f1b83 | ||
|
|
41ae8242b6 | ||
|
|
c260263e4e | ||
|
|
80ec610485 | ||
|
|
3893cb4396 | ||
|
|
f6b86d2d33 | ||
|
|
0b8cd7e32f | ||
|
|
3681e86fad | ||
|
|
5db6a1d0c9 | ||
|
|
1c6f8e8327 | ||
|
|
c6f354ae6c | ||
|
|
e8772fbe2a | ||
|
|
22732e8cc5 | ||
|
|
a14b4c8039 | ||
|
|
84cc9489d4 | ||
|
|
2a4c8b9377 |
@@ -9,6 +9,10 @@
|
||||
[
|
||||
"module-alias",
|
||||
[
|
||||
{
|
||||
"expose": "root",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"expose": "components",
|
||||
"src": "src/core/components"
|
||||
@@ -17,6 +21,10 @@
|
||||
"expose": "core",
|
||||
"src": "src/core"
|
||||
},
|
||||
{
|
||||
"expose": "plugins",
|
||||
"src": "src/plugins"
|
||||
},
|
||||
{
|
||||
"expose": "img",
|
||||
"src": "src/img"
|
||||
|
||||
@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20
|
||||
|
||||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes
|
||||
------------------ | ------------ | -------------------------- | -----
|
||||
3.6.1 | 2017-12-01 | 2.0, 3.0 | [tag v3.6.1](https://github.com/swagger-api/swagger-ui/tree/v3.6.1)
|
||||
3.8.0 | 2017-12-15 | 2.0, 3.0 | [tag v3.8.0](https://github.com/swagger-api/swagger-ui/tree/v3.8.0)
|
||||
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21)
|
||||
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10)
|
||||
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5)
|
||||
|
||||
Vendored
+15
-15
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+3
-3
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -19,7 +19,8 @@ A plugin return value may contain any of these keys, where `myStateKey` is a nam
|
||||
},
|
||||
components: {},
|
||||
wrapComponents: {},
|
||||
fn: {}
|
||||
afterLoad: (system) => {}
|
||||
fn: {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -293,7 +294,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 +311,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 +325,7 @@ const MyNumberDisplayPlugin = function(system) {
|
||||
}
|
||||
}
|
||||
|
||||
// Here's a component wrapper defined as a function.
|
||||
const MyWrapComponentPlugin = function(system) {
|
||||
return {
|
||||
wrapComponents: {
|
||||
@@ -328,6 +333,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,6 +342,56 @@ 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} />
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### `afterLoad`
|
||||
|
||||
The `afterLoad` plugin method allows you to get a reference to the system after your plugin has been registered with the system.
|
||||
|
||||
This interface is used in the core code to attach methods that are driven by bound selectors or actions directly to the system.
|
||||
|
||||
```javascript
|
||||
const MyMethodProvidingPlugin = function() {
|
||||
return {
|
||||
afterLoad(system) {
|
||||
// at this point in time, your actions have been bound into the system
|
||||
// so you can do things with them
|
||||
system.myMethod = system.exampleActions.updateFavoriteColor
|
||||
},
|
||||
statePlugins: {
|
||||
example: {
|
||||
actions: {
|
||||
updateFavoriteColor: (str) => {
|
||||
return {
|
||||
type: "EXAMPLE_SET_FAV_COLOR",
|
||||
payload: str
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### fn
|
||||
|
||||
@@ -49,8 +49,9 @@ Parameter Name | Description
|
||||
--- | ---
|
||||
`deepLinking` | `Boolean=false`. If set to `true`, enables deep linking for tags and operations. See the [Deep Linking documentation](/docs/usage/deep-linking.md) for more information.
|
||||
`displayOperationId` | `Boolean=false`. Controls the display of operationId in operations list. The default is `false`.
|
||||
`defaultModelExpandDepth` | `Number=1`. The default expansion depth for models.
|
||||
`defaultModelRendering` | `String=["example"*, "model"]`. Controls how models are shown when the API is first rendered. (The user can always switch the rendering for a given model by clicking the 'Model' and 'Example Value' links.)
|
||||
`defaultModelsExpandDepth` | `Number=1`. The default expansion depth for models (set to -1 completely hide the models).
|
||||
`defaultModelExpandDepth` | `Number=1`. The default expansion depth for the model on the model-example section.
|
||||
`defaultModelRendering` | `String=["example"*, "model"]`. Controls how the model is shown when the API is first rendered. (The user can always switch the rendering for a given model by clicking the 'Model' and 'Example Value' links.)
|
||||
`displayRequestDuration` | `Boolean=false`. Controls the display of the request duration (in milliseconds) for Try-It-Out requests.
|
||||
`docExpansion` | `String=["list"*, "full", "none"]`. Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing).
|
||||
`filter` | `Boolean=false OR String`. If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be Boolean to enable or disable, or a string, in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag.
|
||||
|
||||
@@ -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 -->
|
||||
```
|
||||
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.6.1",
|
||||
"version": "3.8.0",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -81,13 +81,14 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.4.1",
|
||||
"swagger-client": "^3.4.2",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
"xml": "1.0.1",
|
||||
"xml-but-prettier": "^1.0.1",
|
||||
"yaml-js": "0.2.0"
|
||||
"yaml-js": "0.2.0",
|
||||
"zenscroll": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "7.1.1",
|
||||
|
||||
@@ -39,7 +39,7 @@ export default class ArrayModel extends Component {
|
||||
*/
|
||||
|
||||
return <span className="model">
|
||||
<ModelCollapse title={titleEl} collapsed={ depth > expandDepth } collapsedContent="[...]">
|
||||
<ModelCollapse title={titleEl} expanded={ depth <= expandDepth } collapsedContent="[...]">
|
||||
[
|
||||
{
|
||||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
|
||||
|
||||
@@ -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
|
||||
@@ -61,7 +61,18 @@ export default class BaseLayout extends React.Component {
|
||||
const isSpecEmpty = !specSelectors.specStr()
|
||||
|
||||
if(isSpecEmpty) {
|
||||
return <h4>No spec provided.</h4>
|
||||
let loadingMessage
|
||||
if(isLoading) {
|
||||
loadingMessage = <div className="loading"></div>
|
||||
} else {
|
||||
loadingMessage = <h4>No API definition provided.</h4>
|
||||
}
|
||||
|
||||
return <div className="swagger-ui">
|
||||
<div className="loading-container">
|
||||
{loadingMessage}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -4,31 +4,47 @@ import PropTypes from "prop-types"
|
||||
export default class ModelCollapse extends Component {
|
||||
static propTypes = {
|
||||
collapsedContent: PropTypes.any,
|
||||
collapsed: PropTypes.bool,
|
||||
expanded: PropTypes.bool,
|
||||
children: PropTypes.any,
|
||||
title: PropTypes.element
|
||||
title: PropTypes.element,
|
||||
modelName: PropTypes.string,
|
||||
onToggle: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
collapsedContent: "{...}",
|
||||
collapsed: true,
|
||||
expanded: false,
|
||||
title: null
|
||||
}
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
|
||||
let { collapsed, collapsedContent } = this.props
|
||||
let { expanded, collapsedContent } = this.props
|
||||
|
||||
this.state = {
|
||||
collapsed: collapsed !== undefined ? collapsed : ModelCollapse.defaultProps.collapsed,
|
||||
expanded : expanded,
|
||||
collapsedContent: collapsedContent || ModelCollapse.defaultProps.collapsedContent
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
|
||||
if(this.props.expanded!= nextProps.expanded){
|
||||
this.setState({expanded: nextProps.expanded})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
toggleCollapsed=()=>{
|
||||
|
||||
|
||||
if(this.props.onToggle){
|
||||
this.props.onToggle(this.props.modelName,!this.state.expanded)
|
||||
}
|
||||
|
||||
this.setState({
|
||||
collapsed: !this.state.collapsed
|
||||
expanded: !this.state.expanded
|
||||
})
|
||||
}
|
||||
|
||||
@@ -38,10 +54,10 @@ export default class ModelCollapse extends Component {
|
||||
<span>
|
||||
{ title && <span onClick={this.toggleCollapsed} style={{ "cursor": "pointer" }}>{title}</span> }
|
||||
<span onClick={ this.toggleCollapsed } style={{ "cursor": "pointer" }}>
|
||||
<span className={ "model-toggle" + ( this.state.collapsed ? " collapsed" : "" ) }></span>
|
||||
<span className={ "model-toggle" + ( this.state.expanded ? "" : " collapsed" ) }></span>
|
||||
</span>
|
||||
{ this.state.collapsed ? this.state.collapsedContent : this.props.children }
|
||||
{ this.state.expanded ? this.props.children :this.state.collapsedContent }
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,41 @@
|
||||
import React, { Component, } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
//import layoutActions from "actions/layout"
|
||||
|
||||
|
||||
export default class ModelWrapper extends Component {
|
||||
|
||||
|
||||
export default class ModelComponent extends Component {
|
||||
static propTypes = {
|
||||
schema: PropTypes.object.isRequired,
|
||||
name: PropTypes.string,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
expandDepth: PropTypes.number
|
||||
expandDepth: PropTypes.number,
|
||||
layoutActions: PropTypes.object,
|
||||
layoutSelectors: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
onToggle = (name,isShown) => {
|
||||
// If this prop is present, we'll have deepLinking for it
|
||||
if(this.props.layoutActions) {
|
||||
this.props.layoutActions.show(["models", name],isShown)
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
let { getComponent, getConfigs } = this.props
|
||||
const Model = getComponent("Model")
|
||||
|
||||
let expanded
|
||||
if(this.props.layoutSelectors) {
|
||||
// If this is prop is present, we'll have deepLinking for it
|
||||
expanded = this.props.layoutSelectors.isShown(["models",this.props.name])
|
||||
}
|
||||
|
||||
return <div className="model-box">
|
||||
<Model { ...this.props } getConfigs={ getConfigs } depth={ 1 } expandDepth={ this.props.expandDepth || 0 }/>
|
||||
<Model { ...this.props } getConfigs={ getConfigs } expanded={expanded} depth={ 1 } onToggle={ this.onToggle } expandDepth={ this.props.expandDepth || 0 }/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ export default class Models extends Component {
|
||||
render(){
|
||||
let { specSelectors, getComponent, layoutSelectors, layoutActions, getConfigs } = this.props
|
||||
let definitions = specSelectors.definitions()
|
||||
let { docExpansion, defaultModelExpandDepth } = getConfigs()
|
||||
let showModels = layoutSelectors.isShown("models", docExpansion === "full" || docExpansion === "list" )
|
||||
let { docExpansion, defaultModelsExpandDepth } = getConfigs()
|
||||
if (!definitions.size || defaultModelsExpandDepth < 0) return null
|
||||
|
||||
let showModels = layoutSelectors.isShown("models", defaultModelsExpandDepth > 0 && docExpansion !== "none")
|
||||
const specPathBase = specSelectors.isOAS3() ? ["components", "schemas"] : ["definitions"]
|
||||
|
||||
const ModelWrapper = getComponent("ModelWrapper")
|
||||
const Collapse = getComponent("Collapse")
|
||||
|
||||
if (!definitions.size) return null
|
||||
const Collapse = getComponent("Collapse")
|
||||
|
||||
return <section className={ showModels ? "models is-open" : "models"}>
|
||||
<h4 onClick={() => layoutActions.show("models", !showModels)}>
|
||||
@@ -32,14 +32,17 @@ export default class Models extends Component {
|
||||
<Collapse isOpened={showModels}>
|
||||
{
|
||||
definitions.entrySeq().map( ( [ name, model ])=>{
|
||||
return <div className="model-container" key={ `models-section-${name}` }>
|
||||
|
||||
return <div id={ `model-${name}` } className="model-container" key={ `models-section-${name}` }>
|
||||
<ModelWrapper name={ name }
|
||||
expandDepth={ defaultModelExpandDepth }
|
||||
expandDepth={ defaultModelsExpandDepth }
|
||||
schema={ model }
|
||||
specPath={[...specPathBase, name]}
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }/>
|
||||
specSelectors={ specSelectors }
|
||||
getConfigs = {getConfigs}
|
||||
layoutSelectors = {layoutSelectors}
|
||||
layoutActions = {layoutActions}/>
|
||||
</div>
|
||||
}).toArray()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ObjectModel extends Component {
|
||||
schema: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
expanded: PropTypes.bool,
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
name: PropTypes.string,
|
||||
isRef: PropTypes.bool,
|
||||
@@ -19,9 +21,8 @@ export default class ObjectModel extends Component {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { schema, name, isRef, getComponent, getConfigs, depth, specPath, expandDepth, ...otherProps } = this.props
|
||||
let { specSelectors } = otherProps
|
||||
|
||||
let { schema, name, isRef, getComponent, getConfigs, depth, onToggle, expanded, specPath, ...otherProps } = this.props
|
||||
let { specSelectors,expandDepth } = otherProps
|
||||
const { isOAS3 } = specSelectors
|
||||
|
||||
if(!schema) {
|
||||
@@ -61,7 +62,13 @@ export default class ObjectModel extends Component {
|
||||
</span>
|
||||
|
||||
return <span className="model">
|
||||
<ModelCollapse title={titleEl} collapsed={ depth > expandDepth } collapsedContent={ collapsedContent }>
|
||||
<ModelCollapse
|
||||
modelName={name}
|
||||
title={titleEl}
|
||||
onToggle = {onToggle}
|
||||
expanded={ expanded ? true : depth <= expandDepth }
|
||||
collapsedContent={ collapsedContent }>
|
||||
|
||||
<span className="brace-open object">{ braceOpen }</span>
|
||||
{
|
||||
!isRef ? null : <JumpToPathSection />
|
||||
|
||||
@@ -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)) {
|
||||
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
|
||||
} else if (/^audio\//i.test(contentType)) {
|
||||
|
||||
+18
-2
@@ -47,6 +47,7 @@ module.exports = function SwaggerUI(opts) {
|
||||
showMutatedRequest: true,
|
||||
defaultModelRendering: "example",
|
||||
defaultModelExpandDepth: 1,
|
||||
defaultModelsExpandDepth: 1,
|
||||
showExtensions: false,
|
||||
|
||||
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
|
||||
@@ -91,6 +92,20 @@ module.exports = function SwaggerUI(opts) {
|
||||
}, constructorConfig.initialState)
|
||||
}
|
||||
|
||||
if(constructorConfig.initialState) {
|
||||
// if the user sets a key as `undefined`, that signals to us that we
|
||||
// should delete the key entirely.
|
||||
// known usage: Swagger-Editor validate plugin tests
|
||||
for (var key in constructorConfig.initialState) {
|
||||
if(
|
||||
constructorConfig.initialState.hasOwnProperty(key)
|
||||
&& constructorConfig.initialState[key] === undefined
|
||||
) {
|
||||
delete storeConfigs.state[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let inlinePlugin = ()=> {
|
||||
return {
|
||||
fn: constructorConfig.fn,
|
||||
@@ -104,8 +119,6 @@ module.exports = function SwaggerUI(opts) {
|
||||
|
||||
var system = store.getSystem()
|
||||
|
||||
system.initOAuth = system.authActions.configureAuth
|
||||
|
||||
const downloadSpec = (fetchedConfig) => {
|
||||
if(typeof constructorConfig !== "object") {
|
||||
return system
|
||||
@@ -137,6 +150,9 @@ module.exports = function SwaggerUI(opts) {
|
||||
} else if(mergedConfig.dom_id) {
|
||||
let domNode = document.querySelector(mergedConfig.dom_id)
|
||||
system.render(domNode, "App")
|
||||
} else if(mergedConfig.dom_id === null || mergedConfig.domNode === null) {
|
||||
// do nothing
|
||||
// this is useful for testing that does not need to do any rendering
|
||||
} else {
|
||||
console.error("Skipped rendering: no `dom_id` or `domNode` was specified")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+33
-15
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ import * as specWrapActionReplacements from "./spec-wrap-actions"
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
afterLoad(system) {
|
||||
system.initOAuth = system.authActions.configureAuth
|
||||
},
|
||||
statePlugins: {
|
||||
auth: {
|
||||
reducers,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import YAML from "js-yaml"
|
||||
import yamlConfig from "../../../swagger-config.yaml"
|
||||
import yamlConfig from "root/swagger-config.yaml"
|
||||
import * as actions from "./actions"
|
||||
import * as selectors from "./selectors"
|
||||
import reducers from "./reducers"
|
||||
@@ -1,8 +1,7 @@
|
||||
import scrollTo from "scroll-to-element"
|
||||
import zenscroll from "zenscroll"
|
||||
import { escapeDeepLinkPath } from "core/utils"
|
||||
|
||||
const SCROLL_OFFSET = -5
|
||||
let hasHashBeenParsed = false
|
||||
let hasHashBeenParsed = false //TODO this forces code to only run once which may prevent scrolling if page not refreshed
|
||||
|
||||
|
||||
export const updateResolved = (ori, { layoutActions, getConfigs }) => (...args) => {
|
||||
@@ -12,7 +11,6 @@ export const updateResolved = (ori, { layoutActions, getConfigs }) => (...args)
|
||||
if(!isDeepLinkingEnabled || isDeepLinkingEnabled === "false") {
|
||||
return
|
||||
}
|
||||
|
||||
if(window.location.hash && !hasHashBeenParsed ) {
|
||||
let hash = window.location.hash.slice(1) // # is first character
|
||||
|
||||
@@ -30,21 +28,35 @@ export const updateResolved = (ori, { layoutActions, getConfigs }) => (...args)
|
||||
|
||||
let [tag, operationId] = hash.split("/")
|
||||
|
||||
let swaggerUI = document.querySelector(".swagger-ui")
|
||||
let myScroller = zenscroll.createScroller(swaggerUI)
|
||||
|
||||
let target
|
||||
|
||||
if(tag && operationId) {
|
||||
// Pre-expand and scroll to the operation
|
||||
layoutActions.show(["operations-tag", tag], true)
|
||||
layoutActions.show(["operations", tag, operationId], true)
|
||||
|
||||
scrollTo(`#operations-${escapeDeepLinkPath(tag)}-${escapeDeepLinkPath(operationId)}`, {
|
||||
offset: SCROLL_OFFSET
|
||||
})
|
||||
target = document
|
||||
.getElementById(`operations-${escapeDeepLinkPath(tag)}-${escapeDeepLinkPath(operationId)}`)
|
||||
} else if(tag) {
|
||||
// Pre-expand and scroll to the tag
|
||||
layoutActions.show(["operations-tag", tag], true)
|
||||
|
||||
scrollTo(`#operations-tag-${escapeDeepLinkPath(tag)}`, {
|
||||
offset: SCROLL_OFFSET
|
||||
})
|
||||
target = document.getElementById(`operations-tag-${escapeDeepLinkPath(tag)}`)
|
||||
}
|
||||
|
||||
|
||||
if(target) {
|
||||
myScroller.to(target)
|
||||
setTimeout(() => {
|
||||
// Backup functionality: if we're still at the top of the document,
|
||||
// scroll on the entire page (not within the Swagger-UI container)
|
||||
if(zenscroll.getY() === 0) {
|
||||
zenscroll.to(target)
|
||||
}
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,13 @@
|
||||
import reduce from "lodash/reduce"
|
||||
let request = require.context("./transformers/", true, /\.js$/)
|
||||
let errorTransformers = []
|
||||
import * as NotOfType from "./transformers/not-of-type"
|
||||
import * as ParameterOneOf from "./transformers/parameter-oneof"
|
||||
import * as StripInstance from "./transformers/strip-instance"
|
||||
|
||||
request.keys().forEach( function( key ){
|
||||
if( key === "./hook.js" ) {
|
||||
return
|
||||
}
|
||||
|
||||
if( !key.match(/js$/) ) {
|
||||
return
|
||||
}
|
||||
|
||||
if( key.slice(2).indexOf("/") > -1) {
|
||||
// skip files in subdirs
|
||||
return
|
||||
}
|
||||
|
||||
errorTransformers.push({
|
||||
name: toTitleCase(key).replace(".js", "").replace("./", ""),
|
||||
transform: request(key).transform
|
||||
})
|
||||
})
|
||||
const errorTransformers = [
|
||||
NotOfType,
|
||||
ParameterOneOf,
|
||||
StripInstance
|
||||
]
|
||||
|
||||
export default function transformErrors (errors, system) {
|
||||
let inputs = {
|
||||
@@ -47,10 +34,3 @@ export default function transformErrors (errors, system) {
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function toTitleCase(str) {
|
||||
return str
|
||||
.split("-")
|
||||
.map(substr => substr[0].toUpperCase() + substr.slice(1))
|
||||
.join("")
|
||||
}
|
||||
|
||||
@@ -37,17 +37,3 @@ export function changeMode(thing, mode="") {
|
||||
payload: {thing, mode}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// export function onlyShow(thing, shown=true) {
|
||||
// thing = normalizeArray(thing)
|
||||
// if(thing.length < 2)
|
||||
// throw new Error("layoutActions.onlyShow only works, when `thing` is an array with length > 1")
|
||||
// return {
|
||||
// type: ONLY_SHOW,
|
||||
// payload: {thing, shown}
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { fromJS } from "immutable"
|
||||
import {
|
||||
UPDATE_LAYOUT,
|
||||
UPDATE_FILTER,
|
||||
@@ -12,9 +13,14 @@ export default {
|
||||
[UPDATE_FILTER]: (state, action) => state.set("filter", action.payload),
|
||||
|
||||
[SHOW]: (state, action) => {
|
||||
let thing = action.payload.thing
|
||||
let shown = action.payload.shown
|
||||
return state.setIn(["shown"].concat(thing), shown)
|
||||
const isShown = action.payload.shown
|
||||
// This is one way to serialize an array, another (preferred) is to convert to json-pointer
|
||||
// TODO: use json-pointer serilization instead of fromJS(...), for performance
|
||||
const thingToShow = fromJS(action.payload.thing)
|
||||
// This is a map of paths to bools
|
||||
// eg: [one, two] => true
|
||||
// eg: [one] => false
|
||||
return state.update("shown", fromJS({}), a => a.set(thingToShow, isShown))
|
||||
},
|
||||
|
||||
[UPDATE_MODE]: (state, action) => {
|
||||
@@ -24,4 +30,3 @@ export default {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createSelector } from "reselect"
|
||||
import { normalizeArray } from "core/utils"
|
||||
import { fromJS } from "immutable"
|
||||
|
||||
const state = state => state
|
||||
|
||||
@@ -9,7 +10,7 @@ export const currentFilter = state => state.get("filter")
|
||||
|
||||
export const isShown = (state, thing, def) => {
|
||||
thing = normalizeArray(thing)
|
||||
return Boolean(state.getIn(["shown", ...thing], def))
|
||||
return state.get("shown", fromJS({})).get(fromJS(thing), def)
|
||||
}
|
||||
|
||||
export const whatMode = (state, thing, def="") => {
|
||||
@@ -21,4 +22,3 @@ export const showSummary = createSelector(
|
||||
state,
|
||||
state => !isShown(state, "editor")
|
||||
)
|
||||
|
||||
|
||||
@@ -72,10 +72,10 @@ export const servers = onlyOAS3(createSelector(
|
||||
|
||||
export const isOAS3 = (ori, system) => () => {
|
||||
const spec = system.getSystem().specSelectors.specJson()
|
||||
return isOAS3Helper(spec)
|
||||
return isOAS3Helper(Map.isMap(spec) ? spec : Map())
|
||||
}
|
||||
|
||||
export const isSwagger2 = (ori, system) => () => {
|
||||
const spec = system.getSystem().specSelectors.specJson()
|
||||
return isSwagger2Helper(spec)
|
||||
return isSwagger2Helper(Map.isMap(spec) ? spec : Map())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
return specActions.updateJsonSpec(json)
|
||||
if(json && typeof json === "object") {
|
||||
return specActions.updateJsonSpec(json)
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => {
|
||||
@@ -110,8 +105,7 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio
|
||||
errActions.clear({
|
||||
type: "thrown"
|
||||
})
|
||||
|
||||
if(errors.length > 0) {
|
||||
if(Array.isArray(errors) && errors.length > 0) {
|
||||
let preparedErrors = errors
|
||||
.map(err => {
|
||||
console.error(err)
|
||||
@@ -130,18 +124,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,
|
||||
|
||||
@@ -4,6 +4,10 @@ import { fromJS, Set, Map, OrderedMap, List } from "immutable"
|
||||
|
||||
const DEFAULT_TAG = "default"
|
||||
|
||||
const OPERATION_METHODS = [
|
||||
"get", "put", "post", "delete", "options", "head", "patch", "trace"
|
||||
]
|
||||
|
||||
const state = state => {
|
||||
return state || Map()
|
||||
}
|
||||
@@ -95,6 +99,9 @@ export const operations = createSelector(
|
||||
return {}
|
||||
}
|
||||
path.forEach((operation, method) => {
|
||||
if(OPERATION_METHODS.indexOf(method) < 0) {
|
||||
return
|
||||
}
|
||||
list = list.push(fromJS({
|
||||
path: pathName,
|
||||
method,
|
||||
@@ -256,10 +263,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 +280,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 +304,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 +323,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 +340,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
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { pascalCaseFilename } from "core/utils"
|
||||
|
||||
const request = require.context(".", true, /\.jsx?$/)
|
||||
|
||||
request.keys().forEach( function( key ){
|
||||
if( key === "./index.js" ) {
|
||||
return
|
||||
}
|
||||
|
||||
// if( key.slice(2).indexOf("/") > -1) {
|
||||
// // skip files in subdirs
|
||||
// return
|
||||
// }
|
||||
|
||||
let mod = request(key)
|
||||
module.exports[pascalCaseFilename(key)] = mod.default ? mod.default : mod
|
||||
})
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as components from "./components"
|
||||
|
||||
import SplitPaneMode from "./components/split-pane-mode"
|
||||
export default function SplitPaneModePlugin() {
|
||||
return {
|
||||
// statePlugins: {
|
||||
@@ -9,6 +8,8 @@ export default function SplitPaneModePlugin() {
|
||||
// }
|
||||
// },
|
||||
|
||||
components,
|
||||
components: {
|
||||
SplitPaneMode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import auth from "core/plugins/auth"
|
||||
import util from "core/plugins/util"
|
||||
import SplitPaneModePlugin from "core/plugins/split-pane-mode"
|
||||
import downloadUrlPlugin from "core/plugins/download-url"
|
||||
import configsPlugin from "plugins/configs"
|
||||
import configsPlugin from "core/plugins/configs"
|
||||
import deepLinkingPlugin from "core/plugins/deep-linking"
|
||||
|
||||
import OperationContainer from "core/containers/OperationContainer"
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,14 @@ export default class Store {
|
||||
if(rebuild) {
|
||||
this.buildSystem()
|
||||
}
|
||||
|
||||
if(Array.isArray(plugins)) {
|
||||
plugins.forEach(plugin => {
|
||||
if(plugin.afterLoad) {
|
||||
plugin.afterLoad(this.getSystem())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
buildSystem(buildReducer=true) {
|
||||
|
||||
+6
-16
@@ -1,17 +1,7 @@
|
||||
import { pascalCaseFilename } from "js/utils"
|
||||
import Configs from "./configs"
|
||||
import Topbar from "./topbar"
|
||||
|
||||
const request = require.context(".", true, /\.jsx?$/)
|
||||
|
||||
request.keys().forEach( function( key ){
|
||||
if( key === "./index.js" ) {
|
||||
return
|
||||
}
|
||||
|
||||
// if( key.slice(2).indexOf("/") > -1) {
|
||||
// // skip files in subdirs
|
||||
// return
|
||||
// }
|
||||
|
||||
let mod = request(key)
|
||||
module.exports[pascalCaseFilename(key)] = mod.default ? mod.default : mod
|
||||
})
|
||||
export default {
|
||||
Configs,
|
||||
Topbar
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import StandaloneLayout from "./layout"
|
||||
import TopbarPlugin from "plugins/topbar"
|
||||
import ConfigsPlugin from "plugins/configs"
|
||||
import ConfigsPlugin from "corePlugins/configs"
|
||||
|
||||
// the Standalone preset
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
|
||||
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
@@ -32,17 +34,21 @@ export default class StandaloneLayout extends React.Component {
|
||||
{ Topbar ? <Topbar /> : null }
|
||||
{ loadingStatus === "loading" &&
|
||||
<div className="info">
|
||||
<h4 className="title">Loading...</h4>
|
||||
<div className="loading-container">
|
||||
<div className="loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{ loadingStatus === "failed" &&
|
||||
<div className="info">
|
||||
<h4 className="title">Failed to load spec.</h4>
|
||||
<div className="loading-container">
|
||||
<h4 className="title">Failed to load API definition.</h4>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{ loadingStatus === "failedConfig" &&
|
||||
<div className="info" style={{ maxWidth: "880px", marginLeft: "auto", marginRight: "auto", textAlign: "center" }}>
|
||||
<h4 className="title">Failed to load config.</h4>
|
||||
<h4 className="title">Failed to load remote configuration.</h4>
|
||||
</div>
|
||||
}
|
||||
{ !loadingStatus || loadingStatus === "success" && <BaseLayout /> }
|
||||
|
||||
@@ -653,6 +653,11 @@
|
||||
.loading-container
|
||||
{
|
||||
padding: 40px 0 60px;
|
||||
margin-top: 1em;
|
||||
min-height: 1px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.loading
|
||||
{
|
||||
position: relative;
|
||||
|
||||
@@ -32,18 +32,18 @@ describe("<Models/>", function(){
|
||||
layoutActions: {},
|
||||
getConfigs: () => ({
|
||||
docExpansion: "list",
|
||||
defaultModelExpandDepth: 0
|
||||
defaultModelsExpandDepth: 0
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
it("passes defaultModelExpandDepth to ModelWrapper", function(){
|
||||
it("passes defaultModelsExpandDepth to ModelWrapper", function(){
|
||||
// When
|
||||
let wrapper = shallow(<Models {...props}/>)
|
||||
|
||||
// Then should render tabs
|
||||
expect(wrapper.find("ModelCollapse").length).toEqual(1)
|
||||
expect(wrapper.find("ModelComponent").length).toBeGreaterThan(0)
|
||||
expect(wrapper.find("ModelWrapper").length).toBeGreaterThan(0)
|
||||
wrapper.find("ModelComponent").forEach((modelWrapper) => {
|
||||
expect(modelWrapper.props().expandDepth).toBe(0)
|
||||
})
|
||||
|
||||
@@ -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}`} />
|
||||
}
|
||||
|
||||
|
||||
@@ -683,4 +683,31 @@ describe("bound system", function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe("afterLoad", function() {
|
||||
it("should call an plugin's `afterLoad` method after the plugin is loaded", function() {
|
||||
// Given
|
||||
const system = new System({
|
||||
plugins: [
|
||||
{
|
||||
afterLoad(system) {
|
||||
system.wow = system.dogeSelectors.wow
|
||||
},
|
||||
statePlugins: {
|
||||
doge: {
|
||||
selectors: {
|
||||
wow: () => (system) => {
|
||||
return "so selective"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// When
|
||||
var res = system.getSystem().wow()
|
||||
expect(res).toEqual("so selective")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user