Can use `?name=NAME` to preselect.bubble
@@ -129,6 +129,7 @@ If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist` | |||||
Parameter Name | Description | Parameter Name | Description | ||||
--- | --- | --- | --- | ||||
url | The url pointing to API definition (normally `swagger.json` or `swagger.yaml`). | url | The url pointing to API definition (normally `swagger.json` or `swagger.yaml`). | ||||
urls | An array of API definition objects (`{url: "<url>", name: "<name>"}`) used by Topbar plugin. When used and Topbar plugin is enabled, the `url` parameter will not be parsed. | |||||
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. | 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. | 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. | dom_id | The id of a dom element inside which SwaggerUi will put the user interface for swagger. | ||||
@@ -143,7 +144,7 @@ displayOperationId | Controls the display of operationId in operations list. The | |||||
### Plugins | ### Plugins | ||||
#### Topbar plugin | #### 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`: | |||||
Topbar plugin enables top bar with input for spec path and explore button or a dropdown if `urls` is used. When using the dropdown, a query parameter `name` can be passed to select that API. 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 = [ | let preset = [ | ||||
@@ -6,7 +6,7 @@ import ApisPreset from "core/presets/apis" | |||||
import * as AllPlugins from "core/plugins/all" | import * as AllPlugins from "core/plugins/all" | ||||
import { parseSeach, filterConfigs } from "core/utils" | import { parseSeach, filterConfigs } from "core/utils" | ||||
const CONFIGS = [ "url", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion", | |||||
const CONFIGS = [ "url", "urls", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion", | |||||
"apisSorter", "operationsSorter", "supportedSubmitMethods", "dom_id", "defaultModelRendering", "oauth2RedirectUrl", | "apisSorter", "operationsSorter", "supportedSubmitMethods", "dom_id", "defaultModelRendering", "oauth2RedirectUrl", | ||||
"showRequestHeaders", "custom", "modelPropertyMacro", "parameterMacro", "displayOperationId" ] | "showRequestHeaders", "custom", "modelPropertyMacro", "parameterMacro", "displayOperationId" ] | ||||
@@ -23,6 +23,7 @@ module.exports = function SwaggerUI(opts) { | |||||
dom_id: null, | dom_id: null, | ||||
spec: {}, | spec: {}, | ||||
url: "", | url: "", | ||||
urls: null, | |||||
layout: "BaseLayout", | layout: "BaseLayout", | ||||
docExpansion: "list", | docExpansion: "list", | ||||
validatorUrl: "https://online.swagger.io/validator", | validatorUrl: "https://online.swagger.io/validator", | ||||
@@ -2,12 +2,13 @@ import React, { PropTypes } from "react" | |||||
//import "./topbar.less" | //import "./topbar.less" | ||||
import Logo from "./logo_small.png" | import Logo from "./logo_small.png" | ||||
import { parseSeach } from "core/utils" | |||||
export default class Topbar extends React.Component { | export default class Topbar extends React.Component { | ||||
constructor(props, context) { | constructor(props, context) { | ||||
super(props, context) | super(props, context) | ||||
this.state = { url: props.specSelectors.url() } | |||||
this.state = { url: props.specSelectors.url(), selectedIndex: 0 } | |||||
} | } | ||||
componentWillReceiveProps(nextProps) { | componentWillReceiveProps(nextProps) { | ||||
@@ -19,14 +20,49 @@ export default class Topbar extends React.Component { | |||||
this.setState({url: value}) | this.setState({url: value}) | ||||
} | } | ||||
loadSpec = (url) => { | |||||
this.props.specActions.updateUrl(url) | |||||
this.props.specActions.download(url) | |||||
} | |||||
onUrlSelect =(e)=> { | |||||
let url = e.target.value || e.target.href | |||||
this.loadSpec(url) | |||||
e.preventDefault() | |||||
} | |||||
downloadUrl = (e) => { | downloadUrl = (e) => { | ||||
this.props.specActions.updateUrl(this.state.url) | |||||
this.props.specActions.download(this.state.url) | |||||
this.loadSpec(this.state.url) | |||||
e.preventDefault() | e.preventDefault() | ||||
} | } | ||||
componentWillMount() { | |||||
const urls = this.props.getConfigs().urls || [] | |||||
if(urls && urls.length) { | |||||
let selectedName = parseSeach().name | |||||
if(selectedName) | |||||
{ | |||||
urls.forEach((spec, i) => { | |||||
if(spec.name === selectedName) | |||||
{ | |||||
this.setState({selectedIndex: i}) | |||||
} | |||||
}) | |||||
} | |||||
} | |||||
} | |||||
componentDidMount() { | |||||
const urls = this.props.getConfigs().urls || [] | |||||
if(urls && urls.length) { | |||||
this.loadSpec(urls[this.state.selectedIndex].url) | |||||
} | |||||
} | |||||
render() { | render() { | ||||
let { getComponent, specSelectors } = this.props | |||||
let { getComponent, specSelectors, getConfigs } = this.props | |||||
const Button = getComponent("Button") | const Button = getComponent("Button") | ||||
const Link = getComponent("Link") | const Link = getComponent("Link") | ||||
@@ -36,22 +72,39 @@ export default class Topbar extends React.Component { | |||||
let inputStyle = {} | let inputStyle = {} | ||||
if(isFailed) inputStyle.color = "red" | if(isFailed) inputStyle.color = "red" | ||||
if(isLoading) inputStyle.color = "#aaa" | if(isLoading) inputStyle.color = "#aaa" | ||||
const { urls } = getConfigs() | |||||
let control = [] | |||||
let formOnSubmit = null | |||||
if(urls) { | |||||
let rows = [] | |||||
urls.forEach((link, i) => { | |||||
rows.push(<option key={i} value={link.url} selected={i===this.state.selectedIndex}>{link.name}</option>) | |||||
}) | |||||
control.push(<select disabled={isLoading} onChange={ this.onUrlSelect }>{rows}</select>) | |||||
} | |||||
else { | |||||
formOnSubmit = this.downloadUrl | |||||
control.push(<input className="download-url-input" type="text" onChange={ this.onUrlChange } value={this.state.url} disabled={isLoading} style={inputStyle} />) | |||||
control.push(<Button className="download-url-button" onClick={ this.downloadUrl }>Explore</Button>) | |||||
} | |||||
return ( | return ( | ||||
<div className="topbar"> | |||||
<div className="wrapper"> | |||||
<div className="topbar-wrapper"> | |||||
<Link href="#" title="Swagger UX"> | |||||
<img height="30" width="30" src={ Logo } alt="Swagger UX"/> | |||||
<span>swagger</span> | |||||
</Link> | |||||
<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} /> | |||||
<Button className="download-url-button" onClick={ this.downloadUrl }>Explore</Button> | |||||
</form> | |||||
</div> | |||||
<div className="topbar"> | |||||
<div className="wrapper"> | |||||
<div className="topbar-wrapper"> | |||||
<Link href="#" title="Swagger UX"> | |||||
<img height="30" width="30" src={ Logo } alt="Swagger UX"/> | |||||
<span>swagger</span> | |||||
</Link> | |||||
<form className="download-url-wrapper" onSubmit={formOnSubmit}> | |||||
{control} | |||||
</form> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
) | ) | ||||
} | } | ||||
} | } | ||||
@@ -59,5 +112,6 @@ export default class Topbar extends React.Component { | |||||
Topbar.propTypes = { | Topbar.propTypes = { | ||||
specSelectors: PropTypes.object.isRequired, | specSelectors: PropTypes.object.isRequired, | ||||
specActions: PropTypes.object.isRequired, | specActions: PropTypes.object.isRequired, | ||||
getComponent: PropTypes.func.isRequired | |||||
getComponent: PropTypes.func.isRequired, | |||||
getConfigs: PropTypes.func.isRequired | |||||
} | } |
@@ -34,8 +34,8 @@ | |||||
.download-url-wrapper | .download-url-wrapper | ||||
{ | { | ||||
display: flex; | display: flex; | ||||
flex: 3; | flex: 3; | ||||
justify-content: flex-end; | |||||
input[type=text] | input[type=text] | ||||
{ | { | ||||
@@ -48,6 +48,15 @@ | |||||
outline: none; | outline: none; | ||||
} | } | ||||
select | |||||
{ | |||||
min-width: 200px; | |||||
border: 2px solid #547f00; | |||||
outline: none; | |||||
box-shadow: none; | |||||
} | |||||
.download-url-button | .download-url-button | ||||
{ | { | ||||
font-size: 16px; | font-size: 16px; | ||||