Merge branch 'master' into clickfix
This commit is contained in:
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
37
.eslintrc
Normal file
37
.eslintrc
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": true,
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"extends": ["eslint:recommended", "plugin:react/recommended"],
|
||||||
|
|
||||||
|
"plugins": [
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"semi": [2, "never"],
|
||||||
|
"strict": 0,
|
||||||
|
"quotes": 2,
|
||||||
|
"no-unused-vars": 2,
|
||||||
|
"no-multi-spaces": 1,
|
||||||
|
"camelcase": 1,
|
||||||
|
"no-use-before-define": [2,"nofunc"],
|
||||||
|
"no-underscore-dangle": 0,
|
||||||
|
"no-unused-expressions": 1,
|
||||||
|
"comma-dangle": 0,
|
||||||
|
"no-console": ["error", { allow: ["warn", "error"] }],
|
||||||
|
"react/jsx-no-bind": 1,
|
||||||
|
"react/display-name": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
3
.github/issue_template.md
vendored
Normal file
3
.github/issue_template.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
When reporting an issue, please provide the following details:
|
||||||
|
- swagger-ui version
|
||||||
|
- a swagger file reproducing the issue
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,4 +2,5 @@ node_modules
|
|||||||
.idea
|
.idea
|
||||||
.deps_check
|
.deps_check
|
||||||
.DS_Store
|
.DS_Store
|
||||||
npm-debug.log
|
npm-debug.log*
|
||||||
|
.eslintcache
|
||||||
|
|||||||
36
.travis.yml
36
.travis.yml
@@ -1,13 +1,18 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '6.9'
|
- '6.9'
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||||
before_deploy: "npm run build-core"
|
before_deploy:
|
||||||
|
- npm run build
|
||||||
|
env:
|
||||||
|
- DOCKER_IMAGE_NAME=swaggerapi/swagger-ui
|
||||||
deploy:
|
deploy:
|
||||||
provider: npm
|
- provider: npm
|
||||||
email: apiteam@swagger.io
|
email: apiteam@swagger.io
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
api_key:
|
api_key:
|
||||||
@@ -16,3 +21,30 @@ deploy:
|
|||||||
tags: true
|
tags: true
|
||||||
repo: swagger-api/swagger-ui
|
repo: swagger-api/swagger-ui
|
||||||
node: '6.9'
|
node: '6.9'
|
||||||
|
- provider: script
|
||||||
|
skip_cleanup: true
|
||||||
|
script: swagger-ui-dist-package/deploy.sh
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
repo: swagger-api/swagger-ui
|
||||||
|
node: '6.9'
|
||||||
|
after_success:
|
||||||
|
- if [ $DOCKER_HUB_USERNAME ]; then
|
||||||
|
docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
|
||||||
|
|
||||||
|
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||||
|
DOCKER_IMAGE_TAG=$TRAVIS_TAG;
|
||||||
|
else
|
||||||
|
DOCKER_IMAGE_TAG=unstable;
|
||||||
|
fi;
|
||||||
|
docker build -t $DOCKER_IMAGE_NAME .;
|
||||||
|
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||||
|
docker tag $DOCKER_IMAGE_NAME $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||||
|
docker push $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||||
|
docker tag $DOCKER_IMAGE_NAME $DOCKER_IMAGE_NAME:latest;
|
||||||
|
docker push $DOCKER_IMAGE_NAME:latest;
|
||||||
|
else
|
||||||
|
docker tag $DOCKER_IMAGE_NAME $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||||
|
docker push $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|||||||
21
Dockerfile
21
Dockerfile
@@ -2,18 +2,27 @@ FROM alpine:3.4
|
|||||||
|
|
||||||
MAINTAINER fehguy
|
MAINTAINER fehguy
|
||||||
|
|
||||||
|
ENV VERSION "v2.2.10"
|
||||||
|
ENV FOLDER "swagger-ui-2.2.10"
|
||||||
|
ENV API_URL "http://petstore.swagger.io/v2/swagger.json"
|
||||||
|
ENV API_KEY "**None**"
|
||||||
|
ENV OAUTH_CLIENT_ID "**None**"
|
||||||
|
ENV OAUTH_CLIENT_SECRET "**None**"
|
||||||
|
ENV OAUTH_REALM "**None**"
|
||||||
|
ENV OAUTH_APP_NAME "**None**"
|
||||||
|
ENV OAUTH_ADDITIONAL_PARAMS "**None**"
|
||||||
|
ENV SWAGGER_JSON "/app/swagger.json"
|
||||||
|
ENV PORT 80
|
||||||
|
|
||||||
RUN apk add --update nginx
|
RUN apk add --update nginx
|
||||||
RUN mkdir -p /run/nginx
|
RUN mkdir -p /run/nginx
|
||||||
|
|
||||||
COPY nginx.conf /etc/nginx/
|
COPY nginx.conf /etc/nginx/
|
||||||
|
|
||||||
# copy swagger files to the `/js` folder
|
# copy swagger files to the `/js` folder
|
||||||
ADD ./dist/ /usr/share/nginx/html/js
|
ADD ./dist/* /usr/share/nginx/html/
|
||||||
ADD ./public/index.html /usr/share/nginx/html
|
ADD ./docker-run.sh /usr/share/nginx/
|
||||||
|
|
||||||
# change the folder structure
|
|
||||||
RUN sed -i 's/\.\.\/dist/js/g' /usr/share/nginx/html/index.html
|
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
CMD exec nginx -g 'daemon off;'
|
CMD ["sh", "/usr/share/nginx/docker-run.sh"]
|
||||||
|
|||||||
106
README.md
106
README.md
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
## New!
|
## New!
|
||||||
|
|
||||||
This is the new version of swagger-ui, 3.x.
|
**This is the new version of swagger-ui, 3.x. Want to learn more? Check out our [FAQ](http://swagger.io/new-ui-faq/).**
|
||||||
|
|
||||||
|
As a brand new version, written from the ground up, there are some known issues and unimplemented features. Check out the [Known Issues](#known-issues) section for more details.
|
||||||
|
|
||||||
For the older version of swagger-ui, refer to the [*2.x branch*](https://github.com/swagger-api/swagger-ui/tree/2.x).
|
For the older version of swagger-ui, refer to the [*2.x branch*](https://github.com/swagger-api/swagger-ui/tree/2.x).
|
||||||
|
|
||||||
@@ -13,7 +15,7 @@ The OpenAPI Specification has undergone 4 revisions since initial creation in 20
|
|||||||
|
|
||||||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | Status
|
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | Status
|
||||||
------------------ | ------------ | -------------------------- | ----- | ------
|
------------------ | ------------ | -------------------------- | ----- | ------
|
||||||
3.0.1 | 2017-03-18 | 2.0 | [tag v3.0.1](https://github.com/swagger-api/swagger-ui/tree/v3.0.1) |
|
3.0.11 | 2017-03-19 | 2.0 | [tag v3.0.11](https://github.com/swagger-api/swagger-ui/tree/v3.0.11) |
|
||||||
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.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) |
|
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) |
|
||||||
2.0.24 | 2014-09-12 | 1.1, 1.2 | [tag v2.0.24](https://github.com/swagger-api/swagger-ui/tree/v2.0.24) |
|
2.0.24 | 2014-09-12 | 1.1, 1.2 | [tag v2.0.24](https://github.com/swagger-api/swagger-ui/tree/v2.0.24) |
|
||||||
@@ -37,14 +39,110 @@ Will start nginx with swagger-ui on port 80.
|
|||||||
- Node 6.x
|
- Node 6.x
|
||||||
- NPM 3.x
|
- NPM 3.x
|
||||||
|
|
||||||
If you just want to see your specs, open `public/index.html` in your browser directly from your filesystem.
|
If you just want to see your specs, open `dist/index.html` in your browser directly from your filesystem.
|
||||||
|
|
||||||
If you'd like to make modifications to the codebase, run the dev server with: `npm run dev`.
|
If you'd like to make modifications to the codebase, run the dev server with: `npm run dev`.
|
||||||
|
|
||||||
|
|
||||||
##### Browser support
|
##### Browser support
|
||||||
Swagger UI works in the latest versions of Chrome, Safari, Firefox, Edge and IE11.
|
Swagger UI works in the latest versions of Chrome, Safari, Firefox, Edge and IE11.
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
|
||||||
|
To help with the migration, here are the currently known issues with 3.X. This list will update regularly, and will not include features that were not implemented in previous versions.
|
||||||
|
|
||||||
|
- Only part of the [parameters](#parameters) previously supported are available.
|
||||||
|
- The JSON Form Editor is not implemented.
|
||||||
|
- Shebang URL support for operations is missing.
|
||||||
|
- Support for `collectionFormat` is partial.
|
||||||
|
- l10n (translations) is not implemented.
|
||||||
|
- Relative path support for external files is not implemented.
|
||||||
|
|
||||||
|
### SwaggerUIBundle
|
||||||
|
To use swagger-ui's bundles, you should take a look at the [source of swagger-ui html page](https://github.com/swagger-api/swagger-ui/blob/master/dist/index.html) and customize it. This basically requires you to instantiate a SwaggerUi object as below:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const ui = SwaggerUIBundle({
|
||||||
|
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### OAuth2 configuration
|
||||||
|
You can configure OAuth2 authorization by calling `initOAuth` method with passed configs under the instance of `SwaggerUIBundle`
|
||||||
|
default `client_id` and `client_secret`, `realm`, an application name `appName`, `scopeSeparator`, `additionalQueryStringParams`.
|
||||||
|
|
||||||
|
Config Name | Description
|
||||||
|
--- | ---
|
||||||
|
client_id | Default clientId. MUST be a string
|
||||||
|
client_secret | Default clientSecret. MUST be a string
|
||||||
|
realm | realm query parameter (for oauth1) added to `authorizationUrl` and `tokenUrl` . MUST be a string
|
||||||
|
appName | application name, displayed in authorization popup. MUST be a string
|
||||||
|
scopeSeparator | scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string
|
||||||
|
additionalQueryStringParams | Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object
|
||||||
|
|
||||||
|
```
|
||||||
|
const ui = SwaggerUIBundle({...})
|
||||||
|
|
||||||
|
// Method can be called in any place after calling constructor SwaggerUIBundle
|
||||||
|
ui.initOAuth({
|
||||||
|
clientId: "your-client-id",
|
||||||
|
clientSecret: "your-client-secret-if-required",
|
||||||
|
realm: "your-realms",
|
||||||
|
appName: "your-app-name",
|
||||||
|
scopeSeparator: " ",
|
||||||
|
additionalQueryStringParams: {test: "hello"}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist` package](https://www.npmjs.com/package/swagger-ui-dist).
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
Parameter Name | Description
|
||||||
|
--- | ---
|
||||||
|
url | The url pointing to API definition (normally `swagger.json` or `swagger.yaml`).
|
||||||
|
spec | A JSON object describing the OpenAPI Specification. When used, the `url` parameter will not be parsed. This is useful for testing manually-generated specifications without hosting them.
|
||||||
|
validatorUrl | By default, Swagger-UI attempts to validate specs against swagger.io's online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators ([Validator Badge](https://github.com/swagger-api/validator-badge)). Setting it to `null` will disable validation.
|
||||||
|
dom_id | The id of a dom element inside which SwaggerUi will put the user interface for swagger.
|
||||||
|
oauth2RedirectUrl | OAuth redirect URL
|
||||||
|
operationsSorter | Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.
|
||||||
|
configUrl | Configs URL
|
||||||
|
|
||||||
|
### Plugins
|
||||||
|
|
||||||
|
#### Topbar plugin
|
||||||
|
Topbar plugin enables top bar with input for spec path and explore button. By default the plugin is enabled, and to disable it you need to remove Topbar plugin from presets in `src/standalone/index.js`:
|
||||||
|
|
||||||
|
```
|
||||||
|
let preset = [
|
||||||
|
// TopbarPlugin,
|
||||||
|
ConfigsPlugin,
|
||||||
|
() => {
|
||||||
|
return {
|
||||||
|
components: { StandaloneLayout }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Configs plugin
|
||||||
|
Configs plugin allows to fetch external configs instead of passing them to `SwaggerUIBundle`. Fetched configs support two formats: JSON or yaml. The plugin is enabled by default.
|
||||||
|
There are three options of passing config:
|
||||||
|
- add a query parameter `config` with URL to a server where the configs are hosted. For ex. http://petstore.swagger.io/?configs=http://localhost:3001/config.yaml
|
||||||
|
- add a config `configUrl` with URL to SwaggerUIBundle
|
||||||
|
- change default configs in `swagger-config.yaml` *Note: after changing, the project must be re-built*
|
||||||
|
|
||||||
|
These options can be used altogether, the order of inheritance is following (from the lowest priority to the highest):
|
||||||
|
`swagger-config.yaml` -> config passed to `SwaggerUIBundle` -> config fetched from `configUrl` passed to `SwaggerUIBundle` -> config fetched from URL passed as a query parameter `config`
|
||||||
|
|
||||||
## CORS Support
|
## CORS Support
|
||||||
|
|
||||||
CORS is a technique to prevent websites from doing bad things with your personal data. Most browsers + JavaScript toolkits not only support CORS but enforce it, which has implications for your API server which supports Swagger.
|
CORS is a technique to prevent websites from doing bad things with your personal data. Most browsers + JavaScript toolkits not only support CORS but enforce it, which has implications for your API server which supports Swagger.
|
||||||
|
|||||||
40
composer.json
Normal file
40
composer.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "swagger-api/swagger-ui",
|
||||||
|
"description": " Swagger UI is a collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.",
|
||||||
|
"keywords": [
|
||||||
|
"Swagger",
|
||||||
|
"OpenAPI",
|
||||||
|
"specification",
|
||||||
|
"documentation",
|
||||||
|
"API",
|
||||||
|
"UI"
|
||||||
|
],
|
||||||
|
"homepage": "http://swagger.io",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Anna Bodnia",
|
||||||
|
"email": "anna.bodnia@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Buu Nguyen",
|
||||||
|
"email": "buunguyen@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Josh Ponelat",
|
||||||
|
"email": "jponelat@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kyle Shockey",
|
||||||
|
"email": "kyleshockey1@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Robert Barnwell",
|
||||||
|
"email": "robert@robertismy.name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sahar Jafari",
|
||||||
|
"email": "shr.jafari@gmail.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
|
<!-- HTML for dev server -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Swagger UI</title>
|
<title>Swagger UI</title>
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||||
<link rel="stylesheet" type="text/css" href="../dist/swagger-ui.css" >
|
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||||
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
|
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||||
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
|
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||||
<style>
|
<style>
|
||||||
html
|
html
|
||||||
{
|
{
|
||||||
@@ -66,18 +67,19 @@
|
|||||||
|
|
||||||
<div id="swagger-ui"></div>
|
<div id="swagger-ui"></div>
|
||||||
|
|
||||||
<script src="../dist/swagger-ui-bundle.js"> </script>
|
<script src="./swagger-ui-bundle.js"> </script>
|
||||||
<script src="../dist/swagger-ui-standalone-preset.js"> </script>
|
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||||
<script>
|
<script>
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
|
window["SwaggerUIBundle"] = window["swagger-ui-bundle"]
|
||||||
|
window["SwaggerUIStandalonePreset"] = window["swagger-ui-standalone-preset"]
|
||||||
// Build a system
|
// Build a system
|
||||||
const ui = SwaggerUIBundle({
|
const ui = SwaggerUIBundle({
|
||||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
url: "http://petstore.swagger.io/v2/swagger.json",
|
||||||
dom_id: '#swagger-ui',
|
dom_id: '#swagger-ui',
|
||||||
presets: [
|
presets: [
|
||||||
SwaggerUIBundle.presets.apis,
|
SwaggerUIBundle.presets.apis,
|
||||||
// yay ES6 modules ↘
|
SwaggerUIStandalonePreset
|
||||||
Array.isArray(SwaggerUIStandalonePreset) ? SwaggerUIStandalonePreset : SwaggerUIStandalonePreset.default
|
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
@@ -86,6 +88,15 @@ window.onload = function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
window.ui = ui
|
window.ui = ui
|
||||||
|
|
||||||
|
ui.initOAuth({
|
||||||
|
clientId: "your-client-id",
|
||||||
|
clientSecret: "your-client-secret-if-required",
|
||||||
|
realm: "your-realms",
|
||||||
|
appName: "your-app-name",
|
||||||
|
scopeSeparator: "-",
|
||||||
|
additionalQueryStringParams: {test: "hello"}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
53
dev-helpers/oauth2-redirect.html
Normal file
53
dev-helpers/oauth2-redirect.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<body onload="run()">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
function run () {
|
||||||
|
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||||
|
var sentState = oauth2.state;
|
||||||
|
var redirectUrl = oauth2.redirectUrl;
|
||||||
|
var isValid, qp, arr;
|
||||||
|
|
||||||
|
qp = (window.location.hash || location.search).substring(1);
|
||||||
|
|
||||||
|
arr = qp.split("&")
|
||||||
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||||
|
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||||
|
function (key, value) {
|
||||||
|
return key === "" ? value : decodeURIComponent(value)
|
||||||
|
}
|
||||||
|
) : {}
|
||||||
|
|
||||||
|
isValid = qp.state === sentState
|
||||||
|
|
||||||
|
if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) {
|
||||||
|
if (!isValid) {
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "warning",
|
||||||
|
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qp.code) {
|
||||||
|
delete oauth2.state;
|
||||||
|
oauth2.auth.code = qp.code;
|
||||||
|
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||||
|
} else {
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "error",
|
||||||
|
message: "Authorization failed: no accessCode received from the server"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||||
|
}
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 445 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
13
dist/index.html
vendored
13
dist/index.html
vendored
@@ -1,10 +1,13 @@
|
|||||||
|
<!-- HTML for static distribution bundle build -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!-- this is for the dev server -->
|
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Swagger UI</title>
|
<title>Swagger UI</title>
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||||
<style>
|
<style>
|
||||||
html
|
html
|
||||||
{
|
{
|
||||||
@@ -64,9 +67,8 @@
|
|||||||
|
|
||||||
<div id="swagger-ui"></div>
|
<div id="swagger-ui"></div>
|
||||||
|
|
||||||
<!-- don't be alarmed, these don't match what's in dist, because webpack-dev-server serves them in memory. -->
|
<script src="./swagger-ui-bundle.js"> </script>
|
||||||
<script src="/dist/SwaggerUIBundle.js"> </script>
|
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||||
<script src="/dist/SwaggerUIStandalonePreset.js"> </script>
|
|
||||||
<script>
|
<script>
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
// Build a system
|
// Build a system
|
||||||
@@ -75,8 +77,7 @@ window.onload = function() {
|
|||||||
dom_id: '#swagger-ui',
|
dom_id: '#swagger-ui',
|
||||||
presets: [
|
presets: [
|
||||||
SwaggerUIBundle.presets.apis,
|
SwaggerUIBundle.presets.apis,
|
||||||
// yay ES6 modules ↘
|
SwaggerUIStandalonePreset
|
||||||
Array.isArray(SwaggerUIStandalonePreset) ? SwaggerUIStandalonePreset : SwaggerUIStandalonePreset.default
|
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
|||||||
@@ -8,11 +8,13 @@
|
|||||||
function run () {
|
function run () {
|
||||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||||
var sentState = oauth2.state;
|
var sentState = oauth2.state;
|
||||||
var isValid, qp;
|
var isValid, qp, arr;
|
||||||
|
|
||||||
qp = (window.location.hash || location.search).substring(1);
|
qp = (window.location.hash || location.search).substring(1);
|
||||||
|
|
||||||
qp = qp ? JSON.parse('{"' + qp.replace(/&/g, '","').replace(/=/g, '":"') + '"}',
|
arr = qp.split("&")
|
||||||
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||||
|
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||||
function (key, value) {
|
function (key, value) {
|
||||||
return key === "" ? value : decodeURIComponent(value)
|
return key === "" ? value : decodeURIComponent(value)
|
||||||
}
|
}
|
||||||
@@ -33,51 +35,19 @@
|
|||||||
if (qp.code) {
|
if (qp.code) {
|
||||||
delete oauth2.state;
|
delete oauth2.state;
|
||||||
oauth2.auth.code = qp.code;
|
oauth2.auth.code = qp.code;
|
||||||
createForm(oauth2.auth, qp).submit();
|
oauth2.callback(oauth2.auth);
|
||||||
} else {
|
} else {
|
||||||
oauth2.errCb({
|
oauth2.errCb({
|
||||||
authId: oauth2.auth.name,
|
authId: oauth2.auth.name,
|
||||||
source: "auth",
|
source: "auth",
|
||||||
level: "error",
|
level: "error",
|
||||||
message: "Authorization failed: no accessCode came from the server"
|
message: "Authorization failed: no accessCode received from the server"
|
||||||
});
|
});
|
||||||
window.close();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid});
|
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid});
|
||||||
|
}
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function createForm(auth, qp) {
|
|
||||||
var form = document.createElement("form");
|
|
||||||
var schema = auth.schema;
|
|
||||||
var action = schema.get("tokenUrl");
|
|
||||||
var name, input;
|
|
||||||
|
|
||||||
var fields = {
|
|
||||||
code: qp.code,
|
|
||||||
"redirect_uri": location.protocol + "//" + location.host + location.pathname,
|
|
||||||
"grant_type": "authorization_code",
|
|
||||||
"client_secret": auth.clientSecret,
|
|
||||||
"client_id": auth.clientId
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( name in fields ) {
|
|
||||||
input = document.createElement("input");
|
|
||||||
input.name = name;
|
|
||||||
input.value = fields[name];
|
|
||||||
input.type = "hidden";
|
|
||||||
form.appendChild(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
form.method = "POST";
|
|
||||||
form.action = action;
|
|
||||||
|
|
||||||
document.body.appendChild(form);
|
|
||||||
|
|
||||||
return form;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
83
dist/swagger-ui-bundle.js
vendored
83
dist/swagger-ui-bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-bundle.js.map
vendored
2
dist/swagger-ui-bundle.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;AA6OA;;;;;;AAoIA;AAm7FA;AAwtCA;AAg0IA;;;;;AAkxBA;AAo8IA;AA41GA;AA23FA;AAqqFA;AA0nFA;AA49CA;AAwhDA;AAkrCA;AAumFA;AAmnHA;;;;;;;;;;;;;;AAqjHA;AAyoIA;AAkuJA;AAilHA;AA4kGA;AAwkEA;AAs3DA;AAovDA;AAotBA;AAoqGA;;;;;;AAueA;AAimGA;AA44EA;;;;;AAoGA;AA2qFA;AAo2CA;AAkvDA;AA8tCA;AAoiEA;AA69FA;;;;;;;;;AA20BA;AA2zIA;AAm4DA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAyTA;;;;;;AAoIA;AAi7FA;AAmtCA;AAi0IA;AA0oJA;AAgwFA;AAyrGA;AA4lFA;AAioFA;AA09CA;AAwhDA;AAkrCA;AAu4EA;;;;;AAykCA;AAsyJA;;;;;;;;;;;;;;AA64EA;AA4mIA;AAquJA;AA2qHA;AA2mGA;AAiiEA;AAq4DA;AAg3DA;AAwZA;;;;;;AA8wFA;AAw3FA;;;;;AAkgDA;AAgsFA;AAw2CA;AA2kCA;AA88CA;AAkgFA;AAk2FA;;;;;;;;;AA2pDA;AA2zIA;AAk4DA;AA8mDA","sourceRoot":""}
|
||||||
20
dist/swagger-ui-standalone-preset.js
vendored
20
dist/swagger-ui-standalone-preset.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-standalone-preset.js.map
vendored
2
dist/swagger-ui-standalone-preset.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA0SA;AAyiGA;AAqwFA;;;;;;AA4eA;AAkvFA;AAu+CA;AAo+CA;AAgrCA;AAgyEA","sourceRoot":""}
|
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA8QA;AAmvGA;AAuxFA;;;;;;AAocA;AAkvFA;AAu+CA;AAo+CA;AAgrCA;AAuyEA","sourceRoot":""}
|
||||||
2
dist/swagger-ui.css
vendored
2
dist/swagger-ui.css
vendored
File diff suppressed because one or more lines are too long
48
docker-run.sh
Normal file
48
docker-run.sh
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
INDEX_FILE=/usr/share/nginx/html/index.html
|
||||||
|
|
||||||
|
replace_in_index () {
|
||||||
|
if [ "$1" != "**None**" ]; then
|
||||||
|
sed -i "s|/\*||g" $INDEX_FILE
|
||||||
|
sed -i "s|\*/||g" $INDEX_FILE
|
||||||
|
sed -i "s|$1|$2|g" $INDEX_FILE
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_or_delete_in_index () {
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
sed -i "/$1/d" $INDEX_FILE
|
||||||
|
else
|
||||||
|
replace_in_index $1 $2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_in_index myApiKeyXXXX123456789 $API_KEY
|
||||||
|
replace_or_delete_in_index your-client-id $OAUTH_CLIENT_ID
|
||||||
|
replace_or_delete_in_index your-client-secret-if-required $OAUTH_CLIENT_SECRET
|
||||||
|
replace_or_delete_in_index your-realms $OAUTH_REALM
|
||||||
|
replace_or_delete_in_index your-app-name $OAUTH_APP_NAME
|
||||||
|
if [ "$OAUTH_ADDITIONAL_PARAMS" != "**None**" ]; then
|
||||||
|
replace_in_index "additionalQueryStringParams: {}" "additionalQueryStringParams: {$OAUTH_ADDITIONAL_PARAMS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f $SWAGGER_JSON ]]; then
|
||||||
|
sed -i "s|http://petstore.swagger.io/v2/swagger.json|swagger.json|g" $INDEX_FILE
|
||||||
|
sed -i "s|http://example.com/api|swagger.json|g" $INDEX_FILE
|
||||||
|
else
|
||||||
|
sed -i "s|http://petstore.swagger.io/v2/swagger.json|$API_URL|g" $INDEX_FILE
|
||||||
|
sed -i "s|http://example.com/api|$API_URL|g" $INDEX_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$VALIDATOR_URL" ]]; then
|
||||||
|
sed -i "s|.*validatorUrl:.*$||g" $INDEX_FILE
|
||||||
|
TMP_VU="$VALIDATOR_URL"
|
||||||
|
[[ "$VALIDATOR_URL" != "null" && "$VALIDATOR_URL" != "undefined" ]] && TMP_VU="\"${VALIDATOR_URL}\""
|
||||||
|
sed -i "s|\(url: .*,\)|\1\n validatorUrl: ${TMP_VU},|g" $INDEX_FILE
|
||||||
|
unset TMP_VU
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec nginx -g 'daemon off;'
|
||||||
@@ -4,9 +4,23 @@ var webpack = require('webpack')
|
|||||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||||
var deepExtend = require('deep-extend')
|
var deepExtend = require('deep-extend')
|
||||||
var autoprefixer = require('autoprefixer')
|
var autoprefixer = require('autoprefixer')
|
||||||
|
const {gitDescribeSync} = require('git-describe');
|
||||||
|
|
||||||
var loadersByExtension = require('./build-tools/loadersByExtension')
|
var loadersByExtension = require('./build-tools/loadersByExtension')
|
||||||
|
|
||||||
|
var pkg = require('./package.json')
|
||||||
|
|
||||||
|
let gitInfo
|
||||||
|
|
||||||
|
try {
|
||||||
|
gitInfo = gitDescribeSync(__dirname)
|
||||||
|
} catch(e) {
|
||||||
|
gitInfo = {
|
||||||
|
hash: 'noGit',
|
||||||
|
dirty: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function(options) {
|
module.exports = function(options) {
|
||||||
|
|
||||||
// Special options, that have logic in this file
|
// Special options, that have logic in this file
|
||||||
@@ -60,7 +74,13 @@ module.exports = function(options) {
|
|||||||
'process.env': {
|
'process.env': {
|
||||||
NODE_ENV: specialOptions.minimize ? JSON.stringify('production') : null,
|
NODE_ENV: specialOptions.minimize ? JSON.stringify('production') : null,
|
||||||
WEBPACK_INLINE_STYLES: !Boolean(specialOptions.separateStylesheets)
|
WEBPACK_INLINE_STYLES: !Boolean(specialOptions.separateStylesheets)
|
||||||
|
|
||||||
},
|
},
|
||||||
|
'buildInfo': JSON.stringify({
|
||||||
|
PACKAGE_VERSION: (pkg.version),
|
||||||
|
GIT_COMMIT: gitInfo.hash,
|
||||||
|
GIT_DIRTY: gitInfo.dirty
|
||||||
|
})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
var cssLoader = 'css-loader!postcss-loader'
|
var cssLoader = 'css-loader!postcss-loader'
|
||||||
|
|||||||
37
package.json
37
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "swagger-ui",
|
"name": "swagger-ui",
|
||||||
"version": "3.0.1",
|
"version": "3.0.11",
|
||||||
"main": "dist/swagger-ui.js",
|
"main": "dist/swagger-ui.js",
|
||||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
],
|
],
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "http-server -i -a 0.0.0.0 -p 3001",
|
|
||||||
"build": "npm run build-core && npm run build-bundle && npm run build-standalone",
|
"build": "npm run build-core && npm run build-bundle && npm run build-standalone",
|
||||||
"build-bundle": "webpack --config webpack-dist-bundle.config.js --colors",
|
"build-bundle": "webpack --config webpack-dist-bundle.config.js --colors",
|
||||||
"build-core": "webpack --config webpack-dist.config.js --colors",
|
"build-core": "webpack --config webpack-dist.config.js --colors",
|
||||||
@@ -23,22 +22,28 @@
|
|||||||
"dev": "npm-run-all --parallel hot-server watch open-localhost",
|
"dev": "npm-run-all --parallel hot-server watch open-localhost",
|
||||||
"watch": "webpack --config webpack-watch.config.js --watch --progress",
|
"watch": "webpack --config webpack-watch.config.js --watch --progress",
|
||||||
"open-localhost": "node -e 'require(\"open\")(\"http://localhost:3200\")'",
|
"open-localhost": "node -e 'require(\"open\")(\"http://localhost:3200\")'",
|
||||||
"hot-server": "webpack-dev-server --host 0.0.0.0 --config webpack-hot-dev-server.config.js --inline --hot --progress --content-base dist/",
|
"hot-server": "webpack-dev-server --host 0.0.0.0 --config webpack-hot-dev-server.config.js --inline --hot --progress --content-base dev-helpers/",
|
||||||
"deps-license": "license-checker --production --csv --out $npm_package_config_deps_check_dir/licenses.csv && license-checker --development --csv --out $npm_package_config_deps_check_dir/licenses-dev.csv",
|
"deps-license": "license-checker --production --csv --out $npm_package_config_deps_check_dir/licenses.csv && license-checker --development --csv --out $npm_package_config_deps_check_dir/licenses-dev.csv",
|
||||||
"deps-size": "webpack -p --config webpack.check.js --json | webpack-bundle-size-analyzer >| $npm_package_config_deps_check_dir/sizes.txt",
|
"deps-size": "webpack -p --config webpack.check.js --json | webpack-bundle-size-analyzer >| $npm_package_config_deps_check_dir/sizes.txt",
|
||||||
"deps-check": "npm run deps-license && npm run deps-size",
|
"deps-check": "npm run deps-license && npm run deps-size",
|
||||||
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core"
|
"lint": "eslint --cache --ext '.js,.jsx' src test",
|
||||||
|
"lint-errors": "eslint --cache --quiet --ext '.js,.jsx' src test",
|
||||||
|
"lint-fix": "eslint --cache --ext '.js,.jsx' src test --fix",
|
||||||
|
"test": "npm run lint-errors && npm run just-test-in-node",
|
||||||
|
"test-in-node": "npm run lint-errors && npm run just-test-in-node",
|
||||||
|
"just-test": "karma start --config karma.conf.js",
|
||||||
|
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"babel-polyfill": "^6.23.0",
|
||||||
|
"base64-js": "^1.2.0",
|
||||||
"brace": "0.7.0",
|
"brace": "0.7.0",
|
||||||
"btoa": "^1.1.2",
|
|
||||||
"debounce": "1.0.0",
|
|
||||||
"deep-extend": "0.4.1",
|
"deep-extend": "0.4.1",
|
||||||
"expect": "1.20.2",
|
"expect": "1.20.2",
|
||||||
"getbase": "^2.8.2",
|
"getbase": "^2.8.2",
|
||||||
|
"ieee754": "^1.1.8",
|
||||||
"immutable": "^3.x.x",
|
"immutable": "^3.x.x",
|
||||||
"js-yaml": "^3.5.5",
|
"js-yaml": "^3.5.5",
|
||||||
"jsonschema": "^1.1.0",
|
|
||||||
"less": "2.7.1",
|
"less": "2.7.1",
|
||||||
"lodash": "4.17.2",
|
"lodash": "4.17.2",
|
||||||
"matcher": "^0.1.2",
|
"matcher": "^0.1.2",
|
||||||
@@ -47,7 +52,7 @@
|
|||||||
"react": "^15.4.0",
|
"react": "^15.4.0",
|
||||||
"react-addons-perf": "0.14.8",
|
"react-addons-perf": "0.14.8",
|
||||||
"react-addons-shallow-compare": "0.14.8",
|
"react-addons-shallow-compare": "0.14.8",
|
||||||
"react-addons-test-utils": "0.14.8",
|
"react-addons-test-utils": "^15.4.0",
|
||||||
"react-collapse": "2.3.1",
|
"react-collapse": "2.3.1",
|
||||||
"react-dom": "^15.4.0",
|
"react-dom": "^15.4.0",
|
||||||
"react-height": "^2.0.0",
|
"react-height": "^2.0.0",
|
||||||
@@ -64,12 +69,12 @@
|
|||||||
"reselect": "2.5.3",
|
"reselect": "2.5.3",
|
||||||
"serialize-error": "2.0.0",
|
"serialize-error": "2.0.0",
|
||||||
"shallowequal": "0.2.2",
|
"shallowequal": "0.2.2",
|
||||||
"swagger-client": "^3.0.1",
|
"swagger-client": "~3.0.11",
|
||||||
|
"url-parse": "^1.1.8",
|
||||||
"whatwg-fetch": "0.11.1",
|
"whatwg-fetch": "0.11.1",
|
||||||
"worker-loader": "^0.7.1",
|
"worker-loader": "^0.7.1",
|
||||||
"xml": "1.0.1",
|
"xml": "1.0.1",
|
||||||
"yaml-js": "^0.1.3",
|
"yaml-js": "^0.1.3"
|
||||||
"yaml-worker": "^2.1.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "6.6.1",
|
"autoprefixer": "6.6.1",
|
||||||
@@ -85,11 +90,20 @@
|
|||||||
"css-loader": "0.22.0",
|
"css-loader": "0.22.0",
|
||||||
"deep-extend": "^0.4.1",
|
"deep-extend": "^0.4.1",
|
||||||
"deepmerge": "^1.3.2",
|
"deepmerge": "^1.3.2",
|
||||||
|
"enzyme": "^2.7.1",
|
||||||
|
"eslint": "^2.13.1",
|
||||||
|
"eslint-plugin-react": "^6.10.3",
|
||||||
"extract-text-webpack-plugin": "0.8.2",
|
"extract-text-webpack-plugin": "0.8.2",
|
||||||
"file-loader": "0.8.4",
|
"file-loader": "0.8.4",
|
||||||
|
"git-describe": "^4.0.1",
|
||||||
"html-webpack-plugin": "^2.28.0",
|
"html-webpack-plugin": "^2.28.0",
|
||||||
"imports-loader": "0.6.5",
|
"imports-loader": "0.6.5",
|
||||||
"json-loader": "0.5.3",
|
"json-loader": "0.5.3",
|
||||||
|
"karma": "^0.13.22",
|
||||||
|
"karma-chrome-launcher": "^0.2.3",
|
||||||
|
"karma-mocha": "^0.2.2",
|
||||||
|
"karma-sourcemap-loader": "^0.3.7",
|
||||||
|
"karma-webpack": "1.8.0",
|
||||||
"less": "2.5.3",
|
"less": "2.5.3",
|
||||||
"less-loader": "2.2.1",
|
"less-loader": "2.2.1",
|
||||||
"license-checker": "^8.0.4",
|
"license-checker": "^8.0.4",
|
||||||
@@ -101,6 +115,7 @@
|
|||||||
"postcss-loader": "0.7.0",
|
"postcss-loader": "0.7.0",
|
||||||
"raw-loader": "0.5.1",
|
"raw-loader": "0.5.1",
|
||||||
"react-hot-loader": "^1.3.1",
|
"react-hot-loader": "^1.3.1",
|
||||||
|
"react-test-renderer": "^15.5.4",
|
||||||
"rimraf": "^2.6.0",
|
"rimraf": "^2.6.0",
|
||||||
"sass-loader": "^6.0.2",
|
"sass-loader": "^6.0.2",
|
||||||
"standard": "^8.6.0",
|
"standard": "^8.6.0",
|
||||||
|
|||||||
28
snapcraft.yaml
Normal file
28
snapcraft.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: swagger-ui
|
||||||
|
version: master
|
||||||
|
summary: The World's Most Popular API Framework
|
||||||
|
description: |
|
||||||
|
Swagger UI is part of the Swagger project. The Swagger project allows you to
|
||||||
|
produce, visualize and consume your OWN RESTful services. No proxy or 3rd
|
||||||
|
party services required. Do it your own way.
|
||||||
|
|
||||||
|
Swagger UI is a dependency-free collection of HTML, Javascript, and CSS
|
||||||
|
assets that dynamically generate beautiful documentation and sandbox from a
|
||||||
|
Swagger-compliant API. Because Swagger UI has no dependencies, you can host
|
||||||
|
it in any server environment, or on your local machine.
|
||||||
|
|
||||||
|
grade: devel
|
||||||
|
confinement: strict
|
||||||
|
|
||||||
|
apps:
|
||||||
|
swagger-ui:
|
||||||
|
command: sh -c \"cd $SNAP/lib/node_modules/swagger-ui/dist && http-server -a localhost -p 8080\"
|
||||||
|
daemon: simple
|
||||||
|
plugs: [network, network-bind]
|
||||||
|
|
||||||
|
parts:
|
||||||
|
swagger-ui:
|
||||||
|
source: .
|
||||||
|
plugin: nodejs
|
||||||
|
npm-run: [build]
|
||||||
|
node-packages: [handlebars, http-server]
|
||||||
@@ -64,11 +64,10 @@ export default class ApiKeyAuth extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<label>Value:</label>
|
<label>Value:</label>
|
||||||
<Col>
|
|
||||||
{
|
{
|
||||||
value || <Input type="text" onChange={ this.onChange }/>
|
value ? <code> ****** </code>
|
||||||
|
: <Col><Input type="text" onChange={ this.onChange }/></Col>
|
||||||
}
|
}
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
{
|
{
|
||||||
errors.valueSeq().map( (error, key) => {
|
errors.valueSeq().map( (error, key) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default class AuthorizeBtn extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClick =() => {
|
onClick =() => {
|
||||||
let { authActions, authSelectors, errActions} = this.props
|
let { authActions, authSelectors } = this.props
|
||||||
let definitions = authSelectors.definitionsToAuthorize()
|
let definitions = authSelectors.definitionsToAuthorize()
|
||||||
|
|
||||||
authActions.showDefinitions(definitions)
|
authActions.showDefinitions(definitions)
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ export default class AuthorizeOperationBtn extends React.Component {
|
|||||||
|
|
||||||
let isAuthorized = authSelectors.isAuthorized(security)
|
let isAuthorized = authSelectors.isAuthorized(security)
|
||||||
|
|
||||||
|
if(isAuthorized === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={isAuthorized ? "authorization__btn locked" : "authorization__btn unlocked"} onClick={ this.onClick }>
|
<button className={isAuthorized ? "authorization__btn locked" : "authorization__btn unlocked"} onClick={ this.onClick }>
|
||||||
<svg width="20" height="20">
|
<svg width="20" height="20">
|
||||||
|
|||||||
@@ -42,14 +42,12 @@ export default class Auths extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { definitions, getComponent, authSelectors, errSelectors, specSelectors } = this.props
|
let { definitions, getComponent, authSelectors, errSelectors } = this.props
|
||||||
const ApiKeyAuth = getComponent("apiKeyAuth")
|
const ApiKeyAuth = getComponent("apiKeyAuth")
|
||||||
const BasicAuth = getComponent("basicAuth")
|
const BasicAuth = getComponent("basicAuth")
|
||||||
const Oauth2 = getComponent("oauth2", true)
|
const Oauth2 = getComponent("oauth2", true)
|
||||||
const Button = getComponent("Button")
|
const Button = getComponent("Button")
|
||||||
const JumpToPath = getComponent("JumpToPath", true)
|
|
||||||
|
|
||||||
let specStr = specSelectors.specStr()
|
|
||||||
let authorized = authSelectors.authorized()
|
let authorized = authSelectors.authorized()
|
||||||
|
|
||||||
let authorizedAuth = definitions.filter( (definition, key) => {
|
let authorizedAuth = definitions.filter( (definition, key) => {
|
||||||
|
|||||||
@@ -63,19 +63,23 @@ export default class BasicAuth extends React.Component {
|
|||||||
source={ schema.get("description") } />
|
source={ schema.get("description") } />
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Col tablet={2} desktop={2}>username:</Col>
|
<label>Username:</label>
|
||||||
<Col tablet={10} desktop={10}>
|
|
||||||
{
|
{
|
||||||
username || <Input type="text" required="required" name="username" onChange={ this.onChange }/>
|
username ? <code> { username } </code>
|
||||||
|
: <Col><Input type="text" required="required" name="username" onChange={ this.onChange }/></Col>
|
||||||
}
|
}
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<label>Password:</label>
|
||||||
{
|
{
|
||||||
!username && <Row>
|
username ? <code> ****** </code>
|
||||||
<Col tablet={2} desktop={2}>password:</Col>
|
: <Col><Input required="required"
|
||||||
<Col tablet={10} desktop={10}><Input required="required" autoComplete="new-password" name="password" type="password" onChange={ this.onChange }/></Col>
|
autoComplete="new-password"
|
||||||
</Row>
|
name="password"
|
||||||
|
type="password"
|
||||||
|
onChange={ this.onChange }/></Col>
|
||||||
}
|
}
|
||||||
|
</Row>
|
||||||
{
|
{
|
||||||
errors.valueSeq().map( (error, key) => {
|
errors.valueSeq().map( (error, key) => {
|
||||||
return <AuthError error={ error }
|
return <AuthError error={ error }
|
||||||
|
|||||||
@@ -10,25 +10,27 @@ export default class Oauth2 extends React.Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
authorized: PropTypes.object,
|
authorized: PropTypes.object,
|
||||||
configs: PropTypes.object,
|
|
||||||
getComponent: PropTypes.func.isRequired,
|
getComponent: PropTypes.func.isRequired,
|
||||||
schema: PropTypes.object.isRequired,
|
schema: PropTypes.object.isRequired,
|
||||||
authSelectors: PropTypes.object.isRequired,
|
authSelectors: PropTypes.object.isRequired,
|
||||||
authActions: PropTypes.object.isRequired,
|
authActions: PropTypes.object.isRequired,
|
||||||
errSelectors: PropTypes.object.isRequired,
|
errSelectors: PropTypes.object.isRequired,
|
||||||
errActions: PropTypes.object.isRequired
|
errActions: PropTypes.object.isRequired,
|
||||||
|
getConfigs: PropTypes.any
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context)
|
super(props, context)
|
||||||
let { name, schema, authorized } = this.props
|
let { name, schema, authorized, authSelectors } = this.props
|
||||||
let auth = authorized && authorized.get(name)
|
let auth = authorized && authorized.get(name)
|
||||||
|
let authConfigs = authSelectors.getConfigs() || {}
|
||||||
let username = auth && auth.get("username") || ""
|
let username = auth && auth.get("username") || ""
|
||||||
let clientId = auth && auth.get("clientId") || ""
|
let clientId = auth && auth.get("clientId") || authConfigs.clientId || ""
|
||||||
let clientSecret = auth && auth.get("clientSecret") || ""
|
let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || ""
|
||||||
let passwordType = auth && auth.get("passwordType") || "none"
|
let passwordType = auth && auth.get("passwordType") || "basic"
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
appName: authConfigs.appName,
|
||||||
name: name,
|
name: name,
|
||||||
schema: schema,
|
schema: schema,
|
||||||
scopes: [],
|
scopes: [],
|
||||||
@@ -41,11 +43,12 @@ export default class Oauth2 extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
authorize =() => {
|
authorize =() => {
|
||||||
let { authActions, errActions, getConfigs } = this.props
|
let { authActions, errActions, getConfigs, authSelectors } = this.props
|
||||||
let configs = getConfigs()
|
let configs = getConfigs()
|
||||||
|
let authConfigs = authSelectors.getConfigs()
|
||||||
|
|
||||||
errActions.clear({authId: name,type: "auth", source: "auth"})
|
errActions.clear({authId: name,type: "auth", source: "auth"})
|
||||||
oauth2Authorize(this.state, authActions, errActions, configs)
|
oauth2Authorize({auth: this.state, authActions, errActions, configs, authConfigs })
|
||||||
}
|
}
|
||||||
|
|
||||||
onScopeChange =(e) => {
|
onScopeChange =(e) => {
|
||||||
@@ -98,6 +101,7 @@ export default class Oauth2 extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
|
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
|
||||||
|
{ !this.state.appName ? null : <h5>Application: { this.state.appName } </h5> }
|
||||||
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}}
|
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}}
|
||||||
source={ schema.get("description") } />
|
source={ schema.get("description") } />
|
||||||
|
|
||||||
@@ -108,82 +112,92 @@ export default class Oauth2 extends React.Component {
|
|||||||
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
||||||
|
|
||||||
{
|
{
|
||||||
flow === PASSWORD && ( !isAuthorized || isAuthorized && this.state.username) && <Row>
|
flow !== PASSWORD ? null
|
||||||
<Col tablet={2} desktop={2}>username:</Col>
|
: <Row>
|
||||||
<Col tablet={10} desktop={10}>
|
<Row>
|
||||||
|
<label htmlFor="oauth_username">username:</label>
|
||||||
{
|
{
|
||||||
isAuthorized ? <span>{ this.state.username }</span>
|
isAuthorized ? <code> { this.state.username } </code>
|
||||||
: <input type="text" data-name="username" onChange={ this.onInputChange }/>
|
: <Col tablet={10} desktop={10}>
|
||||||
}
|
<input id="oauth_username" type="text" data-name="username" onChange={ this.onInputChange }/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
}
|
}
|
||||||
|
</Row>
|
||||||
{
|
{
|
||||||
flow === PASSWORD && !isAuthorized && <Row>
|
|
||||||
<Col tablet={2} desktop={2}>password:</Col>
|
}
|
||||||
<Col tablet={10} desktop={10}>
|
<Row>
|
||||||
<input type="password" data-name="password" onChange={ this.onInputChange }/>
|
<label htmlFor="oauth_password">password:</label>
|
||||||
|
{
|
||||||
|
isAuthorized ? <code> ****** </code>
|
||||||
|
: <Col tablet={10} desktop={10}>
|
||||||
|
<input id="oauth_password" type="password" data-name="password" onChange={ this.onInputChange }/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
}
|
}
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<label htmlFor="password_type">type:</label>
|
||||||
{
|
{
|
||||||
flow === PASSWORD && <Row>
|
isAuthorized ? <code> { this.state.passwordType } </code>
|
||||||
<Col tablet={2} desktop={2}>type:</Col>
|
: <Col tablet={10} desktop={10}>
|
||||||
<Col tablet={10} desktop={10}>
|
<select id="password_type" data-name="passwordType" onChange={ this.onInputChange }>
|
||||||
{
|
|
||||||
isAuthorized ? <span>{ this.state.passwordType }</span>
|
|
||||||
: <select data-name="passwordType" onChange={ this.onInputChange }>
|
|
||||||
<option value="none">None or other</option>
|
|
||||||
<option value="basic">Basic auth</option>
|
<option value="basic">Basic auth</option>
|
||||||
<option value="request">Request body</option>
|
<option value="request-body">Request body</option>
|
||||||
|
<option value="query">Query parameters</option>
|
||||||
</select>
|
</select>
|
||||||
}
|
|
||||||
</Col>
|
</Col>
|
||||||
|
}
|
||||||
|
</Row>
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
( flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) &&
|
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) &&
|
||||||
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
|
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
|
||||||
<label htmlFor="client_id">client_id:</label>
|
<label htmlFor="client_id">client_id:</label>
|
||||||
<Col tablet={10} desktop={10}>
|
|
||||||
{
|
{
|
||||||
isAuthorized ? <span>{ this.state.clientId }</span>
|
isAuthorized ? <code> ****** </code>
|
||||||
: <input id="client_id" type="text" required={ flow === PASSWORD } data-name="clientId"
|
: <Col tablet={10} desktop={10}>
|
||||||
|
<input id="client_id"
|
||||||
|
type="text"
|
||||||
|
required={ flow === PASSWORD }
|
||||||
|
value={ this.state.clientId }
|
||||||
|
data-name="clientId"
|
||||||
onChange={ this.onInputChange }/>
|
onChange={ this.onInputChange }/>
|
||||||
}
|
|
||||||
</Col>
|
</Col>
|
||||||
|
}
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
( flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) && <Row>
|
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && <Row>
|
||||||
<label htmlFor="client_secret">client_secret:</label>
|
<label htmlFor="client_secret">client_secret:</label>
|
||||||
<Col tablet={10} desktop={10}>
|
|
||||||
{
|
{
|
||||||
isAuthorized ? <span>{ this.state.clientSecret }</span>
|
isAuthorized ? <code> ****** </code>
|
||||||
: <input id="client_secret" type="text" data-name="clientSecret"
|
: <Col tablet={10} desktop={10}>
|
||||||
|
<input id="client_secret"
|
||||||
|
value={ this.state.clientSecret }
|
||||||
|
type="text"
|
||||||
|
data-name="clientSecret"
|
||||||
onChange={ this.onInputChange }/>
|
onChange={ this.onInputChange }/>
|
||||||
}
|
|
||||||
</Col>
|
</Col>
|
||||||
|
}
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
!isAuthorized && flow !== PASSWORD && scopes && scopes.size ? <div className="scopes">
|
!isAuthorized && scopes && scopes.size ? <div className="scopes">
|
||||||
<h2>Scopes:</h2>
|
<h2>Scopes:</h2>
|
||||||
{ scopes.map((description, name) => {
|
{ scopes.map((description, name) => {
|
||||||
return (
|
return (
|
||||||
<Row key={ name }>
|
<Row key={ name }>
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<Input data-value={ name }
|
<Input data-value={ name }
|
||||||
id={`${name}-checkbox`}
|
id={`${name}-checkbox-${this.state.name}`}
|
||||||
disabled={ isAuthorized }
|
disabled={ isAuthorized }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
onChange={ this.onScopeChange }/>
|
onChange={ this.onScopeChange }/>
|
||||||
<label htmlFor={`${name}-checkbox`}>
|
<label htmlFor={`${name}-checkbox-${this.state.name}`}>
|
||||||
<span className="item"></span>
|
<span className="item"></span>
|
||||||
<div className="text">
|
<div className="text">
|
||||||
<p className="name">{name}</p>
|
<p className="name">{name}</p>
|
||||||
@@ -205,7 +219,7 @@ export default class Oauth2 extends React.Component {
|
|||||||
} )
|
} )
|
||||||
}
|
}
|
||||||
<div className="auth-btn-wrapper">
|
<div className="auth-btn-wrapper">
|
||||||
{ isValid && flow !== APPLICATION &&
|
{ isValid &&
|
||||||
( isAuthorized ? <Button className="btn modal-btn auth authorize" onClick={ this.logout }>Logout</Button>
|
( isAuthorized ? <Button className="btn modal-btn auth authorize" onClick={ this.logout }>Logout</Button>
|
||||||
: <Button className="btn modal-btn auth authorize" onClick={ this.authorize }>Authorize</Button>
|
: <Button className="btn modal-btn auth authorize" onClick={ this.authorize }>Authorize</Button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { PropTypes } from "react"
|
import React, { PropTypes } from "react"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
import { fromJS } from 'immutable'
|
import { fromJS } from "immutable"
|
||||||
|
|
||||||
const noop = ()=>{}
|
const noop = ()=>{}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default class Curl extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<h4>Curl</h4>
|
<h4>Curl</h4>
|
||||||
<div className="copy-paste">
|
<div className="copy-paste">
|
||||||
<textarea onFocus={this.handleFocus} className="curl" style={{ whiteSpace: "normal" }} defaultValue={curl}></textarea>
|
<textarea onFocus={this.handleFocus} className="curl" style={{ whiteSpace: "normal" }} value={curl}></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import React, { PropTypes } from "react"
|
import React, { PropTypes } from "react"
|
||||||
import Im, { List } from "immutable"
|
import { List } from "immutable"
|
||||||
import Collapse from "react-collapse"
|
import Collapse from "react-collapse"
|
||||||
import sortBy from "lodash/sortBy"
|
|
||||||
|
|
||||||
export default class Errors extends React.Component {
|
export default class Errors extends React.Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
jumpToLine: PropTypes.func,
|
editorActions: PropTypes.object,
|
||||||
errSelectors: PropTypes.object.isRequired,
|
errSelectors: PropTypes.object.isRequired,
|
||||||
layoutSelectors: PropTypes.object.isRequired,
|
layoutSelectors: PropTypes.object.isRequired,
|
||||||
layoutActions: PropTypes.object.isRequired
|
layoutActions: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { jumpToLine, errSelectors, layoutSelectors, layoutActions } = this.props
|
let { editorActions, errSelectors, layoutSelectors, layoutActions } = this.props
|
||||||
|
|
||||||
|
if(editorActions && editorActions.jumpToLine) {
|
||||||
|
var jumpToLine = editorActions.jumpToLine
|
||||||
|
}
|
||||||
|
|
||||||
let errors = errSelectors.allErrors()
|
let errors = errSelectors.allErrors()
|
||||||
|
|
||||||
@@ -38,10 +41,11 @@ export default class Errors extends React.Component {
|
|||||||
<Collapse isOpened={ isVisible } animated >
|
<Collapse isOpened={ isVisible } animated >
|
||||||
<div className="errors">
|
<div className="errors">
|
||||||
{ sortedJSErrors.map((err, i) => {
|
{ sortedJSErrors.map((err, i) => {
|
||||||
if(err.get("type") === "thrown") {
|
let type = err.get("type")
|
||||||
|
if(type === "thrown" || type === "auth") {
|
||||||
return <ThrownErrorItem key={ i } error={ err.get("error") || err } jumpToLine={jumpToLine} />
|
return <ThrownErrorItem key={ i } error={ err.get("error") || err } jumpToLine={jumpToLine} />
|
||||||
}
|
}
|
||||||
if(err.get("type") === "spec") {
|
if(type === "spec") {
|
||||||
return <SpecErrorItem key={ i } error={ err } jumpToLine={jumpToLine} />
|
return <SpecErrorItem key={ i } error={ err } jumpToLine={jumpToLine} />
|
||||||
}
|
}
|
||||||
}) }
|
}) }
|
||||||
@@ -69,7 +73,7 @@ const ThrownErrorItem = ( { error, jumpToLine } ) => {
|
|||||||
{ error.get("message") }
|
{ error.get("message") }
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
{ errorLine ? <a onClick={jumpToLine.bind(null, errorLine)}>Jump to line { errorLine }</a> : null }
|
{ errorLine && jumpToLine ? <a onClick={jumpToLine.bind(null, errorLine)}>Jump to line { errorLine }</a> : null }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -78,13 +82,25 @@ const ThrownErrorItem = ( { error, jumpToLine } ) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SpecErrorItem = ( { error, jumpToLine } ) => {
|
const SpecErrorItem = ( { error, jumpToLine } ) => {
|
||||||
|
let locationMessage = null
|
||||||
|
|
||||||
|
if(error.get("path")) {
|
||||||
|
if(List.isList(error.get("path"))) {
|
||||||
|
locationMessage = <small>at { error.get("path").join(".") }</small>
|
||||||
|
} else {
|
||||||
|
locationMessage = <small>at { error.get("path") }</small>
|
||||||
|
}
|
||||||
|
} else if(error.get("line") && !jumpToLine) {
|
||||||
|
locationMessage = <small>on line { error.get("line") }</small>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="error-wrapper">
|
<div className="error-wrapper">
|
||||||
{ !error ? null :
|
{ !error ? null :
|
||||||
<div>
|
<div>
|
||||||
<h4>{ toTitleCase(error.get("source")) + " " + error.get("level") }{ error.get("path") ? <small> at {List.isList(error.get("path")) ? error.get("path").join(".") : error.get("path")}</small>: null }</h4>
|
<h4>{ toTitleCase(error.get("source")) + " " + error.get("level") } { locationMessage }</h4>
|
||||||
<span style={{ whiteSpace: "pre-line"}}>{ error.get("message") }</span>
|
<span style={{ whiteSpace: "pre-line"}}>{ error.get("message") }</span>
|
||||||
<div>
|
<div style={{ "text-decoration": "underline", "cursor": "pointer" }}>
|
||||||
{ jumpToLine ? (
|
{ jumpToLine ? (
|
||||||
<a onClick={jumpToLine.bind(null, error.get("line"))}>Jump to line { error.get("line") }</a>
|
<a onClick={jumpToLine.bind(null, error.get("line"))}>Jump to line { error.get("line") }</a>
|
||||||
) : null }
|
) : null }
|
||||||
@@ -107,6 +123,10 @@ ThrownErrorItem.propTypes = {
|
|||||||
jumpToLine: PropTypes.func
|
jumpToLine: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThrownErrorItem.defaultProps = {
|
||||||
|
jumpToLine: null
|
||||||
|
}
|
||||||
|
|
||||||
SpecErrorItem.propTypes = {
|
SpecErrorItem.propTypes = {
|
||||||
error: PropTypes.object.isRequired,
|
error: PropTypes.object.isRequired,
|
||||||
jumpToLine: PropTypes.func
|
jumpToLine: PropTypes.func
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { Component, PropTypes } from "react"
|
import React, { Component, PropTypes } from "react"
|
||||||
import { fromJS } from "immutable"
|
|
||||||
|
|
||||||
export default class Execute extends Component {
|
export default class Execute extends Component {
|
||||||
|
|
||||||
@@ -29,9 +28,6 @@ export default class Execute extends Component {
|
|||||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue([this.props.path, this.props.method], val)
|
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue([this.props.path, this.props.method], val)
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
let { getComponent, operation, specActions, path, method } = this.props
|
|
||||||
const ContentType = getComponent( "contentType" )
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className="btn execute opblock-control__btn" onClick={ this.onClick }>
|
<button className="btn execute opblock-control__btn" onClick={ this.onClick }>
|
||||||
Execute
|
Execute
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class License extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
url ? <a href={ url }>{ name }</a>
|
url ? <a target="_blank" href={ url }>{ name }</a>
|
||||||
: <span>{ name }</span>
|
: <span>{ name }</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -95,7 +95,7 @@ export default class Info extends React.Component {
|
|||||||
{ version && <small><pre className="version"> { version } </pre></small> }
|
{ version && <small><pre className="version"> { version } </pre></small> }
|
||||||
</h2>
|
</h2>
|
||||||
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
|
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
|
||||||
{ url && <a href={ url }><span className="url"> { url } </span></a> }
|
{ url && <a target="_blank" href={ url }><span className="url"> { url } </span></a> }
|
||||||
</hgroup>
|
</hgroup>
|
||||||
|
|
||||||
<div className="description">
|
<div className="description">
|
||||||
@@ -104,7 +104,7 @@ export default class Info extends React.Component {
|
|||||||
|
|
||||||
{
|
{
|
||||||
termsOfService && <div>
|
termsOfService && <div>
|
||||||
<a href={ termsOfService }>Terms of service</a>
|
<a target="_blank" href={ termsOfService }>Terms of service</a>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import React, { PropTypes } from "react"
|
|||||||
import OriCollapse from "react-collapse"
|
import OriCollapse from "react-collapse"
|
||||||
import _Markdown from "react-remarkable"
|
import _Markdown from "react-remarkable"
|
||||||
|
|
||||||
const noop = () => {}
|
|
||||||
|
|
||||||
function xclass(...args) {
|
function xclass(...args) {
|
||||||
return args.filter(a => !!a).join(" ").trim()
|
return args.filter(a => !!a).join(" ").trim()
|
||||||
}
|
}
|
||||||
@@ -18,7 +16,7 @@ export class Container extends React.Component {
|
|||||||
if(fullscreen)
|
if(fullscreen)
|
||||||
return <section {...rest}/>
|
return <section {...rest}/>
|
||||||
|
|
||||||
let containerClass = "container" + (full ? "-full" : "")
|
let containerClass = "swagger-container" + (full ? "-full" : "")
|
||||||
return (
|
return (
|
||||||
<section {...rest} className={xclass(rest.className, containerClass)}/>
|
<section {...rest} className={xclass(rest.className, containerClass)}/>
|
||||||
)
|
)
|
||||||
@@ -44,12 +42,14 @@ export class Col extends React.Component {
|
|||||||
const {
|
const {
|
||||||
hide,
|
hide,
|
||||||
keepContents,
|
keepContents,
|
||||||
|
/* we don't want these in the `rest` object that passes to the final component,
|
||||||
mobile, /* we don't want these in the final component, since React now complains. So we extract them */
|
since React now complains. So we extract them */
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
mobile,
|
||||||
tablet,
|
tablet,
|
||||||
desktop,
|
desktop,
|
||||||
large,
|
large,
|
||||||
|
/* eslint-enable no-unused-vars */
|
||||||
...rest
|
...rest
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ export const Input = (props) => <input {...props} />
|
|||||||
|
|
||||||
export class Select extends React.Component {
|
export class Select extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
allowedValues: PropTypes.object,
|
allowedValues: PropTypes.array,
|
||||||
value: PropTypes.any,
|
value: PropTypes.any,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
multiple: PropTypes.bool,
|
multiple: PropTypes.bool,
|
||||||
|
|||||||
80
src/core/components/layouts/base.jsx
Normal file
80
src/core/components/layouts/base.jsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import React, { PropTypes } from "react"
|
||||||
|
|
||||||
|
export default class BaseLayout extends React.Component {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
errSelectors: PropTypes.object.isRequired,
|
||||||
|
errActions: PropTypes.object.isRequired,
|
||||||
|
specActions: PropTypes.object.isRequired,
|
||||||
|
specSelectors: PropTypes.object.isRequired,
|
||||||
|
layoutSelectors: PropTypes.object.isRequired,
|
||||||
|
layoutActions: PropTypes.object.isRequired,
|
||||||
|
getComponent: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let { specSelectors, specActions, getComponent } = this.props
|
||||||
|
|
||||||
|
let info = specSelectors.info()
|
||||||
|
let url = specSelectors.url()
|
||||||
|
let basePath = specSelectors.basePath()
|
||||||
|
let host = specSelectors.host()
|
||||||
|
let securityDefinitions = specSelectors.securityDefinitions()
|
||||||
|
let externalDocs = specSelectors.externalDocs()
|
||||||
|
let schemes = specSelectors.schemes()
|
||||||
|
|
||||||
|
let Info = getComponent("info")
|
||||||
|
let Operations = getComponent("operations", true)
|
||||||
|
let Models = getComponent("models", true)
|
||||||
|
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
||||||
|
let Row = getComponent("Row")
|
||||||
|
let Col = getComponent("Col")
|
||||||
|
let Errors = getComponent("errors", true)
|
||||||
|
const Schemes = getComponent("schemes")
|
||||||
|
|
||||||
|
const isSpecEmpty = !specSelectors.specStr()
|
||||||
|
|
||||||
|
if(isSpecEmpty) {
|
||||||
|
return <h4>No spec provided.</h4>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<div className='swagger-ui'>
|
||||||
|
<div>
|
||||||
|
<Errors/>
|
||||||
|
<Row className="information-container">
|
||||||
|
<Col mobile={12}>
|
||||||
|
{ info.count() ? (
|
||||||
|
<Info info={ info } url={ url } host={ host } basePath={ basePath } externalDocs={externalDocs} getComponent={getComponent}/>
|
||||||
|
) : null }
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
{ schemes && schemes.size || securityDefinitions ? (
|
||||||
|
<div className="scheme-container">
|
||||||
|
<Col className="schemes wrapper" mobile={12}>
|
||||||
|
{ schemes && schemes.size ? (
|
||||||
|
<Schemes schemes={ schemes } specActions={ specActions } />
|
||||||
|
) : null }
|
||||||
|
{ securityDefinitions ? (
|
||||||
|
<AuthorizeBtn />
|
||||||
|
) : null }
|
||||||
|
</Col>
|
||||||
|
</div>
|
||||||
|
) : null }
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col mobile={12} desktop={12} >
|
||||||
|
<Operations/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col mobile={12} desktop={12} >
|
||||||
|
<Models/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import React, { Component, PropTypes } from "react"
|
import React, { Component, PropTypes } from "react"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
import isObject from "lodash/isObject"
|
|
||||||
import { List } from "immutable"
|
import { List } from "immutable"
|
||||||
const braceOpen = "{"
|
const braceOpen = "{"
|
||||||
const braceClose = "}"
|
const braceClose = "}"
|
||||||
|
|
||||||
|
const propStyle = { color: "#999", fontStyle: "italic" }
|
||||||
|
|
||||||
const EnumModel = ({ value }) => {
|
const EnumModel = ({ value }) => {
|
||||||
let collapsedContent = <span>Array [ { value.count() } ]</span>
|
let collapsedContent = <span>Array [ { value.count() } ]</span>
|
||||||
return <span className="prop-enum">
|
return <span className="prop-enum">
|
||||||
@@ -128,10 +129,8 @@ class Primitive extends Component {
|
|||||||
let format = schema.get("format")
|
let format = schema.get("format")
|
||||||
let xml = schema.get("xml")
|
let xml = schema.get("xml")
|
||||||
let enumArray = schema.get("enum")
|
let enumArray = schema.get("enum")
|
||||||
let description = schema.get("description")
|
|
||||||
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "$$ref"].indexOf(key) === -1 )
|
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "$$ref"].indexOf(key) === -1 )
|
||||||
let style = required ? { fontWeight: "bold" } : {}
|
let style = required ? { fontWeight: "bold" } : {}
|
||||||
let propStyle = { color: "#999", fontStyle: "italic" }
|
|
||||||
|
|
||||||
return <span className="prop">
|
return <span className="prop">
|
||||||
<span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>}
|
<span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>}
|
||||||
@@ -169,12 +168,23 @@ class ArrayModel extends Component {
|
|||||||
render(){
|
render(){
|
||||||
let { required, schema, depth, expandDepth } = this.props
|
let { required, schema, depth, expandDepth } = this.props
|
||||||
let items = schema.get("items")
|
let items = schema.get("items")
|
||||||
|
let properties = schema.filter( ( v, key) => ["type", "items", "$$ref"].indexOf(key) === -1 )
|
||||||
|
|
||||||
return <span>
|
return <span className="model">
|
||||||
|
<span className="model-title">
|
||||||
|
<span className="model-title__text">{ schema.get("title") }</span>
|
||||||
|
</span>
|
||||||
<Collapse collapsed={ depth > expandDepth } collapsedContent="[...]">
|
<Collapse collapsed={ depth > expandDepth } collapsedContent="[...]">
|
||||||
[
|
[
|
||||||
<span><Model { ...this.props } schema={ items } required={ false }/></span>
|
<span><Model { ...this.props } schema={ items } required={ false }/></span>
|
||||||
]
|
]
|
||||||
|
{
|
||||||
|
properties.size ? <span>
|
||||||
|
{ properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={propStyle}>
|
||||||
|
<br />{ `${key}:`}{ String(v) }</span>)
|
||||||
|
}<br /></span>
|
||||||
|
: null
|
||||||
|
}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
{ required && <span style={{ color: "red" }}>*</span>}
|
{ required && <span style={{ color: "red" }}>*</span>}
|
||||||
</span>
|
</span>
|
||||||
@@ -251,9 +261,6 @@ export default class ModelComponent extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
let { name, schema } = this.props
|
|
||||||
let title = schema.get("title") || name
|
|
||||||
|
|
||||||
return <div className="model-box">
|
return <div className="model-box">
|
||||||
<Model { ...this.props } depth={ 1 } expandDepth={ this.props.expandDepth || 0 }/>
|
<Model { ...this.props } depth={ 1 } expandDepth={ this.props.expandDepth || 0 }/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ import React, { Component, PropTypes } from "react"
|
|||||||
export default class Models extends Component {
|
export default class Models extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
getComponent: PropTypes.func,
|
getComponent: PropTypes.func,
|
||||||
specSelectors: PropTypes.object
|
specSelectors: PropTypes.object,
|
||||||
|
layoutSelectors: PropTypes.object,
|
||||||
|
layoutActions: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
let { specSelectors, getComponent, layoutSelectors, layoutActions } = this.props
|
let { specSelectors, getComponent, layoutSelectors, layoutActions } = this.props
|
||||||
let definitions = specSelectors.definitions()
|
let definitions = specSelectors.definitions()
|
||||||
let showModels = layoutSelectors.isShown('models', true)
|
let showModels = layoutSelectors.isShown("models", true)
|
||||||
|
|
||||||
const Model = getComponent("model")
|
const Model = getComponent("model")
|
||||||
const Collapse = getComponent("Collapse")
|
const Collapse = getComponent("Collapse")
|
||||||
@@ -18,7 +20,7 @@ export default class Models extends Component {
|
|||||||
if (!definitions.size) return null
|
if (!definitions.size) return null
|
||||||
|
|
||||||
return <section className={ showModels ? "models is-open" : "models"}>
|
return <section className={ showModels ? "models is-open" : "models"}>
|
||||||
<h4 onClick={() => layoutActions.show('models', !showModels)}>
|
<h4 onClick={() => layoutActions.show("models", !showModels)}>
|
||||||
<span>Models</span>
|
<span>Models</span>
|
||||||
<svg width="20" height="20">
|
<svg width="20" height="20">
|
||||||
<use xlinkHref="#large-arrow" />
|
<use xlinkHref="#large-arrow" />
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import React from "react"
|
import React, { PropTypes } from "react"
|
||||||
|
|
||||||
export default class OnlineValidatorBadge extends React.Component {
|
export default class OnlineValidatorBadge extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
getComponent: PropTypes.func.isRequired,
|
||||||
|
getConfigs: PropTypes.func.isRequired,
|
||||||
|
specSelectors: PropTypes.object.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context)
|
super(props, context)
|
||||||
let { specSelectors, getConfigs } = props
|
let { specSelectors, getConfigs } = props
|
||||||
let { validatorUrl } = getConfigs()
|
let { validatorUrl } = getConfigs()
|
||||||
this.state = {
|
this.state = {
|
||||||
url: specSelectors.url(),
|
url: specSelectors.url(),
|
||||||
validatorUrl: validatorUrl
|
validatorUrl: validatorUrl === undefined ? "https://online.swagger.io/validator" : validatorUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,7 +23,7 @@ export default class OnlineValidatorBadge extends React.Component {
|
|||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
url: specSelectors.url(),
|
url: specSelectors.url(),
|
||||||
validatorUrl: validatorUrl
|
validatorUrl: validatorUrl === undefined ? "https://online.swagger.io/validator" : validatorUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,14 +33,72 @@ export default class OnlineValidatorBadge extends React.Component {
|
|||||||
|
|
||||||
if ( typeof spec === "object" && Object.keys(spec).length) return null
|
if ( typeof spec === "object" && Object.keys(spec).length) return null
|
||||||
|
|
||||||
if (!this.state.url) {
|
if (!this.state.url || !this.state.validatorUrl || this.state.url.indexOf("localhost") >= 0
|
||||||
|
|| this.state.url.indexOf("127.0.0.1") >= 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<span style={{ float: "right"}}>
|
return (<span style={{ float: "right"}}>
|
||||||
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}>
|
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}>
|
||||||
<img alt="Online validator badge" src={`${ this.state.validatorUrl }?url=${ this.state.url }`} />
|
<ValidatorImage src={`${ this.state.validatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
|
||||||
</a>
|
</a>
|
||||||
</span>)
|
</span>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ValidatorImage extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
src: PropTypes.string,
|
||||||
|
alt: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
loaded: false,
|
||||||
|
error: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const img = new Image()
|
||||||
|
img.onload = () => {
|
||||||
|
this.setState({
|
||||||
|
loaded: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
img.onerror = () => {
|
||||||
|
this.setState({
|
||||||
|
error: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
img.src = this.props.src
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.src !== this.props.src) {
|
||||||
|
const img = new Image()
|
||||||
|
img.onload = () => {
|
||||||
|
this.setState({
|
||||||
|
loaded: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
img.onerror = () => {
|
||||||
|
this.setState({
|
||||||
|
error: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
img.src = nextProps.src
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.error) {
|
||||||
|
return <img alt={"Error"} />
|
||||||
|
} else if (!this.state.loaded) {
|
||||||
|
return <img alt= {"Loading..."} />
|
||||||
|
}
|
||||||
|
return <img src={this.props.src} alt={this.props.alt} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { PropTypes } from "react"
|
import React, { PropTypes } from "react"
|
||||||
import { Map, fromJS } from "immutable"
|
|
||||||
import shallowCompare from "react-addons-shallow-compare"
|
import shallowCompare from "react-addons-shallow-compare"
|
||||||
import { getList } from "core/utils"
|
import { getList } from "core/utils"
|
||||||
import * as CustomPropTypes from "core/proptypes"
|
import * as CustomPropTypes from "core/proptypes"
|
||||||
@@ -112,9 +111,7 @@ export default class Operation extends React.Component {
|
|||||||
specActions,
|
specActions,
|
||||||
specSelectors,
|
specSelectors,
|
||||||
authActions,
|
authActions,
|
||||||
authSelectors,
|
authSelectors
|
||||||
layoutSelectors,
|
|
||||||
layoutActions,
|
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
let summary = operation.get("summary")
|
let summary = operation.get("summary")
|
||||||
@@ -205,11 +202,12 @@ export default class Operation extends React.Component {
|
|||||||
pathMethod={ [path, method] }
|
pathMethod={ [path, method] }
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!tryItOutEnabled || !allowTryItOut ? null : schemes && schemes.size ? <Schemes schemes={ schemes }
|
{!tryItOutEnabled || !allowTryItOut ? null : schemes && schemes.size ? <div className="opblock-schemes">
|
||||||
|
<Schemes schemes={ schemes }
|
||||||
path={ path }
|
path={ path }
|
||||||
method={ method }
|
method={ method }
|
||||||
specActions={ specActions }/>
|
specActions={ specActions }/>
|
||||||
: null
|
</div> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className={(!tryItOutEnabled || !response || !allowTryItOut) ? "execute-wrapper" : "btn-group"}>
|
<div className={(!tryItOutEnabled || !response || !allowTryItOut) ? "execute-wrapper" : "btn-group"}>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { PropTypes } from "react"
|
import React, { PropTypes } from "react"
|
||||||
import {presets} from "react-motion"
|
|
||||||
|
|
||||||
export default class Operations extends React.Component {
|
export default class Operations extends React.Component {
|
||||||
|
|
||||||
@@ -33,7 +32,6 @@ export default class Operations extends React.Component {
|
|||||||
|
|
||||||
const Operation = getComponent("operation")
|
const Operation = getComponent("operation")
|
||||||
const Collapse = getComponent("Collapse")
|
const Collapse = getComponent("Collapse")
|
||||||
const Schemes = getComponent("schemes")
|
|
||||||
|
|
||||||
let showSummary = layoutSelectors.showSummary()
|
let showSummary = layoutSelectors.showSummary()
|
||||||
|
|
||||||
@@ -58,12 +56,6 @@ export default class Operations extends React.Component {
|
|||||||
</small>
|
</small>
|
||||||
}
|
}
|
||||||
|
|
||||||
<button className="expand-methods" title="Expand all methods">
|
|
||||||
<svg className="expand" width="20" height="20">
|
|
||||||
<use xlinkHref="#expand" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button className="expand-operation" title="Expand operation" onClick={() => layoutActions.show(isShownKey, !showTag)}>
|
<button className="expand-operation" title="Expand operation" onClick={() => layoutActions.show(isShownKey, !showTag)}>
|
||||||
<svg className="arrow" width="20" height="20">
|
<svg className="arrow" width="20" height="20">
|
||||||
<use xlinkHref={showTag ? "#large-arrow-down" : "#large-arrow"} />
|
<use xlinkHref={showTag ? "#large-arrow-down" : "#large-arrow"} />
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ export default class Overview extends React.Component {
|
|||||||
{
|
{
|
||||||
taggedOps.map( (tagObj, tag) => {
|
taggedOps.map( (tagObj, tag) => {
|
||||||
let operations = tagObj.get("operations")
|
let operations = tagObj.get("operations")
|
||||||
let tagDetails = tagObj.get("tagDetails")
|
|
||||||
|
|
||||||
let showTagId = ["overview-tags", tag]
|
let showTagId = ["overview-tags", tag]
|
||||||
let showTag = layoutSelectors.isShown(showTagId, true)
|
let showTag = layoutSelectors.isShown(showTagId, true)
|
||||||
@@ -45,7 +44,7 @@ export default class Overview extends React.Component {
|
|||||||
<Collapse isOpened={showTag} animated>
|
<Collapse isOpened={showTag} animated>
|
||||||
{
|
{
|
||||||
operations.map( op => {
|
operations.map( op => {
|
||||||
let { path, method, operation, id } = op.toObject() // toObject is shallow
|
let { path, method, id } = op.toObject() // toObject is shallow
|
||||||
let showOpIdPrefix = "operations"
|
let showOpIdPrefix = "operations"
|
||||||
let showOpId = id
|
let showOpId = id
|
||||||
let shown = layoutSelectors.isShown([showOpIdPrefix, showOpId])
|
let shown = layoutSelectors.isShown([showOpIdPrefix, showOpId])
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { Component, PropTypes } from "react"
|
import React, { Component, PropTypes } from "react"
|
||||||
import shallowCompare from "react-addons-shallow-compare"
|
import shallowCompare from "react-addons-shallow-compare"
|
||||||
import { Set, fromJS, List } from "immutable"
|
import { fromJS, List } from "immutable"
|
||||||
import { getSampleSchema } from "core/utils"
|
import { getSampleSchema } from "core/utils"
|
||||||
|
|
||||||
const NOOP = Function.prototype
|
const NOOP = Function.prototype
|
||||||
@@ -50,14 +50,15 @@ export default class ParamBody extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateValues = (props) => {
|
updateValues = (props) => {
|
||||||
let { specSelectors, pathMethod, param, isExecute, consumesValue="", onChangeConsumes } = props
|
let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props
|
||||||
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name")) : {}
|
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name")) : {}
|
||||||
let isXml = /xml/i.test(consumesValue)
|
let isXml = /xml/i.test(consumesValue)
|
||||||
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")
|
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")
|
||||||
|
|
||||||
if ( paramValue ) {
|
if ( paramValue !== undefined ) {
|
||||||
this.setState({ value: paramValue })
|
let val = !paramValue && !isXml ? "{}" : paramValue
|
||||||
this.onChange(paramValue, {isXml: isXml, isEditBox: isExecute})
|
this.setState({ value: val })
|
||||||
|
this.onChange(val, {isXml: isXml, isEditBox: isExecute})
|
||||||
} else {
|
} else {
|
||||||
if (isXml) {
|
if (isXml) {
|
||||||
this.onChange(this.sample("xml"), {isXml: isXml, isEditBox: isExecute})
|
this.onChange(this.sample("xml"), {isXml: isXml, isEditBox: isExecute})
|
||||||
|
|||||||
@@ -28,11 +28,25 @@ export default class ParameterRow extends Component {
|
|||||||
|
|
||||||
componentWillReceiveProps(props) {
|
componentWillReceiveProps(props) {
|
||||||
let { specSelectors, pathMethod, param } = props
|
let { specSelectors, pathMethod, param } = props
|
||||||
|
let example = param.get("example")
|
||||||
let defaultValue = param.get("default")
|
let defaultValue = param.get("default")
|
||||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"))
|
let parameter = specSelectors.getParameter(pathMethod, param.get("name"))
|
||||||
let value = parameter ? parameter.get("value") : ""
|
let paramValue = parameter ? parameter.get("value") : undefined
|
||||||
if ( defaultValue !== undefined && value === undefined ) {
|
let enumValue = parameter ? parameter.get("enum") : undefined
|
||||||
this.onChangeWrapper(defaultValue)
|
let value
|
||||||
|
|
||||||
|
if ( paramValue !== undefined ) {
|
||||||
|
value = paramValue
|
||||||
|
} else if ( example !== undefined ) {
|
||||||
|
value = example
|
||||||
|
} else if ( defaultValue !== undefined) {
|
||||||
|
value = defaultValue
|
||||||
|
} else if ( param.get("required") && enumValue && enumValue.size ) {
|
||||||
|
value = enumValue.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( value !== undefined ) {
|
||||||
|
this.onChangeWrapper(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { Component, PropTypes } from "react"
|
import React, { Component, PropTypes } from "react"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
import Im, { fromJS } from "immutable"
|
import Im from "immutable"
|
||||||
|
|
||||||
// More readable, just iterate over maps, only
|
// More readable, just iterate over maps, only
|
||||||
const eachMap = (iterable, fn) => iterable.valueSeq().filter(Im.Map.isMap).map(fn)
|
const eachMap = (iterable, fn) => iterable.valueSeq().filter(Im.Map.isMap).map(fn)
|
||||||
@@ -87,7 +87,7 @@ export default class Parameters extends Component {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
eachMap(parameters, (parameter, k) => (
|
eachMap(parameters, (parameter) => (
|
||||||
<ParameterRow fn={ fn }
|
<ParameterRow fn={ fn }
|
||||||
getComponent={ getComponent }
|
getComponent={ getComponent }
|
||||||
param={ parameter }
|
param={ parameter }
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
import React, { PropTypes } from "react"
|
import React, { PropTypes } from "react"
|
||||||
import { fromJS } from 'immutable'
|
import { fromJS } from "immutable"
|
||||||
import { getSampleSchema } from "core/utils"
|
import { getSampleSchema } from "core/utils"
|
||||||
|
|
||||||
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
||||||
if ( examples && examples.size ) {
|
if ( examples && examples.size ) {
|
||||||
return examples.entrySeq().map( ([ key, example ]) => {
|
return examples.entrySeq().map( ([ key, example ]) => {
|
||||||
|
let exampleValue
|
||||||
|
try {
|
||||||
|
exampleValue = example && example.toJS ? example.toJS() : example
|
||||||
|
exampleValue = JSON.stringify(exampleValue)
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
exampleValue = String(example)
|
||||||
|
}
|
||||||
return (<div key={ key }>
|
return (<div key={ key }>
|
||||||
<h5>{ key }</h5>
|
<h5>{ key }</h5>
|
||||||
<HighlightCode className="example" value={ example } />
|
<HighlightCode className="example" value={ exampleValue } />
|
||||||
</div>)
|
</div>)
|
||||||
}).toArray()
|
}).toArray()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ export default class Schemes extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onChange =( e ) => {
|
onChange =( e ) => {
|
||||||
let { path, method, specActions } = this.props
|
|
||||||
|
|
||||||
this.setScheme( e.target.value )
|
this.setScheme( e.target.value )
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ export default class Schemes extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<label htmlFor="schemes">
|
<label htmlFor="schemes">
|
||||||
<span>Schemes</span>
|
<span className="schemes-title">Schemes</span>
|
||||||
<select onChange={ this.onChange }>
|
<select onChange={ this.onChange }>
|
||||||
{ schemes.valueSeq().map(
|
{ schemes.valueSeq().map(
|
||||||
( scheme ) => <option value={ scheme } key={ scheme }>{ scheme }</option>
|
( scheme ) => <option value={ scheme } key={ scheme }>{ scheme }</option>
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ export default class TryItOutButton extends React.Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onTryoutClick: PropTypes.func,
|
onTryoutClick: PropTypes.func,
|
||||||
|
onCancelClick: PropTypes.func,
|
||||||
enabled: PropTypes.bool, // Try it out is enabled, ie: the user has access to the form
|
enabled: PropTypes.bool, // Try it out is enabled, ie: the user has access to the form
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onTryoutClick: Function.prototype,
|
onTryoutClick: Function.prototype,
|
||||||
|
onCancelClick: Function.prototype,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function curl( request ){
|
|||||||
let headers = request.get("headers")
|
let headers = request.get("headers")
|
||||||
curlified.push( "curl" )
|
curlified.push( "curl" )
|
||||||
curlified.push( "-X", request.get("method") )
|
curlified.push( "-X", request.get("method") )
|
||||||
curlified.push( request.get("url") )
|
curlified.push( `"${request.get("url")}"`)
|
||||||
|
|
||||||
if ( headers && headers.size ) {
|
if ( headers && headers.size ) {
|
||||||
for( let p of request.get("headers").entries() ){
|
for( let p of request.get("headers").entries() ){
|
||||||
|
|||||||
@@ -1,21 +1,32 @@
|
|||||||
import deepExtend from "deep-extend"
|
import deepExtend from "deep-extend"
|
||||||
|
|
||||||
import System from "core/system"
|
import System from "core/system"
|
||||||
|
import win from "core/window"
|
||||||
import ApisPreset from "core/presets/apis"
|
import ApisPreset from "core/presets/apis"
|
||||||
import * as AllPlugins from "core/plugins/all"
|
import * as AllPlugins from "core/plugins/all"
|
||||||
import { filterConfigs } from "plugins/configs"
|
import { parseSeach, filterConfigs } from "core/utils"
|
||||||
|
|
||||||
|
const CONFIGS = [ "url", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion",
|
||||||
|
"apisSorter", "operationsSorter", "supportedSubmitMethods", "highlightSizeThreshold", "dom_id",
|
||||||
|
"defaultModelRendering", "oauth2RedirectUrl", "showRequestHeaders", "custom" ]
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const { GIT_DIRTY, GIT_COMMIT, PACKAGE_VERSION } = buildInfo
|
||||||
|
|
||||||
module.exports = function SwaggerUI(opts) {
|
module.exports = function SwaggerUI(opts) {
|
||||||
|
|
||||||
|
win.versions = win.versions || {}
|
||||||
|
win.versions.swaggerUi = `${PACKAGE_VERSION}/${GIT_COMMIT || "unknown"}${GIT_DIRTY ? "-dirty" : ""}`
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
// Some general settings, that we floated to the top
|
// Some general settings, that we floated to the top
|
||||||
dom_id: null,
|
dom_id: null,
|
||||||
spec: {},
|
spec: {},
|
||||||
url: "",
|
url: "",
|
||||||
layout: "Layout",
|
layout: "BaseLayout",
|
||||||
configs: {
|
validatorUrl: "https://online.swagger.io/validator",
|
||||||
validatorUrl: "https://online.swagger.io/validator"
|
configs: {},
|
||||||
},
|
custom: {},
|
||||||
|
|
||||||
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
|
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
|
||||||
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
|
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
|
||||||
@@ -35,79 +46,75 @@ module.exports = function SwaggerUI(opts) {
|
|||||||
store: { },
|
store: { },
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = deepExtend({}, defaults, opts)
|
const constructorConfig = deepExtend({}, defaults, opts)
|
||||||
|
|
||||||
const storeConfigs = deepExtend({}, config.store, {
|
const storeConfigs = deepExtend({}, constructorConfig.store, {
|
||||||
system: {
|
system: {
|
||||||
configs: config.configs
|
configs: constructorConfig.configs
|
||||||
},
|
},
|
||||||
plugins: config.presets,
|
plugins: constructorConfig.presets,
|
||||||
state: {
|
state: {
|
||||||
layout: {
|
layout: {
|
||||||
layout: config.layout
|
layout: constructorConfig.layout
|
||||||
},
|
},
|
||||||
spec: {
|
spec: {
|
||||||
spec: "",
|
spec: "",
|
||||||
url: config.url
|
url: constructorConfig.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let inlinePlugin = ()=> {
|
let inlinePlugin = ()=> {
|
||||||
return {
|
return {
|
||||||
fn: config.fn,
|
fn: constructorConfig.fn,
|
||||||
components: config.components,
|
components: constructorConfig.components,
|
||||||
state: config.state,
|
state: constructorConfig.state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var store = new System(storeConfigs)
|
var store = new System(storeConfigs)
|
||||||
store.register([config.plugins, inlinePlugin])
|
store.register([constructorConfig.plugins, inlinePlugin])
|
||||||
|
|
||||||
var system = store.getSystem()
|
var system = store.getSystem()
|
||||||
|
let queryConfig = parseSeach()
|
||||||
|
|
||||||
const downloadSpec = (configs) => {
|
system.initOAuth = system.authActions.configureAuth
|
||||||
if(typeof config !== "object") {
|
|
||||||
|
const downloadSpec = (fetchedConfig) => {
|
||||||
|
if(typeof constructorConfig !== "object") {
|
||||||
return system
|
return system
|
||||||
}
|
}
|
||||||
|
|
||||||
let localConfig = system.specSelectors.getLocalConfig ? system.specSelectors.getLocalConfig() : {}
|
let localConfig = system.specSelectors.getLocalConfig ? system.specSelectors.getLocalConfig() : {}
|
||||||
let mergedConfig = deepExtend({}, config, configs, localConfig)
|
let mergedConfig = deepExtend({}, localConfig, constructorConfig, fetchedConfig || {}, queryConfig)
|
||||||
store.setConfigs(filterConfigs(mergedConfig))
|
store.setConfigs(filterConfigs(mergedConfig, CONFIGS))
|
||||||
|
|
||||||
if(typeof mergedConfig.spec === "object" && Object.keys(mergedConfig.spec).length) {
|
if (fetchedConfig !== null) {
|
||||||
|
if (!queryConfig.url && typeof mergedConfig.spec === "object" && Object.keys(mergedConfig.spec).length) {
|
||||||
system.specActions.updateUrl("")
|
system.specActions.updateUrl("")
|
||||||
system.specActions.updateLoadingStatus("success");
|
system.specActions.updateLoadingStatus("success")
|
||||||
system.specActions.updateSpec(JSON.stringify(mergedConfig.spec))
|
system.specActions.updateSpec(JSON.stringify(mergedConfig.spec))
|
||||||
} else if(mergedConfig.url) {
|
} else if (system.specActions.download && mergedConfig.url) {
|
||||||
system.specActions.updateUrl(mergedConfig.url)
|
system.specActions.updateUrl(mergedConfig.url)
|
||||||
system.specActions.download(mergedConfig.url)
|
system.specActions.download(mergedConfig.url)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(mergedConfig.dom_id)
|
if(mergedConfig.dom_id) {
|
||||||
system.render(mergedConfig.dom_id, "App")
|
system.render(mergedConfig.dom_id, "App")
|
||||||
|
|
||||||
return system
|
|
||||||
}
|
|
||||||
|
|
||||||
if (system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl(downloadSpec)) {
|
|
||||||
return downloadSpec(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (system.specActions.download && config.url) {
|
|
||||||
system.specActions.download(config.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config.spec && typeof config.spec === "string")
|
|
||||||
system.specActions.updateSpec(config.spec)
|
|
||||||
|
|
||||||
if(config.dom_id) {
|
|
||||||
system.render(config.dom_id, "App")
|
|
||||||
} else {
|
} else {
|
||||||
console.error("Skipped rendering: no `dom_id` was specified")
|
console.error("Skipped rendering: no `dom_id` was specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
return system
|
return system
|
||||||
|
}
|
||||||
|
|
||||||
|
let configUrl = queryConfig.config || constructorConfig.configUrl
|
||||||
|
|
||||||
|
if (!configUrl || !system.specActions.getConfigByUrl || system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl(configUrl, downloadSpec)) {
|
||||||
|
return downloadSpec()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add presets
|
// Add presets
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import React, { PropTypes, Component } from "react"
|
import React, { PropTypes, Component } from "react"
|
||||||
import { arrayify } from "core/utils"
|
|
||||||
import shallowCompare from "react-addons-shallow-compare"
|
import shallowCompare from "react-addons-shallow-compare"
|
||||||
import { List, fromJS } from "immutable"
|
import { List, fromJS } from "immutable"
|
||||||
import assign from "object-assign"
|
|
||||||
//import "less/json-schema-form"
|
//import "less/json-schema-form"
|
||||||
|
|
||||||
const noop = ()=> {}
|
const noop = ()=> {}
|
||||||
@@ -53,7 +51,7 @@ export class JsonSchema_string extends Component {
|
|||||||
}
|
}
|
||||||
onEnumChange = (val) => this.props.onChange(val)
|
onEnumChange = (val) => this.props.onChange(val)
|
||||||
render() {
|
render() {
|
||||||
let { getComponent, value, schema, fn, required, description } = this.props
|
let { getComponent, value, schema, required, description } = this.props
|
||||||
let enumValue = schema["enum"]
|
let enumValue = schema["enum"]
|
||||||
let errors = schema.errors || []
|
let errors = schema.errors || []
|
||||||
|
|
||||||
@@ -71,7 +69,7 @@ export class JsonSchema_string extends Component {
|
|||||||
return <Input type="file" className={ errors.length ? "invalid" : ""} onChange={ this.onChange } disabled={isDisabled}/>
|
return <Input type="file" className={ errors.length ? "invalid" : ""} onChange={ this.onChange } disabled={isDisabled}/>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return <Input type="text" className={ errors.length ? "invalid" : ""} value={value} placeholder={description} onChange={ this.onChange } disabled={isDisabled}/>
|
return <Input type={ schema.format === "password" ? "password" : "text" } className={ errors.length ? "invalid" : ""} value={value} placeholder={description} onChange={ this.onChange } disabled={isDisabled}/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,13 +117,13 @@ export class JsonSchema_array extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onEnumChange = (value) => {
|
onEnumChange = (value) => {
|
||||||
this.setState(state => ({
|
this.setState(() => ({
|
||||||
value: value
|
value: value
|
||||||
}), this.onChange)
|
}), this.onChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { getComponent, onChange, required, schema, fn } = this.props
|
let { getComponent, required, schema, fn } = this.props
|
||||||
|
|
||||||
let itemSchema = fn.inferSchema(schema.items)
|
let itemSchema = fn.inferSchema(schema.items)
|
||||||
|
|
||||||
@@ -152,9 +150,9 @@ export class JsonSchema_array extends Component {
|
|||||||
(errors.length ? <span style={{ color: "red", fortWeight: "bold" }}>{ errors[0] }</span> : null) :
|
(errors.length ? <span style={{ color: "red", fortWeight: "bold" }}>{ errors[0] }</span> : null) :
|
||||||
value.map( (item,i) => {
|
value.map( (item,i) => {
|
||||||
let schema = Object.assign({}, itemSchema)
|
let schema = Object.assign({}, itemSchema)
|
||||||
|
if ( errors.length ) {
|
||||||
let err = errors.filter((err) => err.index === i)
|
let err = errors.filter((err) => err.index === i)
|
||||||
if ( err.length ) {
|
if (err.length) schema.errors = [ err[0].error + i ]
|
||||||
schema.errors = [ err[0].error + i ]
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={i} className="json-schema-form-item">
|
<div key={i} className="json-schema-form-item">
|
||||||
|
|||||||
@@ -1,21 +1,37 @@
|
|||||||
import win from "core/window"
|
import win from "core/window"
|
||||||
|
import { btoa } from "core/utils"
|
||||||
|
|
||||||
export default function authorize ( auth, authActions, errActions, configs ) {
|
export default function authorize ( { auth, authActions, errActions, configs, authConfigs={} } ) {
|
||||||
let { schema, scopes, name, clientId } = auth
|
let { schema, scopes, name, clientId } = auth
|
||||||
|
|
||||||
let redirectUrl = configs.oauth2RedirectUrl
|
|
||||||
let scopeSeparator = " "
|
|
||||||
let state = name
|
|
||||||
let flow = schema.get("flow")
|
let flow = schema.get("flow")
|
||||||
let url
|
let query = []
|
||||||
|
|
||||||
if (flow === "password") {
|
switch (flow) {
|
||||||
|
case "password":
|
||||||
authActions.authorizePassword(auth)
|
authActions.authorizePassword(auth)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case "application":
|
||||||
|
authActions.authorizeApplication(auth)
|
||||||
|
return
|
||||||
|
|
||||||
|
case "accessCode":
|
||||||
|
query.push("response_type=code")
|
||||||
|
break
|
||||||
|
|
||||||
|
case "implicit":
|
||||||
|
query.push("response_type=token")
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof clientId === "string") {
|
||||||
|
query.push("client_id=" + encodeURIComponent(clientId))
|
||||||
|
}
|
||||||
|
|
||||||
|
let redirectUrl = configs.oauth2RedirectUrl
|
||||||
|
|
||||||
// todo move to parser
|
// todo move to parser
|
||||||
if ( !redirectUrl ) {
|
if (typeof redirectUrl === "undefined") {
|
||||||
errActions.newAuthErr( {
|
errActions.newAuthErr( {
|
||||||
authId: name,
|
authId: name,
|
||||||
source: "validation",
|
source: "validation",
|
||||||
@@ -24,22 +40,39 @@ export default function authorize ( auth, authActions, errActions, configs ) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
query.push("redirect_uri=" + encodeURIComponent(redirectUrl))
|
||||||
|
|
||||||
if (flow === "implicit" || flow === "accessCode") {
|
if (Array.isArray(scopes) && 0 < scopes.length) {
|
||||||
url = schema.get("authorizationUrl") + "?response_type=" + (flow === "implicit" ? "token" : "code")
|
let scopeSeparator = authConfigs.scopeSeparator || " "
|
||||||
|
|
||||||
|
query.push("scope=" + encodeURIComponent(scopes.join(scopeSeparator)))
|
||||||
}
|
}
|
||||||
|
|
||||||
url += "&redirect_uri=" + encodeURIComponent(redirectUrl)
|
let state = btoa(new Date())
|
||||||
+ "&scope=" + encodeURIComponent(scopes.join(scopeSeparator))
|
|
||||||
+ "&state=" + encodeURIComponent(state)
|
query.push("state=" + encodeURIComponent(state))
|
||||||
+ "&client_id=" + encodeURIComponent(clientId)
|
|
||||||
|
if (typeof authConfigs.realm !== "undefined") {
|
||||||
|
query.push("realm=" + encodeURIComponent(authConfigs.realm))
|
||||||
|
}
|
||||||
|
|
||||||
|
let { additionalQueryStringParams } = authConfigs
|
||||||
|
|
||||||
|
for (let key in additionalQueryStringParams) {
|
||||||
|
if (typeof additionalQueryStringParams[key] !== "undefined") {
|
||||||
|
query.push([key, additionalQueryStringParams[key]].map(encodeURIComponent).join("="))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = [schema.get("authorizationUrl"), query.join("&")].join("?")
|
||||||
|
|
||||||
// pass action authorizeOauth2 and authentication data through window
|
// pass action authorizeOauth2 and authentication data through window
|
||||||
// to authorize with oauth2
|
// to authorize with oauth2
|
||||||
win.swaggerUIRedirectOauth2 = {
|
win.swaggerUIRedirectOauth2 = {
|
||||||
auth: auth,
|
auth: auth,
|
||||||
state: state,
|
state: state,
|
||||||
callback: authActions.preAuthorizeOauth2,
|
redirectUrl: redirectUrl,
|
||||||
|
callback: flow === "implicit" ? authActions.preAuthorizeImplicit : authActions.authorizeAccessCode,
|
||||||
errCb: errActions.newAuthErr
|
errCb: errActions.newAuthErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export function transformPathToArray(property, jsSpec) {
|
|||||||
return a.concat(b)
|
return a.concat(b)
|
||||||
}, [])
|
}, [])
|
||||||
.concat([""]) // add an empty item into the array, so we don't get stuck with something in our buffer below
|
.concat([""]) // add an empty item into the array, so we don't get stuck with something in our buffer below
|
||||||
.reduce((buffer, curr, i, arr) => {
|
.reduce((buffer, curr) => {
|
||||||
let obj = pathArr.length ? get(jsSpec, pathArr) : jsSpec
|
let obj = pathArr.length ? get(jsSpec, pathArr) : jsSpec
|
||||||
|
|
||||||
if(get(obj, makeAccessArray(buffer, curr))) {
|
if(get(obj, makeAccessArray(buffer, curr))) {
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import React, { PropTypes } from "react"
|
|
||||||
|
|
||||||
export default function (system) {
|
|
||||||
return {
|
|
||||||
components: {
|
|
||||||
NoHostWarning,
|
|
||||||
},
|
|
||||||
statePlugins: {
|
|
||||||
spec: {
|
|
||||||
selectors: {
|
|
||||||
allowTryItOutFor,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a quick style. How do we improve this?
|
|
||||||
const style = {
|
|
||||||
backgroundColor: "#e7f0f7",
|
|
||||||
padding: "1rem",
|
|
||||||
borderRadius: "3px",
|
|
||||||
}
|
|
||||||
|
|
||||||
function NoHostWarning() {
|
|
||||||
return (
|
|
||||||
<div style={style}>Note: The interactive forms are disabled, as no `host` property was found in the specification. Please see: <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object" target="_blank">OAI 2.0/#swagger-object</a></div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only allow if, there is a host field
|
|
||||||
function allowTryItOutFor(state) {
|
|
||||||
return ({specSelectors}) => {
|
|
||||||
return specSelectors.hasHost(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -277,8 +277,6 @@ export let getLineNumberForPathAsync = promisifySyncFn(getLineNumberForPath)
|
|||||||
|
|
||||||
function promisifySyncFn(fn) {
|
function promisifySyncFn(fn) {
|
||||||
return function(...args) {
|
return function(...args) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise((resolve) => resolve(fn(...args)))
|
||||||
resolve(fn(...args))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import win from "core/window"
|
import win from "core/window"
|
||||||
import btoa from "btoa"
|
import { btoa, buildFormData } from "core/utils"
|
||||||
|
|
||||||
export const SHOW_AUTH_POPUP = "show_popup"
|
export const SHOW_AUTH_POPUP = "show_popup"
|
||||||
export const AUTHORIZE = "authorize"
|
export const AUTHORIZE = "authorize"
|
||||||
@@ -7,6 +7,9 @@ export const LOGOUT = "logout"
|
|||||||
export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2"
|
export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2"
|
||||||
export const AUTHORIZE_OAUTH2 = "authorize_oauth2"
|
export const AUTHORIZE_OAUTH2 = "authorize_oauth2"
|
||||||
export const VALIDATE = "validate"
|
export const VALIDATE = "validate"
|
||||||
|
export const CONFIGURE_AUTH = "configure_auth"
|
||||||
|
|
||||||
|
const scopeSeparator = " "
|
||||||
|
|
||||||
export function showDefinitions(payload) {
|
export function showDefinitions(payload) {
|
||||||
return {
|
return {
|
||||||
@@ -29,7 +32,7 @@ export function logout(payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const preAuthorizeOauth2 = (payload) => ( { authActions, errActions } ) => {
|
export const preAuthorizeImplicit = (payload) => ( { authActions, errActions } ) => {
|
||||||
let { auth , token, isValid } = payload
|
let { auth , token, isValid } = payload
|
||||||
let { schema, name } = auth
|
let { schema, name } = auth
|
||||||
let flow = schema.get("flow")
|
let flow = schema.get("flow")
|
||||||
@@ -66,28 +69,83 @@ export function authorizeOauth2(payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
|
export const authorizePassword = ( auth ) => ( { authActions } ) => {
|
||||||
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
||||||
let req = {
|
let form = {
|
||||||
url: schema.get("tokenUrl"),
|
|
||||||
method: "post",
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/x-www-form-urlencoded"
|
|
||||||
},
|
|
||||||
query: {
|
|
||||||
grant_type: "password",
|
grant_type: "password",
|
||||||
username,
|
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
||||||
password
|
}
|
||||||
|
let query = {}
|
||||||
|
let headers = {}
|
||||||
|
|
||||||
|
if ( passwordType === "basic") {
|
||||||
|
headers.Authorization = "Basic " + btoa(username + ":" + password)
|
||||||
|
} else {
|
||||||
|
Object.assign(form, {username}, {password})
|
||||||
|
|
||||||
|
if ( passwordType === "query") {
|
||||||
|
if ( clientId ) {
|
||||||
|
query.client_id = clientId
|
||||||
|
}
|
||||||
|
if ( clientSecret ) {
|
||||||
|
query.client_secret = clientSecret
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Object.assign(form, {client_id: clientId}, {client_secret: clientSecret})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( passwordType === "basic") {
|
return authActions.authorizeRequest({ body: buildFormData(form), url: schema.get("tokenUrl"), name, headers, query, auth})
|
||||||
req.headers.authorization = "Basic " + btoa(clientId + ":" + clientSecret)
|
}
|
||||||
} else if ( passwordType === "request") {
|
|
||||||
req.query = Object.assign(req.query, { client_id: clientId, client_secret: clientSecret })
|
export const authorizeApplication = ( auth ) => ( { authActions } ) => {
|
||||||
|
let { schema, scopes, name, clientId, clientSecret } = auth
|
||||||
|
let form = {
|
||||||
|
grant_type: "client_credentials",
|
||||||
|
client_id: clientId,
|
||||||
|
client_secret: clientSecret,
|
||||||
|
scope: scopes.join(scopeSeparator)
|
||||||
}
|
}
|
||||||
return fn.fetch(req)
|
|
||||||
.then(( response ) => {
|
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const authorizeAccessCode = ( { auth, redirectUrl } ) => ( { authActions } ) => {
|
||||||
|
let { schema, name, clientId, clientSecret } = auth
|
||||||
|
let form = {
|
||||||
|
grant_type: "authorization_code",
|
||||||
|
code: auth.code,
|
||||||
|
client_id: clientId,
|
||||||
|
client_secret: clientSecret,
|
||||||
|
redirect_uri: redirectUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const authorizeRequest = ( data ) => ( { fn, authActions, errActions, authSelectors } ) => {
|
||||||
|
let { body, query={}, headers={}, name, url, auth } = data
|
||||||
|
let { additionalQueryStringParams } = authSelectors.getConfigs() || {}
|
||||||
|
let fetchUrl = url
|
||||||
|
|
||||||
|
for (let key in additionalQueryStringParams) {
|
||||||
|
url += "&" + key + "=" + encodeURIComponent(additionalQueryStringParams[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
let _headers = Object.assign({
|
||||||
|
"Accept":"application/json, text/plain, */*",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
}, headers)
|
||||||
|
|
||||||
|
fn.fetch({
|
||||||
|
url: fetchUrl,
|
||||||
|
method: "post",
|
||||||
|
headers: _headers,
|
||||||
|
query: query,
|
||||||
|
body: body
|
||||||
|
})
|
||||||
|
.then(function (response) {
|
||||||
let token = JSON.parse(response.data)
|
let token = JSON.parse(response.data)
|
||||||
let error = token && ( token.error || "" )
|
let error = token && ( token.error || "" )
|
||||||
let parseError = token && ( token.parseError || "" )
|
let parseError = token && ( token.parseError || "" )
|
||||||
@@ -112,7 +170,22 @@ export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } )
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
authActions.authorizeOauth2({ auth, token })
|
authActions.authorizeOauth2({ auth, token})
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
let err = new Error(e)
|
||||||
|
errActions.newAuthErr( {
|
||||||
|
authId: name,
|
||||||
|
level: "error",
|
||||||
|
source: "auth",
|
||||||
|
message: err.message
|
||||||
|
} )
|
||||||
})
|
})
|
||||||
.catch(err => { errActions.newAuthErr( err ) })
|
}
|
||||||
|
|
||||||
|
export function configureAuth(payload) {
|
||||||
|
return {
|
||||||
|
type: CONFIGURE_AUTH,
|
||||||
|
payload: payload
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { fromJS, Map } from "immutable"
|
import { fromJS, Map } from "immutable"
|
||||||
import btoa from "btoa"
|
import { btoa } from "core/utils"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SHOW_AUTH_POPUP,
|
SHOW_AUTH_POPUP,
|
||||||
AUTHORIZE,
|
AUTHORIZE,
|
||||||
PRE_AUTHORIZE_OAUTH2,
|
|
||||||
AUTHORIZE_OAUTH2,
|
AUTHORIZE_OAUTH2,
|
||||||
LOGOUT
|
LOGOUT,
|
||||||
|
CONFIGURE_AUTH
|
||||||
} from "./actions"
|
} from "./actions"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -21,7 +21,6 @@ export default {
|
|||||||
// refactor withMutations
|
// refactor withMutations
|
||||||
securities.entrySeq().forEach( ([ key, security ]) => {
|
securities.entrySeq().forEach( ([ key, security ]) => {
|
||||||
let type = security.getIn(["schema", "type"])
|
let type = security.getIn(["schema", "type"])
|
||||||
let name = security.get("name")
|
|
||||||
|
|
||||||
if ( type === "apiKey" ) {
|
if ( type === "apiKey" ) {
|
||||||
map = map.set(key, security)
|
map = map.set(key, security)
|
||||||
@@ -59,5 +58,9 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return state.set("authorized", result)
|
return state.set("authorized", result)
|
||||||
|
},
|
||||||
|
|
||||||
|
[CONFIGURE_AUTH]: (state, { payload } ) =>{
|
||||||
|
return state.set("configs", payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const shownDefinitions = createSelector(
|
|||||||
|
|
||||||
export const definitionsToAuthorize = createSelector(
|
export const definitionsToAuthorize = createSelector(
|
||||||
state,
|
state,
|
||||||
auth =>( { specSelectors } ) => {
|
() =>( { specSelectors } ) => {
|
||||||
let definitions = specSelectors.securityDefinitions()
|
let definitions = specSelectors.securityDefinitions()
|
||||||
let list = List()
|
let list = List()
|
||||||
|
|
||||||
@@ -66,7 +66,10 @@ export const authorized = createSelector(
|
|||||||
|
|
||||||
export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
|
export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
|
||||||
let authorized = authSelectors.authorized()
|
let authorized = authSelectors.authorized()
|
||||||
let isAuth = false
|
|
||||||
|
if(!List.isList(securities)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return !!securities.toJS().filter( ( security ) => {
|
return !!securities.toJS().filter( ( security ) => {
|
||||||
let isAuthorized = true
|
let isAuthorized = true
|
||||||
@@ -76,3 +79,8 @@ export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
|
|||||||
}).indexOf(false) === -1
|
}).indexOf(false) === -1
|
||||||
}).length
|
}).length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getConfigs = createSelector(
|
||||||
|
state,
|
||||||
|
auth => auth.get( "configs" )
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { Map } from "immutable"
|
|
||||||
|
|
||||||
// Add security to the final `execute` call ( via `extras` )
|
// Add security to the final `execute` call ( via `extras` )
|
||||||
export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path, method, operation, extras }) => {
|
export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path, method, operation, extras }) => {
|
||||||
let securities = {
|
let securities = {
|
||||||
@@ -10,4 +8,3 @@ export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path
|
|||||||
|
|
||||||
return oriAction({ path, method, operation, securities, ...extras })
|
return oriAction({ path, method, operation, securities, ...extras })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ import { createSelector } from "reselect"
|
|||||||
import { Map } from "immutable"
|
import { Map } from "immutable"
|
||||||
|
|
||||||
export default function downloadUrlPlugin (toolbox) {
|
export default function downloadUrlPlugin (toolbox) {
|
||||||
let { fn, Im } = toolbox
|
let { fn } = toolbox
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
download: (url)=> ({ errActions, specSelectors, specActions }) => {
|
download: (url)=> ({ errActions, specSelectors, specActions }) => {
|
||||||
let { fetch } = fn
|
let { fetch } = fn
|
||||||
url = url || specSelectors.url()
|
url = url || specSelectors.url()
|
||||||
specActions.updateLoadingStatus("loading")
|
specActions.updateLoadingStatus("loading")
|
||||||
fetch(url, {
|
fetch({
|
||||||
|
url,
|
||||||
|
loadSpec: true,
|
||||||
|
credentials: "same-origin",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json,*/*"
|
||||||
}
|
}
|
||||||
}).then(next,next)
|
}).then(next,next)
|
||||||
|
|
||||||
@@ -30,7 +33,7 @@ export default function downloadUrlPlugin (toolbox) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateLoadingStatus: (status) => {
|
updateLoadingStatus: (status) => {
|
||||||
let enums = [null, "loading", "failed", "success"]
|
let enums = [null, "loading", "failed", "success", "failedConfig"]
|
||||||
if(enums.indexOf(status) === -1) {
|
if(enums.indexOf(status) === -1) {
|
||||||
console.error(`Error: ${status} is not one of ${JSON.stringify(enums)}`)
|
console.error(`Error: ${status} is not one of ${JSON.stringify(enums)}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ export function newThrownErrBatch(errors) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function newSpecErr(err, action) {
|
export function newSpecErr(err) {
|
||||||
return {
|
return {
|
||||||
type: NEW_SPEC_ERR,
|
type: NEW_SPEC_ERR,
|
||||||
payload: err
|
payload: err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function newAuthErr(err, action) {
|
export function newAuthErr(err) {
|
||||||
return {
|
return {
|
||||||
type: NEW_AUTH_ERR,
|
type: NEW_AUTH_ERR,
|
||||||
payload: err
|
payload: err
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import concat from "lodash/concat"
|
|
||||||
import reduce from "lodash/reduce"
|
import reduce from "lodash/reduce"
|
||||||
let request = require.context("./transformers/", true, /\.js$/)
|
let request = require.context("./transformers/", true, /\.js$/)
|
||||||
let errorTransformers = []
|
let errorTransformers = []
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import get from "lodash/get"
|
import get from "lodash/get"
|
||||||
import last from "lodash/get"
|
import { fromJS } from "immutable"
|
||||||
import { fromJS, List } from "immutable"
|
|
||||||
|
|
||||||
export function transform(errors, { jsSpec }) {
|
export function transform(errors, { jsSpec }) {
|
||||||
// LOOK HERE THIS TRANSFORMER IS CURRENTLY DISABLED 😃
|
// LOOK HERE THIS TRANSFORMER IS CURRENTLY DISABLED 😃
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
|||||||
let obj = {}
|
let obj = {}
|
||||||
for (var name in props) {
|
for (var name in props) {
|
||||||
if ( !props[name].readOnly || includeReadOnly ) {
|
if ( !props[name].readOnly || includeReadOnly ) {
|
||||||
obj[name] = sampleFromSchema(props[name])
|
obj[name] = sampleFromSchema(props[name], { includeReadOnly: includeReadOnly })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
|||||||
obj.additionalProp1 = {}
|
obj.additionalProp1 = {}
|
||||||
} else if ( additionalProperties ) {
|
} else if ( additionalProperties ) {
|
||||||
let additionalProps = objectify(additionalProperties)
|
let additionalProps = objectify(additionalProperties)
|
||||||
let additionalPropVal = sampleFromSchema(additionalProps)
|
let additionalPropVal = sampleFromSchema(additionalProps, { includeReadOnly: includeReadOnly })
|
||||||
|
|
||||||
for (let i = 1; i < 4; i++) {
|
for (let i = 1; i < 4; i++) {
|
||||||
obj["additionalProp" + i] = additionalPropVal
|
obj["additionalProp" + i] = additionalPropVal
|
||||||
@@ -65,7 +65,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(type === "array") {
|
if(type === "array") {
|
||||||
return [ sampleFromSchema(items) ]
|
return [ sampleFromSchema(items, { includeReadOnly: includeReadOnly }) ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if(schema["enum"]) {
|
if(schema["enum"]) {
|
||||||
@@ -127,8 +127,12 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
|||||||
|
|
||||||
if (xml.wrapped) {
|
if (xml.wrapped) {
|
||||||
res[displayName] = []
|
res[displayName] = []
|
||||||
if (Array.isArray(defaultValue)) {
|
if (Array.isArray(example)) {
|
||||||
|
example.forEach((v)=>{
|
||||||
|
items.example = v
|
||||||
|
res[displayName].push(sampleXmlFromSchema(items, config))
|
||||||
|
})
|
||||||
|
} else if (Array.isArray(defaultValue)) {
|
||||||
defaultValue.forEach((v)=>{
|
defaultValue.forEach((v)=>{
|
||||||
items.default = v
|
items.default = v
|
||||||
res[displayName].push(sampleXmlFromSchema(items, config))
|
res[displayName].push(sampleXmlFromSchema(items, config))
|
||||||
@@ -145,14 +149,20 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
|||||||
|
|
||||||
let _res = []
|
let _res = []
|
||||||
|
|
||||||
if (Array.isArray(defaultValue)) {
|
if (Array.isArray(example)) {
|
||||||
|
example.forEach((v)=>{
|
||||||
|
items.example = v
|
||||||
|
_res.push(sampleXmlFromSchema(items, config))
|
||||||
|
})
|
||||||
|
return _res
|
||||||
|
} else if (Array.isArray(defaultValue)) {
|
||||||
defaultValue.forEach((v)=>{
|
defaultValue.forEach((v)=>{
|
||||||
items.default = v
|
items.default = v
|
||||||
_res.push(sampleXmlFromSchema(items, config))
|
_res.push(sampleXmlFromSchema(items, config))
|
||||||
})
|
})
|
||||||
return _res
|
return _res
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sampleXmlFromSchema(items, config)
|
return sampleXmlFromSchema(items, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +186,13 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
|||||||
} else {
|
} else {
|
||||||
props[propName].xml.name = props[propName].xml.name || propName
|
props[propName].xml.name = props[propName].xml.name || propName
|
||||||
props[propName].example = props[propName].example !== undefined ? props[propName].example : example[propName]
|
props[propName].example = props[propName].example !== undefined ? props[propName].example : example[propName]
|
||||||
res[displayName].push(sampleXmlFromSchema(props[propName]))
|
let t = sampleXmlFromSchema(props[propName])
|
||||||
|
if (Array.isArray(t)) {
|
||||||
|
res[displayName] = res[displayName].concat(t)
|
||||||
|
} else {
|
||||||
|
res[displayName].push(t)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import YAML from "js-yaml"
|
import YAML from "js-yaml"
|
||||||
|
import parseUrl from "url-parse"
|
||||||
import serializeError from "serialize-error"
|
import serializeError from "serialize-error"
|
||||||
|
|
||||||
// Actions conform to FSA (flux-standard-actions)
|
// Actions conform to FSA (flux-standard-actions)
|
||||||
@@ -184,13 +185,24 @@ export const logRequest = (req) => {
|
|||||||
|
|
||||||
// Actually fire the request via fn.execute
|
// Actually fire the request via fn.execute
|
||||||
// (For debugging) and ease of testing
|
// (For debugging) and ease of testing
|
||||||
export const executeRequest = (req) => ({fn, specActions, errActions}) => {
|
export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
||||||
let { pathName, method } = req
|
let { pathName, method, operation } = req
|
||||||
let parsedRequest = Object.assign({}, req)
|
|
||||||
if ( pathName && method ) {
|
let op = operation.toJS()
|
||||||
parsedRequest.operationId = method.toLowerCase() + "-" + pathName
|
|
||||||
|
// if url is relative, parseUrl makes it absolute by inferring from `window.location`
|
||||||
|
req.contextUrl = parseUrl(specSelectors.url()).toString()
|
||||||
|
|
||||||
|
|
||||||
|
if(op && op.operationId) {
|
||||||
|
req.operationId = op.operationId
|
||||||
|
} else if(op && pathName && method) {
|
||||||
|
req.operationId = fn.opId(op, pathName, method)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let parsedRequest = Object.assign({}, req)
|
||||||
parsedRequest = fn.buildRequest(parsedRequest)
|
parsedRequest = fn.buildRequest(parsedRequest)
|
||||||
|
|
||||||
specActions.setRequest(req.pathName, req.method, parsedRequest)
|
specActions.setRequest(req.pathName, req.method, parsedRequest)
|
||||||
|
|
||||||
return fn.execute(req)
|
return fn.execute(req)
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export default {
|
|||||||
|
|
||||||
[VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
[VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
||||||
let operation = state.getIn( [ "resolved", "paths", ...pathMethod ] )
|
let operation = state.getIn( [ "resolved", "paths", ...pathMethod ] )
|
||||||
let parameters = operation.get("parameters")
|
|
||||||
let isXml = /xml/i.test(operation.get("consumes_value"))
|
let isXml = /xml/i.test(operation.get("consumes_value"))
|
||||||
|
|
||||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
||||||
@@ -64,9 +63,6 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
[ClEAR_VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
[ClEAR_VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
||||||
let operation = state.getIn( [ "resolved", "paths", ...pathMethod ] )
|
|
||||||
let parameters = operation.get("parameters")
|
|
||||||
|
|
||||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
||||||
return parameters.withMutations( parameters => {
|
return parameters.withMutations( parameters => {
|
||||||
for ( let i = 0, len = parameters.count(); i < len; i++ ) {
|
for ( let i = 0, len = parameters.count(); i < len; i++ ) {
|
||||||
@@ -101,7 +97,11 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
[UPDATE_OPERATION_VALUE]: (state, { payload: { path, value, key } }) => {
|
[UPDATE_OPERATION_VALUE]: (state, { payload: { path, value, key } }) => {
|
||||||
return state.setIn(["resolved", "paths", ...path, key], fromJS(value))
|
let operationPath = ["resolved", "paths", ...path]
|
||||||
|
if(!state.getIn(operationPath)) {
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
return state.setIn([...operationPath, key], fromJS(value))
|
||||||
},
|
},
|
||||||
|
|
||||||
[CLEAR_RESPONSE]: (state, { payload: { path, method } } ) =>{
|
[CLEAR_RESPONSE]: (state, { payload: { path, method } } ) =>{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createSelector } from "reselect"
|
import { createSelector } from "reselect"
|
||||||
|
import { sorters } from "core/utils"
|
||||||
import { fromJS, Set, Map, List } from "immutable"
|
import { fromJS, Set, Map, List } from "immutable"
|
||||||
|
|
||||||
const DEFAULT_TAG = "default"
|
const DEFAULT_TAG = "default"
|
||||||
@@ -198,13 +199,16 @@ export const operationsWithTags = createSelector(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
export const taggedOperations = createSelector(
|
export const taggedOperations = ( state ) =>( { getConfigs } ) => {
|
||||||
state,
|
let { operationsSorter }= getConfigs()
|
||||||
operationsWithTags,
|
|
||||||
(state, tagMap) => {
|
return operationsWithTags(state).map((ops, tag) => {
|
||||||
return tagMap.map((ops, tag) => Map({tagDetails: tagDetails(state, tag), operations: ops}))
|
let sortFn = typeof operationsSorter === "function" ? operationsSorter
|
||||||
}
|
: sorters.operationsSorter[operationsSorter]
|
||||||
)
|
let operations = !sortFn ? ops : ops.sort(sortFn)
|
||||||
|
|
||||||
|
return Map({tagDetails: tagDetails(state, tag), operations: operations})})
|
||||||
|
}
|
||||||
|
|
||||||
export const responses = createSelector(
|
export const responses = createSelector(
|
||||||
state,
|
state,
|
||||||
@@ -224,7 +228,7 @@ export const requestFor = (state, path, method) => {
|
|||||||
return requests(state).getIn([path, method], null)
|
return requests(state).getIn([path, method], null)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const allowTryItOutFor = (state, path, method ) => {
|
export const allowTryItOutFor = () => {
|
||||||
// This is just a hook for now.
|
// This is just a hook for now.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -291,7 +295,11 @@ export function operationConsumes(state, pathMethod) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const operationScheme = ( state, path, method ) => {
|
export const operationScheme = ( state, path, method ) => {
|
||||||
return state.getIn(["scheme", path, method]) || state.getIn(["scheme", "_defaultScheme"]) || "http"
|
let url = state.get("url")
|
||||||
|
let matchResult = url.match(/^([a-z][a-z0-9+\-.]*):/)
|
||||||
|
let urlScheme = Array.isArray(matchResult) ? matchResult[1] : null
|
||||||
|
|
||||||
|
return state.getIn(["scheme", path, method]) || state.getIn(["scheme", "_defaultScheme"]) || urlScheme || ""
|
||||||
}
|
}
|
||||||
|
|
||||||
export const canExecuteScheme = ( state, path, method ) => {
|
export const canExecuteScheme = ( state, path, method ) => {
|
||||||
|
|||||||
@@ -57,14 +57,14 @@ export default class SplitPaneMode extends React.Component {
|
|||||||
const mode = layoutSelectors.whatMode(MODE_KEY)
|
const mode = layoutSelectors.whatMode(MODE_KEY)
|
||||||
const left = mode === MODE_RIGHT ? <noscript/> : children[0]
|
const left = mode === MODE_RIGHT ? <noscript/> : children[0]
|
||||||
const right = mode === MODE_LEFT ? <noscript/> : children[1]
|
const right = mode === MODE_LEFT ? <noscript/> : children[1]
|
||||||
const size = this.sizeFromMode(mode, '50%')
|
const size = this.sizeFromMode(mode, "50%")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SplitPane
|
<SplitPane
|
||||||
disabledClass={''}
|
disabledClass={""}
|
||||||
ref={'splitPane'}
|
ref={"splitPane"}
|
||||||
split='vertical'
|
split='vertical'
|
||||||
defaultSize={'50%'}
|
defaultSize={"50%"}
|
||||||
primary="second"
|
primary="second"
|
||||||
minSize={0}
|
minSize={0}
|
||||||
size={size}
|
size={size}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ module.exports = function({ configs }) {
|
|||||||
buildRequest: Swagger.buildRequest,
|
buildRequest: Swagger.buildRequest,
|
||||||
execute: Swagger.execute,
|
execute: Swagger.execute,
|
||||||
resolve: Swagger.resolve,
|
resolve: Swagger.resolve,
|
||||||
serializeRes: Swagger.serializeRes
|
serializeRes: Swagger.serializeRes,
|
||||||
|
opId: Swagger.helpers.opId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ import ReactDOM from "react-dom"
|
|||||||
import { connect, Provider } from "react-redux"
|
import { connect, Provider } from "react-redux"
|
||||||
import omit from "lodash/omit"
|
import omit from "lodash/omit"
|
||||||
|
|
||||||
|
|
||||||
const NotFoundComponent = name => ()=> <span style={{color: "red"}}> "{name}" component not found </span>
|
|
||||||
|
|
||||||
|
|
||||||
const SystemWrapper = (getSystem, ComponentToWrap ) => class extends Component {
|
const SystemWrapper = (getSystem, ComponentToWrap ) => class extends Component {
|
||||||
render() {
|
render() {
|
||||||
return <ComponentToWrap {...getSystem() } {...this.props} {...this.context} />
|
return <ComponentToWrap {...getSystem() } {...this.props} {...this.context} />
|
||||||
@@ -75,10 +71,10 @@ const createClass = component => React.createClass({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const Fallback = ({ error, name }) => <div style={{ // eslint-disable-line react/prop-types
|
const Fallback = ({ name }) => <div style={{ // eslint-disable-line react/prop-types
|
||||||
padding: "1em",
|
padding: "1em",
|
||||||
"color": "#aaa"
|
"color": "#aaa"
|
||||||
}}>😱 <i>Could not render { name ? name : "this component" }, see console.</i></div>
|
}}>😱 <i>Could not render { name === "t" ? "this component" : name }, see the console.</i></div>
|
||||||
|
|
||||||
const wrapRender = (component) => {
|
const wrapRender = (component) => {
|
||||||
const isStateless = component => !(component.prototype && component.prototype.isReactComponent)
|
const isStateless = component => !(component.prototype && component.prototype.isReactComponent)
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import BasePreset from "./base"
|
import BasePreset from "./base"
|
||||||
|
|
||||||
import allowTryItOutIfHost from "core/plugins/allow-try-it-out-if-host"
|
// Just the base, for now.
|
||||||
|
|
||||||
export default function PresetApis() {
|
export default function PresetApis() {
|
||||||
|
|
||||||
return [
|
return [
|
||||||
BasePreset,
|
BasePreset,
|
||||||
allowTryItOutIfHost,
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ import Model from "core/components/model"
|
|||||||
import Models from "core/components/models"
|
import Models from "core/components/models"
|
||||||
import TryItOutButton from "core/components/try-it-out-button"
|
import TryItOutButton from "core/components/try-it-out-button"
|
||||||
|
|
||||||
|
import BaseLayout from "core/components/layouts/base"
|
||||||
|
|
||||||
import * as LayoutUtils from "core/components/layout-utils"
|
import * as LayoutUtils from "core/components/layout-utils"
|
||||||
import * as JsonSchemaComponents from "core/json-schema-components"
|
import * as JsonSchemaComponents from "core/json-schema-components"
|
||||||
|
|
||||||
@@ -87,6 +89,7 @@ export default function() {
|
|||||||
model: Model,
|
model: Model,
|
||||||
models: Models,
|
models: Models,
|
||||||
TryItOutButton,
|
TryItOutButton,
|
||||||
|
BaseLayout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { createStore, applyMiddleware, bindActionCreators, compose } from "redux"
|
import { createStore, applyMiddleware, bindActionCreators, compose } from "redux"
|
||||||
import Im, { fromJS, Map } from "immutable"
|
import Im, { fromJS, Map } from "immutable"
|
||||||
import deepExtend from "deep-extend"
|
import deepExtend from "deep-extend"
|
||||||
import createLogger from "redux-logger"
|
|
||||||
import { combineReducers } from "redux-immutable"
|
import { combineReducers } from "redux-immutable"
|
||||||
import assign from "object-assign"
|
|
||||||
import serializeError from "serialize-error"
|
import serializeError from "serialize-error"
|
||||||
import { NEW_THROWN_ERR } from "corePlugins/err/actions"
|
import { NEW_THROWN_ERR } from "corePlugins/err/actions"
|
||||||
import win from "core/window"
|
import win from "core/window"
|
||||||
@@ -75,7 +73,7 @@ export default class Store {
|
|||||||
let dispatch = this.getStore().dispatch
|
let dispatch = this.getStore().dispatch
|
||||||
let getState = this.getStore().getState
|
let getState = this.getStore().getState
|
||||||
|
|
||||||
this.boundSystem = assign({},
|
this.boundSystem = Object.assign({},
|
||||||
this.getRootInjects(),
|
this.getRootInjects(),
|
||||||
this.getWrappedAndBoundActions(dispatch),
|
this.getWrappedAndBoundActions(dispatch),
|
||||||
this.getBoundSelectors(getState, this.getSystem),
|
this.getBoundSelectors(getState, this.getSystem),
|
||||||
@@ -93,7 +91,7 @@ export default class Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRootInjects() {
|
getRootInjects() {
|
||||||
return assign({
|
return Object.assign({
|
||||||
getSystem: this.getSystem,
|
getSystem: this.getSystem,
|
||||||
getStore: this.getStore.bind(this),
|
getStore: this.getStore.bind(this),
|
||||||
getComponents: this.getComponents.bind(this),
|
getComponents: this.getComponents.bind(this),
|
||||||
@@ -252,7 +250,7 @@ export default class Store {
|
|||||||
|
|
||||||
getMapStateToProps() {
|
getMapStateToProps() {
|
||||||
return () => {
|
return () => {
|
||||||
let obj = assign({}, this.getSystem())
|
let obj = Object.assign({}, this.getSystem())
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import Im from "immutable"
|
import Im from "immutable"
|
||||||
import assign from "object-assign"
|
|
||||||
import shallowEqual from "shallowequal"
|
import shallowEqual from "shallowequal"
|
||||||
|
|
||||||
import camelCase from "lodash/camelCase"
|
import camelCase from "lodash/camelCase"
|
||||||
@@ -85,7 +84,7 @@ export function objReduce(obj, fn) {
|
|||||||
return Object.keys(obj).reduce((newObj, key) => {
|
return Object.keys(obj).reduce((newObj, key) => {
|
||||||
let res = fn(obj[key], key)
|
let res = fn(obj[key], key)
|
||||||
if(res && typeof res === "object")
|
if(res && typeof res === "object")
|
||||||
assign(newObj, res)
|
Object.assign(newObj, res)
|
||||||
return newObj
|
return newObj
|
||||||
}, {})
|
}, {})
|
||||||
}
|
}
|
||||||
@@ -135,12 +134,11 @@ export function getList(iterable, keys) {
|
|||||||
// Adapted from http://stackoverflow.com/a/2893259/454004
|
// Adapted from http://stackoverflow.com/a/2893259/454004
|
||||||
// Note: directly ported from CoffeeScript
|
// Note: directly ported from CoffeeScript
|
||||||
export function formatXml (xml) {
|
export function formatXml (xml) {
|
||||||
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp
|
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, reg, transitions, wsexp
|
||||||
reg = /(>)(<)(\/*)/g
|
reg = /(>)(<)(\/*)/g
|
||||||
wsexp = /[ ]*(.*)[ ]+\n/g
|
wsexp = /[ ]*(.*)[ ]+\n/g
|
||||||
contexp = /(<.+>)(.+\n)/g
|
contexp = /(<.+>)(.+\n)/g
|
||||||
xml = xml.replace(/\r\n/g, "\n").replace(reg, "$1\n$2$3").replace(wsexp, "$1\n").replace(contexp, "$1\n$2")
|
xml = xml.replace(/\r\n/g, "\n").replace(reg, "$1\n$2$3").replace(wsexp, "$1\n").replace(contexp, "$1\n$2")
|
||||||
pad = 0
|
|
||||||
formatted = ""
|
formatted = ""
|
||||||
lines = xml.split("\n")
|
lines = xml.split("\n")
|
||||||
indent = 0
|
indent = 0
|
||||||
@@ -164,7 +162,7 @@ export function formatXml (xml) {
|
|||||||
"other->other": 0
|
"other->other": 0
|
||||||
}
|
}
|
||||||
fn = function(ln) {
|
fn = function(ln) {
|
||||||
var fromTo, j, key, padding, type, types, value
|
var fromTo, key, padding, type, types, value
|
||||||
types = {
|
types = {
|
||||||
single: Boolean(ln.match(/<.+\/>/)),
|
single: Boolean(ln.match(/<.+\/>/)),
|
||||||
closing: Boolean(ln.match(/<\/.+>/)),
|
closing: Boolean(ln.match(/<\/.+>/)),
|
||||||
@@ -187,11 +185,13 @@ export function formatXml (xml) {
|
|||||||
padding = ""
|
padding = ""
|
||||||
indent += transitions[fromTo]
|
indent += transitions[fromTo]
|
||||||
padding = ((function() {
|
padding = ((function() {
|
||||||
var m, ref1, results
|
/* eslint-disable no-unused-vars */
|
||||||
|
var m, ref1, results, j
|
||||||
results = []
|
results = []
|
||||||
for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {
|
for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {
|
||||||
results.push(" ")
|
results.push(" ")
|
||||||
}
|
}
|
||||||
|
/* eslint-enable no-unused-vars */
|
||||||
return results
|
return results
|
||||||
})()).join("")
|
})()).join("")
|
||||||
if (fromTo === "opening->closing") {
|
if (fromTo === "opening->closing") {
|
||||||
@@ -215,19 +215,9 @@ export function formatXml (xml) {
|
|||||||
export function highlight (el) {
|
export function highlight (el) {
|
||||||
const MAX_LENGTH = 5000
|
const MAX_LENGTH = 5000
|
||||||
var
|
var
|
||||||
_window = window,
|
|
||||||
_document = document,
|
_document = document,
|
||||||
appendChild = "appendChild",
|
appendChild = "appendChild",
|
||||||
test = "test",
|
test = "test"
|
||||||
// style and color templates
|
|
||||||
textShadow = ";text-shadow:",
|
|
||||||
opacity = "opacity:.",
|
|
||||||
_0px_0px = " 0px 0px ",
|
|
||||||
_3px_0px_5 = "3px 0px 5",
|
|
||||||
brace = ")",
|
|
||||||
|
|
||||||
i,
|
|
||||||
microlighted
|
|
||||||
|
|
||||||
if (!el) return ""
|
if (!el) return ""
|
||||||
if (el.textContent.length > MAX_LENGTH) { return el.textContent }
|
if (el.textContent.length > MAX_LENGTH) { return el.textContent }
|
||||||
@@ -260,14 +250,7 @@ export function highlight (el) {
|
|||||||
lastTokenType,
|
lastTokenType,
|
||||||
// flag determining if token is multi-character
|
// flag determining if token is multi-character
|
||||||
multichar,
|
multichar,
|
||||||
node,
|
node
|
||||||
|
|
||||||
// calculating the colors for the style templates
|
|
||||||
colorArr = /(\d*\, \d*\, \d*)(, ([.\d]*))?/g.exec(
|
|
||||||
_window.getComputedStyle(el).color
|
|
||||||
),
|
|
||||||
pxColor = "px rgba("+colorArr[1]+",",
|
|
||||||
alpha = colorArr[3]||1
|
|
||||||
|
|
||||||
// running through characters and highlighting
|
// running through characters and highlighting
|
||||||
while (prev2 = prev1,
|
while (prev2 = prev1,
|
||||||
@@ -468,6 +451,17 @@ export const propChecker = (props, nextProps, objectList=[], ignoreList=[]) => {
|
|||||||
|| objectList.some( objectPropName => !eq(props[objectPropName], nextProps[objectPropName])))
|
|| objectList.some( objectPropName => !eq(props[objectPropName], nextProps[objectPropName])))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validateNumber = ( val ) => {
|
||||||
|
if ( !/^-?\d+(.?\d+)?$/.test(val)) {
|
||||||
|
return "Value must be a number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateInteger = ( val ) => {
|
||||||
|
if ( !/^-?\d+$/.test(val)) {
|
||||||
|
return "Value must be integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validation of parameters before execute
|
// validation of parameters before execute
|
||||||
export const validateParam = (param, isXml) => {
|
export const validateParam = (param, isXml) => {
|
||||||
@@ -517,29 +511,16 @@ export const validateParam = (param, isXml) => {
|
|||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
const validateNumber = ( val ) => {
|
|
||||||
if ( !/^\d+(.?\d+)?$/.test(val)) {
|
|
||||||
return "Value must be a number"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const validateInteger = ( val ) => {
|
|
||||||
if ( !/^\d+$/.test(val)) {
|
|
||||||
return "Value must be integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getSampleSchema = (schema, contentType="", config={}) => {
|
export const getSampleSchema = (schema, contentType="", config={}) => {
|
||||||
if (/xml/.test(contentType)) {
|
if (/xml/.test(contentType)) {
|
||||||
if (!schema.xml || !schema.xml.name) {
|
if (!schema.xml || !schema.xml.name) {
|
||||||
let name
|
|
||||||
schema.xml = schema.xml || {}
|
schema.xml = schema.xml || {}
|
||||||
|
|
||||||
if (schema.$$ref) {
|
if (schema.$$ref) {
|
||||||
let match = schema.$$ref.match(/\S*\/(\S+)$/)
|
let match = schema.$$ref.match(/\S*\/(\S+)$/)
|
||||||
schema.xml.name = match[1]
|
schema.xml.name = match[1]
|
||||||
} else if (schema.type || schema.items || schema.properties || schema.additionalProperties) {
|
} else if (schema.type || schema.items || schema.properties || schema.additionalProperties) {
|
||||||
return '<?xml version="1.0" encoding="UTF-8"?>\n<!-- XML example cannot be generated -->'
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- XML example cannot be generated -->"
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -549,3 +530,62 @@ export const getSampleSchema = (schema, contentType="", config={}) => {
|
|||||||
|
|
||||||
return JSON.stringify(memoizedSampleFromSchema(schema, config), null, 2)
|
return JSON.stringify(memoizedSampleFromSchema(schema, config), null, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const parseSeach = () => {
|
||||||
|
let map = {}
|
||||||
|
let search = window.location.search
|
||||||
|
|
||||||
|
if ( search != "" ) {
|
||||||
|
let params = search.substr(1).split("&")
|
||||||
|
|
||||||
|
for (let i in params) {
|
||||||
|
i = params[i].split("=")
|
||||||
|
map[decodeURIComponent(i[0])] = decodeURIComponent(i[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
export const btoa = (str) => {
|
||||||
|
let buffer
|
||||||
|
|
||||||
|
if (str instanceof Buffer) {
|
||||||
|
buffer = str
|
||||||
|
} else {
|
||||||
|
buffer = new Buffer(str.toString(), "utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toString("base64")
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sorters = {
|
||||||
|
operationsSorter: {
|
||||||
|
alpha: (a, b) => a.get("path").localeCompare(b.get("path")),
|
||||||
|
method: (a, b) => a.get("method").localeCompare(b.get("method"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const buildFormData = (data) => {
|
||||||
|
let formArr = []
|
||||||
|
|
||||||
|
for (let name in data) {
|
||||||
|
let val = data[name]
|
||||||
|
if (val !== undefined && val !== "") {
|
||||||
|
formArr.push([name, "=", encodeURIComponent(val).replace(/%20/g,"+")].join(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formArr.join("&")
|
||||||
|
}
|
||||||
|
|
||||||
|
export const filterConfigs = (configs, allowed) => {
|
||||||
|
let i, filteredConfigs = {}
|
||||||
|
|
||||||
|
for (i in configs) {
|
||||||
|
if (allowed.indexOf(i) !== -1) {
|
||||||
|
filteredConfigs[i] = configs[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredConfigs
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
var win = {
|
function makeWindow() {
|
||||||
|
var win = {
|
||||||
location: {},
|
location: {},
|
||||||
history: {},
|
history: {},
|
||||||
open: () => {},
|
open: () => {},
|
||||||
close: () => {}
|
close: () => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if(typeof window === "undefined") {
|
||||||
|
return win
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
win = window
|
win = window
|
||||||
var props = ["File", "Blob", "FormData"]
|
var props = ["File", "Blob", "FormData"]
|
||||||
for (var prop of props) {
|
for (var prop of props) {
|
||||||
@@ -13,8 +18,11 @@ try {
|
|||||||
win[prop] = window[prop]
|
win[prop] = window[prop]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch( e ) {
|
} catch( e ) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return win
|
||||||
}
|
}
|
||||||
|
|
||||||
export default win
|
module.exports = makeWindow()
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import YAML from "js-yaml"
|
import YAML from "js-yaml"
|
||||||
import yamlConfig from "../../../swagger-config.yaml"
|
import yamlConfig from "../../../swagger-config.yaml"
|
||||||
|
|
||||||
const CONFIGS = [ "url", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion",
|
|
||||||
"apisSorter", "operationsSorter", "supportedSubmitMethods", "highlightSizeThreshold", "dom_id",
|
|
||||||
"defaultModelRendering", "oauth2RedirectUrl", "showRequestHeaders" ]
|
|
||||||
|
|
||||||
const parseYamlConfig = (yaml, system) => {
|
const parseYamlConfig = (yaml, system) => {
|
||||||
try {
|
try {
|
||||||
return YAML.safeLoad(yaml)
|
return YAML.safeLoad(yaml)
|
||||||
@@ -16,22 +12,6 @@ const parseYamlConfig = (yaml, system) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseSeach = () => {
|
|
||||||
let map = {}
|
|
||||||
let search = window.location.search
|
|
||||||
|
|
||||||
if ( search != "" ) {
|
|
||||||
let params = search.substr(1).split("&");
|
|
||||||
|
|
||||||
for (let i in params) {
|
|
||||||
i = params[i].split("=");
|
|
||||||
map[decodeURIComponent(i[0])] = decodeURIComponent(i[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default function configPlugin (toolbox) {
|
export default function configPlugin (toolbox) {
|
||||||
let { fn } = toolbox
|
let { fn } = toolbox
|
||||||
@@ -42,9 +22,7 @@ export default function configPlugin (toolbox) {
|
|||||||
return fetch(url)
|
return fetch(url)
|
||||||
},
|
},
|
||||||
|
|
||||||
getConfigByUrl: (callback)=> ({ specActions }) => {
|
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => {
|
||||||
let config = parseSeach()
|
|
||||||
let configUrl = config.config
|
|
||||||
if (configUrl) {
|
if (configUrl) {
|
||||||
return specActions.downloadConfig(configUrl).then(next, next)
|
return specActions.downloadConfig(configUrl).then(next, next)
|
||||||
}
|
}
|
||||||
@@ -52,9 +30,12 @@ export default function configPlugin (toolbox) {
|
|||||||
function next(res) {
|
function next(res) {
|
||||||
if (res instanceof Error || res.status >= 400) {
|
if (res instanceof Error || res.status >= 400) {
|
||||||
specActions.updateLoadingStatus("failedConfig")
|
specActions.updateLoadingStatus("failedConfig")
|
||||||
console.log(res.statusText + " " + configUrl)
|
specActions.updateLoadingStatus("failedConfig")
|
||||||
|
specActions.updateUrl("")
|
||||||
|
console.error(res.statusText + " " + configUrl)
|
||||||
|
cb(null)
|
||||||
} else {
|
} else {
|
||||||
callback(parseYamlConfig(res.text))
|
cb(parseYamlConfig(res.text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,16 +54,3 @@ export default function configPlugin (toolbox) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function filterConfigs (configs) {
|
|
||||||
let i, filteredConfigs = {}
|
|
||||||
|
|
||||||
for (i in configs) {
|
|
||||||
if (CONFIGS.indexOf(i) !== -1) {
|
|
||||||
filteredConfigs[i] = configs[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredConfigs
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import Topbar from './topbar.jsx'
|
import Topbar from "./topbar.jsx"
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ export default class Topbar extends React.Component {
|
|||||||
this.setState({url: value})
|
this.setState({url: value})
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadUrl = () => {
|
downloadUrl = (e) => {
|
||||||
this.props.specActions.updateUrl(this.state.url)
|
this.props.specActions.updateUrl(this.state.url)
|
||||||
this.props.specActions.download(this.state.url)
|
this.props.specActions.download(this.state.url)
|
||||||
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -43,10 +44,10 @@ export default class Topbar extends React.Component {
|
|||||||
<img height="30" width="30" src={ Logo } alt="Swagger UX"/>
|
<img height="30" width="30" src={ Logo } alt="Swagger UX"/>
|
||||||
<span>swagger</span>
|
<span>swagger</span>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="download-url-wrapper">
|
<form className="download-url-wrapper" onSubmit={this.downloadUrl}>
|
||||||
<input className="download-url-input" type="text" onChange={ this.onUrlChange } value={this.state.url} disabled={isLoading} style={inputStyle} />
|
<input className="download-url-input" type="text" onChange={ this.onUrlChange } value={this.state.url} disabled={isLoading} style={inputStyle} />
|
||||||
<Button className="download-url-button" onClick={ this.downloadUrl }>Explore</Button>
|
<Button className="download-url-button" onClick={ this.downloadUrl }>Explore</Button>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import StandaloneLayout from './layout'
|
import StandaloneLayout from "./layout"
|
||||||
import '../style/main.scss'
|
import "../style/main.scss"
|
||||||
|
|
||||||
import TopbarPlugin from "plugins/topbar"
|
import TopbarPlugin from "plugins/topbar"
|
||||||
import ConfigsPlugin from "plugins/configs"
|
import ConfigsPlugin from "plugins/configs"
|
||||||
@@ -16,4 +16,4 @@ let preset = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
export default preset
|
module.exports = preset
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { PropTypes } from 'react'
|
import React, { PropTypes } from "react"
|
||||||
|
|
||||||
export default class StandaloneLayout extends React.Component {
|
export default class StandaloneLayout extends React.Component {
|
||||||
|
|
||||||
@@ -6,35 +6,23 @@ export default class StandaloneLayout extends React.Component {
|
|||||||
errSelectors: PropTypes.object.isRequired,
|
errSelectors: PropTypes.object.isRequired,
|
||||||
errActions: PropTypes.object.isRequired,
|
errActions: PropTypes.object.isRequired,
|
||||||
specActions: PropTypes.object.isRequired,
|
specActions: PropTypes.object.isRequired,
|
||||||
|
specSelectors: PropTypes.object.isRequired,
|
||||||
layoutSelectors: PropTypes.object.isRequired,
|
layoutSelectors: PropTypes.object.isRequired,
|
||||||
layoutActions: PropTypes.object.isRequired
|
layoutActions: PropTypes.object.isRequired,
|
||||||
|
getComponent: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { specSelectors, specActions, getComponent, errSelectors, errActions, spec, readOnly } = this.props
|
let { getComponent, specSelectors } = this.props
|
||||||
|
|
||||||
let info = specSelectors.info()
|
|
||||||
let url = specSelectors.url()
|
|
||||||
let basePath = specSelectors.basePath()
|
|
||||||
let host = specSelectors.host()
|
|
||||||
let securityDefinitions = specSelectors.securityDefinitions()
|
|
||||||
let externalDocs = specSelectors.externalDocs()
|
|
||||||
let schemes = specSelectors.schemes()
|
|
||||||
|
|
||||||
let Info = getComponent("info")
|
|
||||||
let Operations = getComponent("operations", true)
|
|
||||||
let Models = getComponent("models", true)
|
|
||||||
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
|
||||||
let Container = getComponent("Container")
|
let Container = getComponent("Container")
|
||||||
let Row = getComponent("Row")
|
let Row = getComponent("Row")
|
||||||
let Col = getComponent("Col")
|
let Col = getComponent("Col")
|
||||||
let Button = getComponent("Button")
|
|
||||||
let Errors = getComponent("errors", true)
|
|
||||||
const SplitPaneMode = getComponent("SplitPaneMode", true)
|
|
||||||
const Schemes = getComponent("schemes")
|
|
||||||
|
|
||||||
const Topbar = getComponent("Topbar", true)
|
const Topbar = getComponent("Topbar", true)
|
||||||
|
const BaseLayout = getComponent("BaseLayout", true)
|
||||||
const OnlineValidatorBadge = getComponent("onlineValidatorBadge", true)
|
const OnlineValidatorBadge = getComponent("onlineValidatorBadge", true)
|
||||||
|
|
||||||
const loadingStatus = specSelectors.loadingStatus()
|
const loadingStatus = specSelectors.loadingStatus()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -56,38 +44,7 @@ export default class StandaloneLayout extends React.Component {
|
|||||||
<h4 className="title">Failed to load config.</h4>
|
<h4 className="title">Failed to load config.</h4>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{ loadingStatus === "success" &&
|
{ !loadingStatus || loadingStatus === "success" && <BaseLayout/> }
|
||||||
<div>
|
|
||||||
<Errors/>
|
|
||||||
<Row className="information-container">
|
|
||||||
<Col mobile={12}>
|
|
||||||
{ info.count() ? (
|
|
||||||
<Info info={ info } url={ url } host={ host } basePath={ basePath } externalDocs={externalDocs} getComponent={getComponent}/>
|
|
||||||
) : null }
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<div className="scheme-container">
|
|
||||||
<Col className="schemes wrapper" mobile={12}>
|
|
||||||
{ schemes && schemes.size ? (
|
|
||||||
<Schemes schemes={ schemes } specActions={ specActions } />
|
|
||||||
) : null }
|
|
||||||
{ securityDefinitions ? (
|
|
||||||
<AuthorizeBtn />
|
|
||||||
) : null }
|
|
||||||
</Col>
|
|
||||||
</div>
|
|
||||||
<Row>
|
|
||||||
<Col mobile={12} desktop={12} >
|
|
||||||
<Operations/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Col mobile={12} desktop={12} >
|
|
||||||
<Models/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</div> }
|
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<OnlineValidatorBadge />
|
<OnlineValidatorBadge />
|
||||||
|
|||||||
@@ -136,8 +136,8 @@
|
|||||||
|
|
||||||
svg
|
svg
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 20px;
|
||||||
height: 100%;
|
height: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,16 +9,26 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: rgba($_color-delete, .1);
|
background: rgba($_color-delete, .1);
|
||||||
|
|
||||||
|
.error-wrapper
|
||||||
|
{
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.errors
|
.errors
|
||||||
{
|
{
|
||||||
h4
|
h4
|
||||||
{
|
{
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
margin: 0 0 10px 0;
|
margin: 0;
|
||||||
|
|
||||||
@include text_code();
|
@include text_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
small
|
||||||
|
{
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hgroup
|
hgroup
|
||||||
|
|||||||
@@ -286,12 +286,37 @@ body
|
|||||||
@include method($_color-get);
|
@include method($_color-get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.opblock-patch
|
||||||
|
{
|
||||||
|
@include method($_color-patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.opblock-head
|
||||||
|
{
|
||||||
|
@include method($_color-head);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.opblock-options
|
||||||
|
{
|
||||||
|
@include method($_color-options);
|
||||||
|
}
|
||||||
|
|
||||||
&.opblock-deprecated
|
&.opblock-deprecated
|
||||||
{
|
{
|
||||||
opacity: .6;
|
opacity: .6;
|
||||||
|
|
||||||
@include method($_color-disabled);
|
@include method($_color-disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opblock-schemes
|
||||||
|
{
|
||||||
|
padding: 8px 20px;
|
||||||
|
|
||||||
|
.schemes-title
|
||||||
|
{
|
||||||
|
padding: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -467,14 +492,28 @@ body
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
|
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-all;
|
||||||
|
word-break: break-word;
|
||||||
|
hyphens: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
|
||||||
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #41444e;
|
background: #41444e;
|
||||||
|
|
||||||
|
overflow-wrap: break-word;
|
||||||
@include text_code(#fff);
|
@include text_code(#fff);
|
||||||
span
|
span
|
||||||
{
|
{
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.headerline
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scheme-container
|
.scheme-container
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
max-width: 300px;
|
||||||
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -33,8 +35,11 @@
|
|||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
flex: 3;
|
||||||
|
|
||||||
input[type=text]
|
input[type=text]
|
||||||
{
|
{
|
||||||
|
width: 100%;
|
||||||
min-width: 350px;
|
min-width: 350px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
|||||||
2
swagger-ui-dist-package/.npmignore
Normal file
2
swagger-ui-dist-package/.npmignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
README.md
|
||||||
|
deploy.sh
|
||||||
1
swagger-ui-dist-package/.npmrc
Normal file
1
swagger-ui-dist-package/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||||
3
swagger-ui-dist-package/README.md
Normal file
3
swagger-ui-dist-package/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
This module, `swagger-ui-dist`, exposes Swagger-UI's entire dist folder as a dependency-free npm module.
|
||||||
|
|
||||||
|
Use `swagger-ui` instead, if you'd like to have npm install dependencies for you.
|
||||||
21
swagger-ui-dist-package/deploy.sh
Executable file
21
swagger-ui-dist-package/deploy.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
# Deploy `swagger-ui-dist` to npm.
|
||||||
|
|
||||||
|
# Parameter Expansion: http://stackoverflow.com/questions/6393551/what-is-the-meaning-of-0-in-a-bash-script
|
||||||
|
cd "${0%/*}"
|
||||||
|
|
||||||
|
# Get UI version
|
||||||
|
UI_VERSION=$(node -p "require('../package.json').version")
|
||||||
|
|
||||||
|
# Replace our version placeholder with UI's version
|
||||||
|
sed -i "s|\$\$VERSION|$UI_VERSION|g" package.json
|
||||||
|
|
||||||
|
# Copy UI's dist files to our directory
|
||||||
|
cp ../dist/* .
|
||||||
|
|
||||||
|
if [ "$PUBLISH_DIST" = "true" ] || [ "$TRAVIS" = "true" ] ; then
|
||||||
|
npm publish .
|
||||||
|
else
|
||||||
|
npm pack .
|
||||||
|
fi
|
||||||
|
|
||||||
|
find . -not -name .npmignore -not -name .npmrc -not -name deploy.sh -not -name package.json -not -name README.md -not -name *.tgz -delete
|
||||||
18
swagger-ui-dist-package/package.json
Normal file
18
swagger-ui-dist-package/package.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "swagger-ui-dist",
|
||||||
|
"version": "$$VERSION",
|
||||||
|
"main": "dist/swagger-ui.js",
|
||||||
|
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||||
|
"contributors": [
|
||||||
|
"(in alphabetical order)",
|
||||||
|
"Anna Bodnia <anna.bodnia@gmail.com>",
|
||||||
|
"Buu Nguyen <buunguyen@gmail.com>",
|
||||||
|
"Josh Ponelat <jponelat@gmail.com>",
|
||||||
|
"Kyle Shockey <kyleshockey1@gmail.com>",
|
||||||
|
"Robert Barnwell <robert@robertismy.name>",
|
||||||
|
"Sahar Jafari <shr.jafari@gmail.com>"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {}
|
||||||
|
}
|
||||||
@@ -3,10 +3,9 @@ import React from "react"
|
|||||||
import expect, { createSpy } from "expect"
|
import expect, { createSpy } from "expect"
|
||||||
import { shallow } from "enzyme"
|
import { shallow } from "enzyme"
|
||||||
import Operation from "components/operation"
|
import Operation from "components/operation"
|
||||||
import Collapse from "react-collapse"
|
|
||||||
|
|
||||||
describe("<Operation/>", function(){
|
describe("<Operation/>", function(){
|
||||||
it("blanket tests", function(){
|
it.skip("blanket tests", function(){
|
||||||
|
|
||||||
let props = {
|
let props = {
|
||||||
operation: {get: ()=>{}},
|
operation: {get: ()=>{}},
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://example.com -H "Accept: application/json" -H "content-type: application/json" -d {"id":0,"name":"doggie","status":"available"}')
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"Accept: application/json\" -H \"content-type: application/json\" -d {\"id\":0,\"name\":\"doggie\",\"status\":\"available\"}")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does not change the case of header in curl", function() {
|
it("does not change the case of header in curl", function() {
|
||||||
@@ -35,7 +35,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://example.com -H "conTenT Type: application/Moar"')
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"conTenT Type: application/Moar\"")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl statement with an array of query params", function() {
|
it("prints a curl statement with an array of query params", function() {
|
||||||
@@ -46,7 +46,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X GET http://swaggerhub.com/v1/one?name=john|smith')
|
expect(curlified).toEqual("curl -X GET \"http://swaggerhub.com/v1/one?name=john|smith\"")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl statement with an array of query params and auth", function() {
|
it("prints a curl statement with an array of query params and auth", function() {
|
||||||
@@ -60,7 +60,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X GET http://swaggerhub.com/v1/one?name=john|smith -H "authorization: Basic Zm9vOmJhcg=="')
|
expect(curlified).toEqual("curl -X GET \"http://swaggerhub.com/v1/one?name=john|smith\" -H \"authorization: Basic Zm9vOmJhcg==\"")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl statement with html", function() {
|
it("prints a curl statement with html", function() {
|
||||||
@@ -71,13 +71,13 @@ describe("curlify", function() {
|
|||||||
accept: "application/json"
|
accept: "application/json"
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
description: '<b>Test</b>'
|
description: "<b>Test</b>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X GET http://swaggerhub.com/v1/one?name=john|smith -H "accept: application/json" -d {"description":"<b>Test</b>"}')
|
expect(curlified).toEqual("curl -X GET \"http://swaggerhub.com/v1/one?name=john|smith\" -H \"accept: application/json\" -d {\"description\":\"<b>Test</b>\"}")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("handles post body with html", function() {
|
it("handles post body with html", function() {
|
||||||
@@ -88,13 +88,13 @@ describe("curlify", function() {
|
|||||||
accept: "application/json"
|
accept: "application/json"
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
description: '<b>Test</b>'
|
description: "<b>Test</b>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://swaggerhub.com/v1/one?name=john|smith -H "accept: application/json" -d {"description":"<b>Test</b>"}')
|
expect(curlified).toEqual("curl -X POST \"http://swaggerhub.com/v1/one?name=john|smith\" -H \"accept: application/json\" -d {\"description\":\"<b>Test</b>\"}")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("handles post body with special chars", function() {
|
it("handles post body with special chars", function() {
|
||||||
@@ -102,14 +102,14 @@ describe("curlify", function() {
|
|||||||
url: "http://swaggerhub.com/v1/one?name=john|smith",
|
url: "http://swaggerhub.com/v1/one?name=john|smith",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: {
|
body: {
|
||||||
description: '@prefix nif:<http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .\n' +
|
description: "@prefix nif:<http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .\n" +
|
||||||
'@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> .'
|
"@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> ."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://swaggerhub.com/v1/one?name=john|smith -d {"description":"@prefix nif:<http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> ."}')
|
expect(curlified).toEqual("curl -X POST \"http://swaggerhub.com/v1/one?name=john|smith\" -d {\"description\":\"@prefix nif:<http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> .\"}")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("handles delete form with parameters", function() {
|
it("handles delete form with parameters", function() {
|
||||||
@@ -123,7 +123,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X DELETE http://example.com -H "accept: application/x-www-form-urlencoded"')
|
expect(curlified).toEqual("curl -X DELETE \"http://example.com\" -H \"accept: application/x-www-form-urlencoded\"")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should print a curl with formData", function() {
|
it("should print a curl with formData", function() {
|
||||||
@@ -136,7 +136,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://example.com -H "content-type: multipart/form-data" -F id=123 -F name=Sahar')
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F id=123 -F name=Sahar")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl post statement from an object", function() {
|
it("prints a curl post statement from an object", function() {
|
||||||
@@ -153,7 +153,7 @@ describe("curlify", function() {
|
|||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://example.com -H "accept: application/json" -d {"id":10101}')
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"accept: application/json\" -d {\"id\":10101}")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("prints a curl post statement from a string containing a single quote", function() {
|
it("prints a curl post statement from a string containing a single quote", function() {
|
||||||
@@ -163,12 +163,12 @@ describe("curlify", function() {
|
|||||||
headers: {
|
headers: {
|
||||||
accept: "application/json"
|
accept: "application/json"
|
||||||
},
|
},
|
||||||
body: '{"id":"foo\'bar"}'
|
body: "{\"id\":\"foo'bar\"}"
|
||||||
}
|
}
|
||||||
|
|
||||||
let curlified = curl(Im.fromJS(req))
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
expect(curlified).toEqual('curl -X POST http://example.com -H "accept: application/json" -d "{\\"id\\":\\"foo\'bar\\"}"')
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"accept: application/json\" -d \"{\\\"id\\\":\\\"foo'bar\\\"}\"")
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
import expect, { createSpy } from "expect"
|
import expect from "expect"
|
||||||
import { transformPathToArray } from "core/path-translator"
|
import { transformPathToArray } from "core/path-translator"
|
||||||
|
|
||||||
describe("validation plugin - path translator", function(){
|
describe("validation plugin - path translator", function(){
|
||||||
|
|||||||
@@ -1,268 +0,0 @@
|
|||||||
/* eslint-env mocha */
|
|
||||||
import expect from "expect"
|
|
||||||
import { pathForPosition, positionRangeForPath } from "corePlugins/ast/ast"
|
|
||||||
|
|
||||||
describe.skip("ASTManager", function() {
|
|
||||||
describe("#pathForPosition", function() {
|
|
||||||
describe("out of range", function() {
|
|
||||||
it("returns empty array for out of range row", function(done) {
|
|
||||||
var position = {line: 3, column: 0}
|
|
||||||
var assertPath = function(path) {
|
|
||||||
expect(path).toEqual([])
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
|
|
||||||
pathForPosition("swagger: 2.0", position)
|
|
||||||
.then(assertPath)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns empty array for out of range column", function(done) {
|
|
||||||
var position = {line: 0, column: 100}
|
|
||||||
var assertPath = function(path) {
|
|
||||||
expect(path).toEqual([])
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
|
|
||||||
pathForPosition("swagger: 2.0", position)
|
|
||||||
.then(assertPath)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when document is a simple hash `swagger: 2.0`", function() {
|
|
||||||
it("should return empty array when pointer is at middle of the hash key", function(done) {
|
|
||||||
var position = {line: 0, column: 3}
|
|
||||||
pathForPosition("swagger: 2.0", position).then(function(path) {
|
|
||||||
expect(path).toEqual([])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return ['swagger'] when pointer is at the value", function(done) {
|
|
||||||
var position = {line: 0, column: 10}
|
|
||||||
pathForPosition("swagger: 2.0", position).then(function(path) {
|
|
||||||
expect(path).toEqual(["swagger"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when document is an array: ['abc', 'cde']", function() {
|
|
||||||
var yaml = [
|
|
||||||
/*
|
|
||||||
0
|
|
||||||
01234567 */
|
|
||||||
/* 0 */ "- abc",
|
|
||||||
/* 1 */ "- def"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
it("should return empty array when pointer is at array dash", function(done) {
|
|
||||||
var position = {line: 0, column: 0}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual([])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return ['0'] when pointer is at abc", function(done) {
|
|
||||||
var position = {line: 0, column: 3}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["0"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return ['1'] when pointer is at abc", function(done) {
|
|
||||||
var position = {line: 1, column: 3}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["1"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when document is an array of arrays", function() {
|
|
||||||
var yaml = [
|
|
||||||
/*
|
|
||||||
0 10
|
|
||||||
0123456789012345 */
|
|
||||||
/* 0 */ "-",
|
|
||||||
/* 1 */ " - abc",
|
|
||||||
/* 2 */ " - def",
|
|
||||||
/* 3 */ "-",
|
|
||||||
/* 4 */ " - ABC",
|
|
||||||
/* 5 */ " - DEF"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
it("should return ['0', '0'] when pointer is at 'abc'", function(done) {
|
|
||||||
var position = {line: 1, column: 5}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["0", "0"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when document is an array of hashs", function() {
|
|
||||||
var yaml = [
|
|
||||||
/*
|
|
||||||
0 10
|
|
||||||
0123456789012345 */
|
|
||||||
/* 0 */ "- key: value",
|
|
||||||
/* 1 */ " num: 1",
|
|
||||||
/* 2 */ "- name: Tesla",
|
|
||||||
/* 3 */ " year: 2016"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
it("should return ['0'] when pointer is at 'key'", function(done) {
|
|
||||||
var position = {line: 0, column: 3}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["0"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return ['0', 'key'] when pointer is at 'value'", function(done) {
|
|
||||||
var position = {line: 0, column: 9}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["0", "key"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return ['1', 'year'] when pointer is at '2016'", function(done) {
|
|
||||||
var position = {line: 3, column: 10}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["1", "year"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("full document", function() {
|
|
||||||
var yaml = [
|
|
||||||
/*
|
|
||||||
0 10 20 30
|
|
||||||
012345678901234567890123456789012345678 */
|
|
||||||
/* 0 */ "swagger: '2.0'",
|
|
||||||
/* 1 */ "info:",
|
|
||||||
/* 2 */ " title: Test document",
|
|
||||||
/* 3 */ " version: 0.0.1",
|
|
||||||
/* 4 */ " contact:",
|
|
||||||
/* 5 */ " name: Sahar",
|
|
||||||
/* 6 */ " url: github.com",
|
|
||||||
/* 7 */ " email: me@example.com",
|
|
||||||
/* 8 */ " "
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
it("should return ['info', 'contact', 'email'] when pointer is at me@", function(done) {
|
|
||||||
var position = {line: 7, column: 13}
|
|
||||||
pathForPosition(yaml, position).then(function(path) {
|
|
||||||
expect(path).toEqual(["info", "contact", "email"])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("#positionRangeForPath", function() {
|
|
||||||
it("return {{-1, -1}, {-1, -1}} for invalid paths", function(done) {
|
|
||||||
var yaml = [
|
|
||||||
"key: value",
|
|
||||||
"anotherKey: value"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
positionRangeForPath(yaml, ["invalid"])
|
|
||||||
.then(function(position) {
|
|
||||||
expect(position.start).toEqual({line: -1, column: -1})
|
|
||||||
expect(position.end).toEqual({line: -1, column: -1})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when document is a simple hash `swagger: 2.0`", function() {
|
|
||||||
var yaml = "swagger: 2.0"
|
|
||||||
|
|
||||||
it("return {0, 0} for start of empty array path (root)", function(done) {
|
|
||||||
positionRangeForPath(yaml, []).then(function(position) {
|
|
||||||
expect(position.start).toEqual({line: 0, column: 0})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("return {0, 12} for end of empty array path (root)", function(done) {
|
|
||||||
positionRangeForPath(yaml, []).then(function(position) {
|
|
||||||
expect(position.end).toEqual({line: 0, column: 12})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("return {0, 9} for start of ['swagger']", function(done) {
|
|
||||||
positionRangeForPath(yaml, ["swagger"]).then(function(position) {
|
|
||||||
expect(position.start).toEqual({line: 0, column: 9})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("return {0, 12} for end of ['swagger']", function(done) {
|
|
||||||
positionRangeForPath(yaml, ["swagger"]).then(function(position) {
|
|
||||||
expect(position.end).toEqual({line: 0, column: 12})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when document is an array of primitives", function() {
|
|
||||||
var yaml = [
|
|
||||||
"key:",
|
|
||||||
" - value1",
|
|
||||||
" - value2"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
it("returns {1, 4} for ['key', '0']", function(done) {
|
|
||||||
positionRangeForPath(yaml, ["key", "0"]).then(function(position) {
|
|
||||||
expect(position.start).toEqual({line: 1, column: 4})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("full document", function() {
|
|
||||||
var yaml = [
|
|
||||||
/*
|
|
||||||
0 10 20 30
|
|
||||||
012345678901234567890123456789012345678 */
|
|
||||||
/* 0 */ "swagger: '2.0'",
|
|
||||||
/* 1 */ "info:",
|
|
||||||
/* 2 */ " title: Test document",
|
|
||||||
/* 3 */ " version: 0.0.1",
|
|
||||||
/* 4 */ " contact:",
|
|
||||||
/* 5 */ " name: Sahar",
|
|
||||||
/* 6 */ " url: github.com",
|
|
||||||
/* 7 */ " email: me@example.com",
|
|
||||||
/* 8 */ " "
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
it("returns {2, 2} for start of ['info']", function(done) {
|
|
||||||
positionRangeForPath(yaml, ["info"]).then(function(position) {
|
|
||||||
expect(position.start).toEqual({line: 2, column: 2})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns {5, 10} for start of ['info', 'contact', 'name']", function(done) {
|
|
||||||
positionRangeForPath(yaml, ["info", "contact", "name"]).then(function(position) {
|
|
||||||
expect(position.start).toEqual({line: 5, column: 10})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns {5, 15} for end of ['info', 'contact', 'name']", function(done) {
|
|
||||||
positionRangeForPath(yaml, ["info", "contact", "name"]).then(function(position) {
|
|
||||||
expect(position.end).toEqual({line: 5, column: 15})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
import expect, { createSpy } from "expect"
|
import expect, { createSpy } from "expect"
|
||||||
import { fromJS } from "immutable"
|
|
||||||
import { execute } from "corePlugins/auth/spec-wrap-actions"
|
import { execute } from "corePlugins/auth/spec-wrap-actions"
|
||||||
|
|
||||||
describe("spec plugin - actions", function(){
|
describe("spec plugin - actions", function(){
|
||||||
@@ -18,7 +17,7 @@ describe("spec plugin - actions", function(){
|
|||||||
|
|
||||||
// When
|
// When
|
||||||
let executeFn = execute(oriExecute, system)
|
let executeFn = execute(oriExecute, system)
|
||||||
let executePromise = executeFn({})
|
executeFn({})
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(oriExecute.calls.length).toEqual(1)
|
expect(oriExecute.calls.length).toEqual(1)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import expect, { createSpy } from "expect"
|
import expect from "expect"
|
||||||
import { Map, List } from "immutable"
|
import { Map, List } from "immutable"
|
||||||
import { transform } from "corePlugins/err/error-transformers/transformers/not-of-type"
|
import { transform } from "corePlugins/err/error-transformers/transformers/not-of-type"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import expect, { createSpy } from "expect"
|
import expect from "expect"
|
||||||
import { Map, List, fromJS } from "immutable"
|
import { fromJS } from "immutable"
|
||||||
import { transform } from "corePlugins/err/error-transformers/transformers/parameter-oneof"
|
import { transform } from "corePlugins/err/error-transformers/transformers/parameter-oneof"
|
||||||
|
|
||||||
describe.skip("err plugin - tranformers - parameter oneof", () => {
|
describe.skip("err plugin - tranformers - parameter oneof", () => {
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ describe("createXMLExample", function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns array with default values with wrapped=true", function () {
|
it("returns array with default values with wrapped=true", function () {
|
||||||
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<animal>one</animal>\n</animals>"
|
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<animal>1</animal>\n\t<animal>2</animal>\n</animals>"
|
||||||
var definition = {
|
var definition = {
|
||||||
items: {
|
items: {
|
||||||
"enum": ["one", "two"],
|
"enum": ["one", "two"],
|
||||||
@@ -405,6 +405,7 @@ describe("createXMLExample", function () {
|
|||||||
name: "animal"
|
name: "animal"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"default": ["1", "2"],
|
||||||
xml: {
|
xml: {
|
||||||
wrapped: true,
|
wrapped: true,
|
||||||
name: "animals"
|
name: "animals"
|
||||||
@@ -413,8 +414,53 @@ describe("createXMLExample", function () {
|
|||||||
|
|
||||||
expect(sut(definition)).toEqual(expected)
|
expect(sut(definition)).toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("returns array with example values with ", function () {
|
||||||
|
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<animal>1</animal>\n\t<animal>2</animal>\n</animals>"
|
||||||
|
var definition = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
"animal": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"example": [
|
||||||
|
"1",
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xml: {
|
||||||
|
name: "animals"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(sut(definition)).toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("returns array with example values with wrapped=true", function () {
|
||||||
|
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animals>\n\t<animal>1</animal>\n\t<animal>2</animal>\n</animals>"
|
||||||
|
var definition = {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
xml: {
|
||||||
|
name: "animal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": [ "1", "2" ],
|
||||||
|
xml: {
|
||||||
|
wrapped: true,
|
||||||
|
name: "animals"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(sut(definition)).toEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
describe("object", function () {
|
describe("object", function () {
|
||||||
it("returns object with 2 properties", function () {
|
it("returns object with 2 properties", function () {
|
||||||
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<aliens>\n\t<alien>string</alien>\n\t<dog>0</dog>\n</aliens>"
|
var expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<aliens>\n\t<alien>string</alien>\n\t<dog>0</dog>\n</aliens>"
|
||||||
|
|||||||
72
test/core/plugins/spec-reducer.js
Normal file
72
test/core/plugins/spec-reducer.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
import expect from "expect"
|
||||||
|
import { fromJS } from "immutable"
|
||||||
|
import reducer from "corePlugins/spec/reducers"
|
||||||
|
|
||||||
|
describe("spec plugin - reducer", function(){
|
||||||
|
|
||||||
|
describe("update operation value", function() {
|
||||||
|
it("should update the operation at the specified key", () => {
|
||||||
|
const updateOperationValue = reducer["spec_update_operation_value"]
|
||||||
|
|
||||||
|
const state = fromJS({
|
||||||
|
resolved: {
|
||||||
|
"paths": {
|
||||||
|
"/pet": {
|
||||||
|
"post": {
|
||||||
|
"description": "my operation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let result = updateOperationValue(state, {
|
||||||
|
payload: {
|
||||||
|
path: ["/pet", "post"],
|
||||||
|
value: "application/json",
|
||||||
|
key: "consumes_value"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let expectedResult = {
|
||||||
|
resolved: {
|
||||||
|
"paths": {
|
||||||
|
"/pet": {
|
||||||
|
"post": {
|
||||||
|
"description": "my operation",
|
||||||
|
"consumes_value": "application/json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(result.toJS()).toEqual(expectedResult)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("shouldn't throw an error if we try to update the consumes_value of a null operation", () => {
|
||||||
|
const updateOperationValue = reducer["spec_update_operation_value"]
|
||||||
|
|
||||||
|
const state = fromJS({
|
||||||
|
resolved: {
|
||||||
|
"paths": {
|
||||||
|
"/pet": {
|
||||||
|
"post": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let result = updateOperationValue(state, {
|
||||||
|
payload: {
|
||||||
|
path: ["/pet", "post"],
|
||||||
|
value: "application/json",
|
||||||
|
key: "consumes_value"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.toJS()).toEqual(state.toJS())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -25,7 +25,7 @@ describe("spec plugin - actions", function(){
|
|||||||
|
|
||||||
// When
|
// When
|
||||||
let executeFn = execute({ path: "/one", method: "get"})
|
let executeFn = execute({ path: "/one", method: "get"})
|
||||||
let executePromise = executeFn(system)
|
executeFn(system)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(system.specActions.executeRequest.calls[0].arguments[0]).toEqual({
|
expect(system.specActions.executeRequest.calls[0].arguments[0]).toEqual({
|
||||||
@@ -60,7 +60,7 @@ describe("spec plugin - actions", function(){
|
|||||||
|
|
||||||
// When
|
// When
|
||||||
let executeFn = execute({ hi: "hello" })
|
let executeFn = execute({ hi: "hello" })
|
||||||
let executePromise = executeFn(system)
|
executeFn(system)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(system.specActions.executeRequest.calls[0].arguments[0]).toInclude({hi: "hello"})
|
expect(system.specActions.executeRequest.calls[0].arguments[0]).toInclude({hi: "hello"})
|
||||||
@@ -72,7 +72,6 @@ describe("spec plugin - actions", function(){
|
|||||||
|
|
||||||
xit("should call fn.execute with arg ", function(){
|
xit("should call fn.execute with arg ", function(){
|
||||||
|
|
||||||
const response = {}
|
|
||||||
const system = {
|
const system = {
|
||||||
fn: {
|
fn: {
|
||||||
execute: createSpy().andReturn(Promise.resolve())
|
execute: createSpy().andReturn(Promise.resolve())
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
import expect, { createSpy } from "expect"
|
import expect from "expect"
|
||||||
import { fromJS } from "immutable"
|
import { fromJS } from "immutable"
|
||||||
import { parameterValues, contentTypeValues } from "corePlugins/spec/selectors"
|
import { parameterValues, contentTypeValues, operationScheme } from "corePlugins/spec/selectors"
|
||||||
|
|
||||||
describe("spec plugin - selectors", function(){
|
describe("spec plugin - selectors", function(){
|
||||||
|
|
||||||
@@ -92,4 +92,43 @@ describe("spec plugin - selectors", function(){
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("operationScheme", function(){
|
||||||
|
|
||||||
|
it("should return the correct scheme for a remote spec that doesn't specify a scheme", function(){
|
||||||
|
// Given
|
||||||
|
let state = fromJS({
|
||||||
|
url: "https://generator.swagger.io/api/swagger.json",
|
||||||
|
resolved: {
|
||||||
|
paths: {
|
||||||
|
"/one": {
|
||||||
|
get: {
|
||||||
|
"consumes_value": "one",
|
||||||
|
"produces_value": "two"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// When
|
||||||
|
let scheme = operationScheme(state, ["/one"], "get")
|
||||||
|
// Then
|
||||||
|
expect(scheme).toEqual("https")
|
||||||
|
})
|
||||||
|
|
||||||
|
// it("should be ok, if no operation found", function(){
|
||||||
|
// // Given
|
||||||
|
// let state = fromJS({ })
|
||||||
|
//
|
||||||
|
// // When
|
||||||
|
// let contentTypes = contentTypeValues(state, [ "/one", "get" ])
|
||||||
|
// // Then
|
||||||
|
// expect(contentTypes.toJS()).toEqual({
|
||||||
|
// requestContentType: undefined,
|
||||||
|
// responseContentType: undefined
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user