Compare commits

...
29 Commits
Author SHA1 Message Date
kyle b749ea737d Merge pull request #4062 from shockey/master
v3.8.1
2017-12-30 01:39:49 -06:00
Kyle Shockey 248aeca0db v3.8.1 2017-12-30 01:33:23 -06:00
kyle adf03e49ae Merge pull request #4060 from shockey/master
Refactor `specPath` to Immutable.js data structures to avoid waste renders
2017-12-28 18:55:02 -06:00
Kyle Shockey 9bad35ed85 Refactor specPath to Im data structures to avoid waste renders 2017-12-28 18:04:12 -06:00
kyle ccc3b109a7 Merge pull request #4059 from shockey/master
Refactor `afterLoad` interface to expose raw plugin context
2017-12-28 16:49:58 -06:00
Kyle Shockey 56caeec8c8 Add documentation for rootInjects interface 2017-12-28 16:44:20 -06:00
Kyle Shockey 9d48c4751a Refactor afterLoad interface to expose raw plugin context 2017-12-28 16:26:18 -06:00
kyle 1646b270f8 Merge pull request #4052 from shockey/v/3.8.0
v3.8.0
2017-12-23 02:03:30 -06:00
Kyle Shockey 03f80dcc70 v3.8.0 2017-12-23 01:58:57 -06:00
kyle f982eb4894 Merge pull request #4049 from shockey/support/editor-validation-refactor
Supporting changes for Swagger-Editor semantic validation changes
2017-12-23 00:25:30 -06:00
kyle 10b4f5d8a7 Merge branch 'master' into support/editor-validation-refactor 2017-12-23 00:18:26 -06:00
kyle 9c2f9d2059 Merge pull request #4051 from shockey/bug/4040-default-tag
Don't parse non-method path keys as operations
2017-12-22 23:39:38 -06:00
kyle 7469705bef Merge branch 'master' into bug/4040-default-tag 2017-12-22 23:35:54 -06:00
Kyle Shockey 57db23ed1f Don't parse non-method path keys as operations 2017-12-22 23:30:38 -06:00
kyle 135fc34077 Merge pull request #4050 from shockey/bug/editor-1596
Prevent non-object values from being dispatched as new JSON content
2017-12-22 23:25:26 -06:00
Kyle Shockey ca0b248df2 Prevent non-object values from being dispatched as new JSON content 2017-12-22 23:19:10 -06:00
Kyle Shockey 27156bb79d Linter fixes 2017-12-22 22:58:37 -06:00
Kyle Shockey b03bf90664 Allow initialState key deletion 2017-12-22 22:41:53 -06:00
Kyle Shockey a9ebdb8a7a Add layout back to initalState 2017-12-22 22:29:55 -06:00
Kyle Shockey 68c689e491 Type-check errors before iterating over them 2017-12-20 13:59:22 -06:00
Kyle Shockey 150ebf3bc0 Add ability to explicitly skip rendering 2017-12-19 23:46:09 -06:00
Kyle Shockey e07b105b29 Remove layout from default initial state 2017-12-19 23:45:35 -06:00
Kyle Shockey 022b660b8c Merge branch 'master' into support/editor-validation-refactor 2017-12-19 23:29:59 -06:00
Kyle Shockey a2f8d289a0 Fix error transformer imports 2017-12-15 14:17:12 -08:00
Kyle Shockey 2dd25abbdd Move initOAuth attacher out of core constructor 2017-12-15 14:16:44 -08:00
Kyle Shockey c1ae4c133d Add afterLoad plugin interface 2017-12-14 21:01:37 -08:00
Kyle Shockey 85c83931c4 Move configs plugin to core 2017-12-14 20:17:31 -08:00
Kyle Shockey b5c713a72b Eliminate require.context usage 2017-12-14 20:17:31 -08:00
Kyle Shockey ca7f7ea78b Stop using require.context in error transformers 2017-12-14 20:17:31 -08:00
41 changed files with 330 additions and 137 deletions
+8
View File
@@ -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"
+1 -1
View File
@@ -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.7.0 | 2017-12-15 | 2.0, 3.0 | [tag v3.7.0](https://github.com/swagger-api/swagger-ui/tree/v3.7.0)
3.8.0 | 2017-12-15 | 2.0, 3.0 | [tag v3.8.1](https://github.com/swagger-api/swagger-ui/tree/v3.8.1)
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)
+15 -15
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+51 -1
View File
@@ -19,7 +19,9 @@ A plugin return value may contain any of these keys, where `myStateKey` is a nam
},
components: {},
wrapComponents: {},
fn: {}
rootInjects: {},
afterLoad: (system) => {},
fn: {},
}
```
@@ -363,7 +365,55 @@ const MyWrapComponentPlugin = function(system) {
}
```
##### `rootInjects`
The `rootInjects` interface allows you to inject values at the top level of the system.
This interface takes an object, which will be merged in with the top-level system object at runtime.
```js
const MyRootInjectsPlugin = function(system) {
return {
rootInjects: {
myConstant: 123,
myMethod: (...params) => console.log(...params)
}
}
}
```
##### `afterLoad`
The `afterLoad` plugin method allows you to get a reference to the system after your plugin has been registered.
This interface is used in the core code to attach methods that are driven by bound selectors or actions. You can also use it to execute logic that requires your plugin to already be ready, for example fetching initial data from a remote endpoint and passing it to an action your plugin creates.
The plugin context, which is bound to `this`, is undocumented, but below is an example of how to attach a bound action as a top-level method:
```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
this.rootInjects = this.rootInjects || {}
this.rootInjects.myMethod = system.exampleActions.updateFavoriteColor
},
statePlugins: {
example: {
actions: {
updateFavoriteColor: (str) => {
return {
type: "EXAMPLE_SET_FAV_COLOR",
payload: str
}
}
}
}
}
}
}
```
##### fn
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.7.0",
"version": "3.8.1",
"main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [
@@ -67,6 +67,7 @@
"react-height": "^2.0.0",
"react-hot-loader": "1.3.1",
"react-immutable-proptypes": "2.1.0",
"react-immutable-pure-component": "^1.1.1",
"react-markdown": "^2.5.0",
"react-motion": "^0.5.2",
"react-object-inspector": "0.2.1",
@@ -81,7 +82,7 @@
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
"swagger-client": "^3.4.2",
"swagger-client": "^3.4.4",
"url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1",
+13 -2
View File
@@ -1,5 +1,6 @@
import React, { Component } from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
const propStyle = { color: "#999", fontStyle: "italic" }
@@ -12,7 +13,7 @@ export default class ArrayModel extends Component {
name: PropTypes.string,
required: PropTypes.bool,
expandDepth: PropTypes.number,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
depth: PropTypes.number
}
@@ -48,7 +49,17 @@ export default class ArrayModel extends Component {
!description ? null :
<Markdown source={ description } />
}
<span><Model { ...this.props } getConfigs={ getConfigs } specPath={[...specPath, "items"]} name={null} schema={ items } required={ false } depth={ depth + 1 } /></span>
<span>
<Model
{ ...this.props }
getConfigs={ getConfigs }
specPath={specPath.push("items")}
name={null}
schema={ items }
required={ false }
depth={ depth + 1 }
/>
</span>
]
</ModelCollapse>
</span>
+2 -1
View File
@@ -1,5 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
export default class ModelExample extends React.Component {
static propTypes = {
@@ -9,7 +10,7 @@ export default class ModelExample extends React.Component {
example: PropTypes.any.isRequired,
isExecute: PropTypes.bool,
getConfigs: PropTypes.func.isRequired,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
}
constructor(props, context) {
+4 -3
View File
@@ -1,8 +1,9 @@
import React, { PureComponent } from "react"
import React from "react"
import ImmutablePureComponent from "react-immutable-pure-component"
import ImPropTypes from "react-immutable-proptypes"
import PropTypes from "prop-types"
export default class Model extends PureComponent {
export default class Model extends ImmutablePureComponent {
static propTypes = {
schema: ImPropTypes.orderedMap.isRequired,
getComponent: PropTypes.func.isRequired,
@@ -13,7 +14,7 @@ export default class Model extends PureComponent {
required: PropTypes.bool,
expandDepth: PropTypes.number,
depth: PropTypes.number,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
}
getModelName =( ref )=> {
+3 -2
View File
@@ -1,4 +1,5 @@
import React, { Component } from "react"
import Im from "immutable"
import PropTypes from "prop-types"
export default class Models extends Component {
@@ -20,7 +21,7 @@ export default class Models extends Component {
const specPathBase = specSelectors.isOAS3() ? ["components", "schemas"] : ["definitions"]
const ModelWrapper = getComponent("ModelWrapper")
const Collapse = getComponent("Collapse")
const Collapse = getComponent("Collapse")
return <section className={ showModels ? "models is-open" : "models"}>
<h4 onClick={() => layoutActions.show("models", !showModels)}>
@@ -37,7 +38,7 @@ export default class Models extends Component {
<ModelWrapper name={ name }
expandDepth={ defaultModelsExpandDepth }
schema={ model }
specPath={[...specPathBase, name]}
specPath={Im.List([...specPathBase, name])}
getComponent={ getComponent }
specSelectors={ specSelectors }
getConfigs = {getConfigs}
+7 -6
View File
@@ -1,6 +1,7 @@
import React, { Component, } from "react"
import PropTypes from "prop-types"
import { List } from "immutable"
import ImPropTypes from "react-immutable-proptypes"
const braceOpen = "{"
const braceClose = "}"
@@ -17,7 +18,7 @@ export default class ObjectModel extends Component {
isRef: PropTypes.bool,
expandDepth: PropTypes.number,
depth: PropTypes.number,
specPath: PropTypes.object.isRequired
specPath: ImPropTypes.list.isRequired
}
render(){
@@ -102,7 +103,7 @@ export default class ObjectModel extends Component {
<Model key={ `object-${name}-${key}_${value}` } { ...otherProps }
required={ isRequired }
getComponent={ getComponent }
specPath={[...specPath, "properties", key]}
specPath={specPath.push("properties", key)}
getConfigs={ getConfigs }
schema={ value }
depth={ depth + 1 } />
@@ -141,7 +142,7 @@ export default class ObjectModel extends Component {
<td>
<Model { ...otherProps } required={ false }
getComponent={ getComponent }
specPath={[...specPath, "additionalProperties"]}
specPath={specPath.push("additionalProperties")}
getConfigs={ getConfigs }
schema={ additionalProperties }
depth={ depth + 1 } />
@@ -156,7 +157,7 @@ export default class ObjectModel extends Component {
{anyOf.map((schema, k) => {
return <div key={k}><Model { ...otherProps } required={ false }
getComponent={ getComponent }
specPath={[...specPath, "anyOf", k]}
specPath={specPath.push("anyOf", k)}
getConfigs={ getConfigs }
schema={ schema }
depth={ depth + 1 } /></div>
@@ -172,7 +173,7 @@ export default class ObjectModel extends Component {
{oneOf.map((schema, k) => {
return <div key={k}><Model { ...otherProps } required={ false }
getComponent={ getComponent }
specPath={[...specPath, "oneOf", k]}
specPath={specPath.push("oneOf", k)}
getConfigs={ getConfigs }
schema={ schema }
depth={ depth + 1 } /></div>
@@ -189,7 +190,7 @@ export default class ObjectModel extends Component {
<Model { ...otherProps }
required={ false }
getComponent={ getComponent }
specPath={[...specPath, "not"]}
specPath={specPath.push("not")}
getConfigs={ getConfigs }
schema={ not }
depth={ depth + 1 } />
+6 -5
View File
@@ -2,11 +2,12 @@ import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import { getList } from "core/utils"
import { getExtensions, sanitizeUrl } from "core/utils"
import { Iterable } from "immutable"
import { Iterable, List } from "immutable"
import ImPropTypes from "react-immutable-proptypes"
export default class Operation extends PureComponent {
static propTypes = {
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
operation: PropTypes.instanceOf(Iterable).isRequired,
response: PropTypes.instanceOf(Iterable),
request: PropTypes.instanceOf(Iterable),
@@ -33,7 +34,7 @@ export default class Operation extends PureComponent {
operation: null,
response: null,
request: null,
specPath: []
specPath: List()
}
render() {
@@ -174,7 +175,7 @@ export default class Operation extends PureComponent {
<Parameters
parameters={parameters}
specPath={[...specPath, "parameters"]}
specPath={specPath.push("parameters")}
operation={operation}
onChangeKey={onChangeKey}
onTryoutClick = { onTryoutClick }
@@ -248,7 +249,7 @@ export default class Operation extends PureComponent {
specActions={ specActions }
produces={ produces }
producesValue={ operation.get("produces_value") }
specPath={[...specPath, "responses"]}
specPath={specPath.push("responses")}
path={ path }
method={ method }
displayRequestDuration={ displayRequestDuration }
+2 -1
View File
@@ -1,5 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import Im from "immutable"
import { createDeepLinkPath, sanitizeUrl } from "core/utils"
const SWAGGER2_OPERATION_METHODS = [
@@ -119,7 +120,7 @@ export default class Operations extends React.Component {
operations.map( op => {
const path = op.get("path")
const method = op.get("method")
const specPath = ["paths", path, method]
const specPath = Im.List(["paths", path, method])
// FIXME: (someday) this logic should probably be in a selector,
+3 -2
View File
@@ -1,6 +1,7 @@
import React, { Component } from "react"
import { Map } from "immutable"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import win from "core/window"
import { getExtensions } from "core/utils"
@@ -15,7 +16,7 @@ export default class ParameterRow extends Component {
specSelectors: PropTypes.object.isRequired,
pathMethod: PropTypes.array.isRequired,
getConfigs: PropTypes.func.isRequired,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired
}
constructor(props, context) {
@@ -139,7 +140,7 @@ export default class ParameterRow extends Component {
{
bodyParam && schema ? <ModelExample getComponent={ getComponent }
specPath={[...specPath, "schema"]}
specPath={specPath.push("schema")}
getConfigs={ getConfigs }
isExecute={ isExecute }
specSelectors={ specSelectors }
+2 -2
View File
@@ -21,7 +21,7 @@ export default class Parameters extends Component {
onChangeKey: PropTypes.array,
pathMethod: PropTypes.array.isRequired,
getConfigs: PropTypes.func.isRequired,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
}
@@ -98,7 +98,7 @@ export default class Parameters extends Component {
eachMap(parameters, (parameter, i) => (
<ParameterRow
fn={ fn }
specPath={[...specPath, i]}
specPath={specPath.push(i.toString())}
getComponent={ getComponent }
getConfigs={ getConfigs }
param={ parameter }
+5 -4
View File
@@ -1,7 +1,8 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import cx from "classnames"
import { fromJS, Seq, Iterable } from "immutable"
import { fromJS, Seq, Iterable, List } from "immutable"
import { getSampleSchema, fromJSOrdered } from "core/utils"
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
@@ -47,7 +48,7 @@ export default class Response extends React.Component {
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
fn: PropTypes.object.isRequired,
contentType: PropTypes.string,
controlsAcceptHeader: PropTypes.bool,
@@ -99,7 +100,7 @@ export default class Response extends React.Component {
var schema, specPathWithPossibleSchema
if(isOAS3()) {
const schemaPath = ["content", this.state.responseContentType, "schema"]
const schemaPath = List(["content", this.state.responseContentType, "schema"])
const oas3SchemaForContentType = response.getIn(schemaPath)
sampleResponse = oas3SchemaForContentType ? getSampleSchema(oas3SchemaForContentType.toJS(), this.state.responseContentType, {
includeReadOnly: true
@@ -108,7 +109,7 @@ export default class Response extends React.Component {
specPathWithPossibleSchema = oas3SchemaForContentType ? schemaPath : specPath
} else {
schema = inferSchema(response.toJS()) // TODO: don't convert back and forth. Lets just stick with immutable for inferSchema
specPathWithPossibleSchema = response.has("schema") ? [...specPath, "schema"] : specPath
specPathWithPossibleSchema = response.has("schema") ? specPath.push("schema") : specPath
sampleResponse = schema ? getSampleSchema(schema, contentType, {
includeReadOnly: true,
includeWriteOnly: true // writeOnly has no filtering effect in swagger 2.0
+4 -3
View File
@@ -1,6 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import { fromJS, Iterable } from "immutable"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils"
export default class Responses extends React.Component {
@@ -17,7 +18,7 @@ export default class Responses extends React.Component {
specSelectors: PropTypes.object.isRequired,
specActions: PropTypes.object.isRequired,
oas3Actions: PropTypes.object.isRequired,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
fn: PropTypes.object.isRequired
}
@@ -120,7 +121,7 @@ export default class Responses extends React.Component {
let className = tryItOutResponse && tryItOutResponse.get("status") == code ? "response_current" : ""
return (
<Response key={ code }
specPath={[...specPath, code]}
specPath={specPath.push(code)}
isDefault={defaultCode === code}
fn={fn}
className={ className }
+2 -2
View File
@@ -1,5 +1,6 @@
import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { helpers } from "swagger-client"
import { Iterable, fromJS } from "immutable"
@@ -31,8 +32,7 @@ export default class OperationContainer extends PureComponent {
request: PropTypes.instanceOf(Iterable),
security: PropTypes.instanceOf(Iterable),
isDeepLinkingEnabled: PropTypes.bool.isRequired,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
getComponent: PropTypes.func.isRequired,
authActions: PropTypes.object,
oas3Actions: PropTypes.object,
+17 -2
View File
@@ -92,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,
@@ -105,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
@@ -138,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")
}
+4
View File
@@ -5,6 +5,10 @@ import * as specWrapActionReplacements from "./spec-wrap-actions"
export default function() {
return {
afterLoad(system) {
this.rootInjects = this.rootInjects || {}
this.rootInjects.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,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("")
}
@@ -38,7 +38,7 @@ const RequestBody = ({
expandDepth={1}
isExecute={isExecute}
schema={mediaTypeValue.get("schema")}
specPath={[...specPath, "content", contentType]}
specPath={specPath.push("content", contentType)}
example={<RequestBodyEditor
requestBody={requestBody}
onChange={onChange}
@@ -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())
}
@@ -29,7 +29,7 @@ class Parameters extends Component {
fn: PropTypes.object.isRequired,
tryItOutEnabled: PropTypes.bool,
allowTryItOut: PropTypes.bool,
specPath: PropTypes.array.isRequired,
specPath: ImPropTypes.list.isRequired,
onTryoutClick: PropTypes.func,
onCancelClick: PropTypes.func,
onChangeKey: PropTypes.array,
@@ -107,7 +107,7 @@ class Parameters extends Component {
const { isOAS3 } = specSelectors
const requestBody = operation.get("requestBody")
const requestBodySpecPath = [...specPath.slice(0, -1), "requestBody"] // remove the "parameters" part
const requestBodySpecPath = specPath.slice(0, -1).push("requestBody") // remove the "parameters" part
return (
<div className="opblock-section">
@@ -143,7 +143,7 @@ class Parameters extends Component {
eachMap(parameters, (parameter, i) => (
<ParameterRow fn={ fn }
getComponent={ getComponent }
specPath={[...specPath, i]}
specPath={specPath.push(i)}
getConfigs={ getConfigs }
param={ parameter }
key={ parameter.get( "name" ) }
+2 -3
View File
@@ -68,7 +68,7 @@ export const parseToJson = (str) => ({specActions, specSelectors, errActions}) =
line: e.mark && e.mark.line ? e.mark.line + 1 : undefined
})
}
if(json) {
if(json && typeof json === "object") {
return specActions.updateJsonSpec(json)
}
return {}
@@ -105,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)
+7
View File
@@ -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,
@@ -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
})
+4 -3
View File
@@ -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
}
}
}
+1 -1
View File
@@ -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"
+25
View File
@@ -68,6 +68,12 @@ export default class Store {
if(rebuild) {
this.buildSystem()
}
const needAnotherRebuild = callAfterLoad.call(this.system, plugins, this.getSystem())
if(needAnotherRebuild) {
this.buildSystem()
}
}
buildSystem(buildReducer=true) {
@@ -320,6 +326,25 @@ function combinePlugins(plugins, toolbox) {
return {}
}
function callAfterLoad(plugins, system, { hasLoaded } = {}) {
let calledSomething = hasLoaded
if(isObject(plugins) && !isArray(plugins)) {
if(typeof plugins.afterLoad === "function") {
calledSomething = true
plugins.afterLoad.call(this, system)
}
}
if(isFunc(plugins))
return callAfterLoad.call(this, plugins(system), system, { hasLoaded: calledSomething })
if(isArray(plugins)) {
return plugins.map(plugin => callAfterLoad.call(this, plugin, system, { hasLoaded: calledSomething }))
}
return calledSomething
}
// Wraps deepExtend, to account for certain fields, being wrappers.
// Ie: we need to convert some fields into arrays, and append to them.
// Rather than overwrite
+6 -16
View File
@@ -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 -1
View File
@@ -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
+2 -2
View File
@@ -1,7 +1,7 @@
import React from "react"
import expect from "expect"
import { shallow } from "enzyme"
import { fromJS } from "immutable"
import { fromJS, List } from "immutable"
import ObjectModel from "components/object-model"
import ModelExample from "components/model-example"
import Immutable from "immutable"
@@ -25,7 +25,7 @@ describe("<ObjectModel />", function() {
}
},
isRef : false,
specPath: [],
specPath: List(),
schema: Immutable.fromJS(
{
"properties": {
+110
View File
@@ -683,4 +683,114 @@ describe("bound system", function(){
})
})
describe("afterLoad", function() {
it("should call a plugin's `afterLoad` method after the plugin is loaded", function() {
// Given
const system = new System({
plugins: [
{
afterLoad(system) {
this.rootInjects.wow = system.dogeSelectors.wow
},
statePlugins: {
doge: {
selectors: {
wow: () => (system) => {
return "so selective"
}
}
}
}
}
]
})
// When
var res = system.getSystem().wow()
expect(res).toEqual("so selective")
})
it("should call a preset plugin's `afterLoad` method after the plugin is loaded", function() {
// Given
const MyPlugin = {
afterLoad(system) {
this.rootInjects.wow = system.dogeSelectors.wow
},
statePlugins: {
doge: {
selectors: {
wow: () => (system) => {
return "so selective"
}
}
}
}
}
const system = new System({
plugins: [
[MyPlugin]
]
})
// When
var res = system.getSystem().wow()
expect(res).toEqual("so selective")
})
it("should call a function preset plugin's `afterLoad` method after the plugin is loaded", function() {
// Given
const MyPlugin = {
afterLoad(system) {
this.rootInjects.wow = system.dogeSelectors.wow
},
statePlugins: {
doge: {
selectors: {
wow: () => (system) => {
return "so selective"
}
}
}
}
}
const system = new System({
plugins: [
() => {
return [MyPlugin]
}
]
})
// When
var res = system.getSystem().wow()
expect(res).toEqual("so selective")
})
it("should call a registered plugin's `afterLoad` method after the plugin is loaded", function() {
// Given
const MyPlugin = {
afterLoad(system) {
this.rootInjects.wow = system.dogeSelectors.wow
},
statePlugins: {
doge: {
selectors: {
wow: () => (system) => {
return "so selective"
}
}
}
}
}
const system = new System({
plugins: []
})
system.register([MyPlugin])
// When
var res = system.getSystem().wow()
expect(res).toEqual("so selective")
})
})
})