Skip to content

Commit

Permalink
Updated Topbar with a select option if urls is passed.
Browse files Browse the repository at this point in the history
Can use `?name=NAME` to preselect.
  • Loading branch information
supergibbs committed Jun 20, 2017
1 parent 4536eba commit 2e40f59
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 21 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist`
Parameter Name | Description
--- | ---
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.
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.
Expand All @@ -143,7 +144,7 @@ displayOperationId | Controls the display of operationId in operations list. The
### 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`:
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 = [
Expand Down
3 changes: 2 additions & 1 deletion src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ApisPreset from "core/presets/apis"
import * as AllPlugins from "core/plugins/all"
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",
"showRequestHeaders", "custom", "modelPropertyMacro", "parameterMacro", "displayOperationId" ]

Expand All @@ -23,6 +23,7 @@ module.exports = function SwaggerUI(opts) {
dom_id: null,
spec: {},
url: "",
urls: null,
layout: "BaseLayout",
docExpansion: "list",
validatorUrl: "https://online.swagger.io/validator",
Expand Down
90 changes: 72 additions & 18 deletions src/plugins/topbar/topbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import React, { PropTypes } from "react"

//import "./topbar.less"
import Logo from "./logo_small.png"
import { parseSeach } from "core/utils"

export default class Topbar extends React.Component {

constructor(props, context) {
super(props, context)
this.state = { url: props.specSelectors.url() }
this.state = { url: props.specSelectors.url(), selectedIndex: 0 }
}

componentWillReceiveProps(nextProps) {
Expand All @@ -19,14 +20,49 @@ export default class Topbar extends React.Component {
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) => {
this.props.specActions.updateUrl(this.state.url)
this.props.specActions.download(this.state.url)
this.loadSpec(this.state.url)
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() {
let { getComponent, specSelectors } = this.props
let { getComponent, specSelectors, getConfigs } = this.props
const Button = getComponent("Button")
const Link = getComponent("Link")

Expand All @@ -36,28 +72,46 @@ export default class Topbar extends React.Component {
let inputStyle = {}
if(isFailed) inputStyle.color = "red"
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 (
<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>
)
}
}

Topbar.propTypes = {
specSelectors: PropTypes.object.isRequired,
specActions: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired
}
11 changes: 10 additions & 1 deletion src/style/_topbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
.download-url-wrapper
{
display: flex;

flex: 3;
justify-content: flex-end;

input[type=text]
{
Expand All @@ -48,6 +48,15 @@
outline: none;
}

select
{
min-width: 200px;

border: 2px solid #547f00;
outline: none;
box-shadow: none;
}

.download-url-button
{
font-size: 16px;
Expand Down

1 comment on commit 2e40f59

@edesdan
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty handy!! Thanks!

Please sign in to comment.