Compare commits

..
Author SHA1 Message Date
Kyle Shockey 1e2baeb91b this.downloadJSON -> this.downloadText
we're always saving as `.txt`, so JSON is a misnomer
2018-04-12 17:56:35 -07:00
Kyle Shockey ac43ee5feb center "Download" text in button 2018-04-12 17:56:07 -07:00
Kyle Shockey 64b83738ce prevent HighlightCode from scrolling entire document 2018-04-12 17:52:27 -07:00
kyle 0cdd54c24d Merge branch 'master' into auto-hide-contents 2018-04-12 17:17:20 -07:00
giancarlokc a3ef0d609f CSS fix. 2018-04-05 23:31:35 -07:00
giancarlokc 80e994ef79 Code clean up. 2018-04-05 23:21:00 -07:00
giancarlokc 115c5305ea Removed collapsing, added scrolling. 2018-04-05 23:16:46 -07:00
giancarlokc cd065d674c Merge branch 'auto-hide-contents' of https://github.com/giancarlokc/swagger-ui into auto-hide-contents 2018-04-05 22:39:19 -07:00
giancarlokc 6f061d8de5 Fix dist 2018-04-05 22:38:43 -07:00
Giancarlo Klemm Camilo 11eb6ef002 Merge branch 'master' into auto-hide-contents 2018-04-05 22:38:11 -07:00
Graeme 177464e06f Fix the angry linter 2018-04-05 21:07:07 -07:00
Graeme 6173d3b966 Better downloading
now downloads file on button click
2018-04-05 20:51:12 -07:00
Graeme 485d04ff3c Added basic downloading
Slightly broken
2018-04-03 15:21:05 -07:00
giancarlokc 0b8dab2d5e Auto hidding content that is longer than 600 characters long. 2018-04-02 23:56:26 -07:00
18 changed files with 54 additions and 248 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes
------------------ | ------------ | -------------------------- | -----
3.13.4 | 2018-04-15 | 2.0, 3.0 | [tag v3.13.4](https://github.com/swagger-api/swagger-ui/tree/v3.13.4)
3.13.3 | 2018-03-23 | 2.0, 3.0 | [tag v3.13.3](https://github.com/swagger-api/swagger-ui/tree/v3.13.3)
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21)
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10)
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5)
+14 -14
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.13.4",
"version": "3.13.3",
"main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [
@@ -52,7 +52,6 @@
"getbase": "^2.8.2",
"ieee754": "^1.1.8",
"immutable": "^3.x.x",
"js-file-download": "^0.4.1",
"js-yaml": "^3.5.5",
"lodash": "4.17.5",
"matcher": "^0.1.2",
@@ -84,7 +83,7 @@
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
"swagger-client": "^3.7.0",
"swagger-client": "^3.6.0",
"url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1",
@@ -117,6 +116,7 @@
"eslint-plugin-react": "^7.1.0",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "0.11.2",
"file-saver": "^1.3.8",
"git-describe": "^4.0.1",
"imports-loader": "0.7.1",
"json-loader": "0.5.4",
+6 -10
View File
@@ -1,13 +1,12 @@
import React, { Component } from "react"
import PropTypes from "prop-types"
import { highlight } from "core/utils"
import saveAs from "js-file-download"
import { saveAs } from "file-saver"
export default class HighlightCode extends Component {
static propTypes = {
value: PropTypes.string.isRequired,
className: PropTypes.string,
downloadable: PropTypes.bool
className: PropTypes.string
}
componentDidMount() {
@@ -23,7 +22,8 @@ export default class HighlightCode extends Component {
}
downloadText = () => {
saveAs(this.props.value, "response.txt")
let fileToSave = new Blob([this.props.value], {type: "text/plain"})
saveAs(fileToSave, "response")
}
preventYScrollingBeyondElement = (e) => {
@@ -45,16 +45,12 @@ export default class HighlightCode extends Component {
}
render () {
let { value, className, downloadable } = this.props
let { value, className } = this.props
className = className || ""
return (
<div className="highlight-code">
{ !downloadable ? null :
<div className="download-contents" onClick={this.downloadText}>
Download
</div>
}
<div className="download-contents" onClick={this.downloadText}>Download</div>
<pre
ref={this.initializeComponent}
onWheel={this.preventYScrollingBeyondElement}
+1 -1
View File
@@ -197,7 +197,7 @@ export default class ParameterRow extends Component {
getConfigs={ getConfigs }
isExecute={ isExecute }
specSelectors={ specSelectors }
schema={ param.get("schema") }
schema={ schema }
example={ bodyParam }/>
: null
}
+6 -55
View File
@@ -5,10 +5,7 @@ import lowerCase from "lodash/lowerCase"
import { extractFileNameFromContentDispositionHeader } from "core/utils"
import win from "core/window"
export default class ResponseBody extends React.PureComponent {
state = {
parsedContent: null
}
export default class ResponseBody extends React.Component {
static propTypes = {
content: PropTypes.any.isRequired,
@@ -18,39 +15,8 @@ export default class ResponseBody extends React.PureComponent {
url: PropTypes.string
}
updateParsedContent = (prevContent) => {
const { content } = this.props
if(prevContent === content) {
return
}
if(content && content instanceof Blob) {
var reader = new FileReader()
reader.onload = () => {
this.setState({
parsedContent: reader.result
})
}
reader.readAsText(content)
} else {
this.setState({
parsedContent: content.toString()
})
}
}
componentDidMount() {
this.updateParsedContent(null)
}
componentDidUpdate(prevProps) {
this.updateParsedContent(prevProps.content)
}
render() {
let { content, contentType, url, headers={}, getComponent } = this.props
const { parsedContent } = this.state
const HighlightCode = getComponent("highlightCode")
let body, bodyEl
url = url || ""
@@ -100,7 +66,7 @@ export default class ResponseBody extends React.PureComponent {
body = "can't parse JSON. Raw result:\n\n" + content
}
bodyEl = <HighlightCode downloadable value={ body } />
bodyEl = <HighlightCode value={ body } />
// XML
} else if (/xml/i.test(contentType)) {
@@ -108,11 +74,11 @@ export default class ResponseBody extends React.PureComponent {
textNodesOnSameLine: true,
indentor: " "
})
bodyEl = <HighlightCode downloadable value={ body } />
bodyEl = <HighlightCode value={ body } />
// HTML or Plain Text
} else if (lowerCase(contentType) === "text/html" || /text\/plain/.test(contentType)) {
bodyEl = <HighlightCode downloadable value={ content } />
bodyEl = <HighlightCode value={ content } />
// Image
} else if (/^image\//i.test(contentType)) {
@@ -126,25 +92,10 @@ export default class ResponseBody extends React.PureComponent {
} else if (/^audio\//i.test(contentType)) {
bodyEl = <pre><audio controls><source src={ url } type={ contentType } /></audio></pre>
} else if (typeof content === "string") {
bodyEl = <HighlightCode downloadable value={ content } />
bodyEl = <HighlightCode value={ content } />
} else if ( content.size > 0 ) {
// We don't know the contentType, but there was some content returned
if(parsedContent) {
// We were able to squeeze something out of content
// in `updateParsedContent`, so let's display it
bodyEl = <div>
<p className="i">
Unrecognized response type; displaying content as text.
</p>
<HighlightCode downloadable value={ parsedContent } />
</div>
} else {
// Give up
bodyEl = <p className="i">
Unrecognized response type; unable to display.
</p>
}
bodyEl = <div>Unknown response type</div>
} else {
// We don't know the contentType and there was no content returned
bodyEl = null
+2 -2
View File
@@ -37,12 +37,12 @@ export default class Schemes extends React.Component {
}
render() {
let { schemes, currentScheme } = this.props
let { schemes } = this.props
return (
<label htmlFor="schemes">
<span className="schemes-title">Schemes</span>
<select onChange={ this.onChange } value={currentScheme}>
<select onChange={ this.onChange }>
{ schemes.valueSeq().map(
( scheme ) => <option value={ scheme } key={ scheme }>{ scheme }</option>
).toArray()}
@@ -33,8 +33,7 @@ export default class HttpAuth extends React.Component {
let { onChange } = this.props
let { value, name } = e.target
let newValue = Object.assign({}, this.state.value)
let newValue = this.state.value || {}
if(name) {
newValue[name] = value
} else {
@@ -54,7 +53,7 @@ export default class HttpAuth extends React.Component {
const Markdown = getComponent( "Markdown" )
const JumpToPath = getComponent("JumpToPath", true)
const scheme = (schema.get("scheme") || "").toLowerCase()
const scheme = schema.get("scheme")
let value = this.getValue()
let errors = errSelectors.allErrors().filter( err => err.get("authId") === name)
@@ -126,7 +125,7 @@ export default class HttpAuth extends React.Component {
)
}
return <div>
<em><b>{name}</b> HTTP authentication: unsupported scheme {`'${scheme}'`}</em>
<em><b>{name}</b> HTTP authentication: unsupported or missing scheme</em>
</div>
}
}
-1
View File
@@ -632,7 +632,6 @@
> .microlight {
overflow-y: auto;
max-height: 400px;
min-height: 6em;
}
}
-44
View File
@@ -1,44 +0,0 @@
describe("bug #4196: HTTP basic auth credential retention", function () {
let mainPage
beforeEach(function (client, done) {
mainPage = client
.url("localhost:3230")
.page.main()
client.waitForElementVisible(".download-url-input", 5000)
.pause(80)
.clearValue(".download-url-input")
.setValue(".download-url-input", "http://localhost:3230/test-specs/bugs/4196.yaml")
.click("button.download-url-button")
.pause(1000)
done()
})
afterEach(function (client, done) {
done()
})
it("should display the most recent auth data across modal close/opens", function (client) {
client.waitForElementVisible(".opblock-tag-section", 10000)
.click("button.btn.authorize") // Open modal
.waitForElementVisible("section>input", 5000)
.setValue("section>input", "aaa") // Set user
.waitForElementVisible(`section>input[type="password"]`, 5000)
.setValue(`section>input[type="password"]`, "aaa") // Set password
.click(".auth-btn-wrapper button:nth-child(1)") // Click Authorize
.assert.containsText("div.wrapper:nth-child(4)>code", "aaa")
.click(".auth-btn-wrapper button:nth-child(2)") // Close modal
.pause(50)
.click("button.btn.authorize") // Open modal
.pause(50)
.click(".auth-btn-wrapper button:nth-child(1)") // Logout
.waitForElementVisible("section>input", 5000)
.setValue("section>input", "bbb") // Set user
.waitForElementVisible(`section>input[type="password"]`, 5000)
.setValue(`section>input[type="password"]`, "bbb") // Set password
.click(".auth-btn-wrapper button:nth-child(1)") // Click Authorize
.pause(5000)
.assert.containsText("div.wrapper:nth-child(4)>code", "bbb")
client.end()
})
})
+9 -19
View File
@@ -71,16 +71,6 @@ describe("render pet api container", function () {
client.end()
})
it("Testing post /pet api model values", function (client) {
apiWrapper.waitForElementVisible("@petOperationPostContainer", 5000)
.click("@petOperationPostCollpase")
.waitForElementVisible("@petOperationPostCollapseContainer", 5000)
.click("a.tablinks[data-name=model]")
.assert.containsText("span.model-title > .model-title__text", `Pet`)
client.end()
})
it("render put /pet api container", function (client) {
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
.assert.containsText("@petOperationPutTitle", "/pet")
@@ -91,10 +81,10 @@ describe("render pet api container", function () {
.waitForElementVisible("@petOperationPutExecuteBtn", 1000)
.click("@petOperationPutTryBtn")
.assert.cssClassNotPresent("@petOperationPutTryBtn", "cancel")
client.end()
})
it("Testing put /pet api Mock data", function (client) {
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
.click("@petOperationPutCollpase")
@@ -125,7 +115,7 @@ describe("render pet api container", function () {
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
.click("@petOperationGetByTagTryBtn")
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
client.end()
})
@@ -148,7 +138,7 @@ describe("render pet api container", function () {
client.end()
})
it("render get by ID /pet/{petId} api container", function (client) {
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000)
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}")
@@ -158,7 +148,7 @@ describe("render pet api container", function () {
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
.click("@petOperationGetByTagTryBtn")
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
client.end()
})
@@ -177,7 +167,7 @@ describe("render pet api container", function () {
.assert.attributeEquals("@petOperationGetByIdParameter", "title", "Value must be an integer")
.click("@petOperationGetByTagTryBtn")
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
client.end()
})
@@ -190,10 +180,10 @@ describe("render pet api container", function () {
.waitForElementVisible("@petOperationDeleteExecuteBtn", 1000)
.click("@petOperationDeleteTryBtn")
.assert.cssClassNotPresent("@petOperationDeleteTryBtn", "cancel")
client.end()
})
it("Testing delete /pet api Mock data", function (client) {
apiWrapper.waitForElementVisible("@petOperationDeleteContainer", 3000)
.click("@petOperationDeleteCollpase")
@@ -213,4 +203,4 @@ describe("render pet api container", function () {
client.end()
})
})
})
-85
View File
@@ -1,85 +0,0 @@
openapi: 3.0.0
info:
title: Demo API
description: First test
termsOfService: 'http://demo.io/terms-of-service/'
contact:
name: Demo Support
email: support@demo.io
version: 1.0.0
servers:
- url: '{server}/v1'
variables:
server:
default: https://api.demo.io
description: the API endpoint
paths:
/session:
put:
summary: Returns a new authentication token
tags:
- session
security:
- basicAuth: []
responses:
'201':
description: A session object
content:
application/json:
schema:
allOf:
- type: object
properties:
user_id:
type: string
format: uuid
readOnly: true
example: 110e8400-e29b-11d4-a716-446655440000
- $ref: '#/components/schemas/Session'
'401':
$ref: '#/components/responses/Unauthorized'
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
Session:
required:
- token
properties:
token:
type: string
readOnly: true
example: >-
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
Error:
required:
- message
properties:
message:
description: a human readable message explaining the error
type: string
reason:
description: a functionnal key about the error
type: string
responses:
Unauthorized:
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'