Browse Source

Updated Topbar with a select option if `urls` is passed.

Can use `?name=NAME` to preselect.
bubble
Jesse Mandel 7 years ago
parent
commit
2e40f59cad
4 changed files with 86 additions and 21 deletions
  1. +2
    -1
      README.md
  2. +2
    -1
      src/core/index.js
  3. +72
    -18
      src/plugins/topbar/topbar.jsx
  4. +10
    -1
      src/style/_topbar.scss

+ 2
- 1
README.md View File

@@ -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.
@@ -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 = [


+ 2
- 1
src/core/index.js View File

@@ -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" ]

@@ -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",


+ 72
- 18
src/plugins/topbar/topbar.jsx View File

@@ -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) {
@@ -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")

@@ -36,22 +72,39 @@ 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>
)
}
}
@@ -59,5 +112,6 @@ export default class Topbar extends React.Component {
Topbar.propTypes = {
specSelectors: PropTypes.object.isRequired,
specActions: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired
}

+ 10
- 1
src/style/_topbar.scss View File

@@ -34,8 +34,8 @@
.download-url-wrapper
{
display: flex;

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

input[type=text]
{
@@ -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;


Loading…
Cancel
Save