Added maxRows and filter support

Useful for the display of very large swagger specs. Can limit the number of operations to a smaller value and search
This commit is contained in:
Gwyn Judd
2017-06-07 16:29:46 +12:00
parent 42efd8a60e
commit c3f9c094d1
6 changed files with 61 additions and 9 deletions

View File

@@ -144,6 +144,8 @@ modelPropertyMacro | MUST be a function. Function to set default values to each
docExpansion | Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing). The default is 'list'.
displayOperationId | Controls the display of operationId in operations list. The default is `false`.
displayRequestDuration | Controls the display of the request duration (in milliseconds) for `Try it out` requests. The default is `false`.
maxDisplayedTags | If set, limits the number of tagged operations displayed to at most this many. The default is to show all operations.
filter | If set, enables filtering. The top bar will show an edit box that you can use to filter the tagged operations that are shown. Can be true/false to enable or disable, or an explicit filter string in which case filtering will be enabled using that string as the filter expression. Filtering is case sensitive matching the filter expression anywhere inside the tag.
### Plugins

View File

@@ -10,11 +10,12 @@ export default class BaseLayout extends React.Component {
specSelectors: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object.isRequired,
layoutActions: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired
getComponent: PropTypes.func.isRequired,
filter: PropTypes.string.isRequired
}
render() {
let { specSelectors, specActions, getComponent } = this.props
let { specSelectors, specActions, getComponent, filter } = this.props
let info = specSelectors.info()
let url = specSelectors.url()
@@ -66,7 +67,7 @@ export default class BaseLayout extends React.Component {
<Row>
<Col mobile={12} desktop={12} >
<Operations/>
<Operations filter={ filter }/>
</Col>
</Row>
<Row>

View File

@@ -11,7 +11,8 @@ export default class Operations extends React.Component {
layoutActions: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired,
authSelectors: PropTypes.object.isRequired,
getConfigs: PropTypes.func.isRequired
getConfigs: PropTypes.func.isRequired,
filter: PropTypes.string.isRequired
};
render() {
@@ -24,6 +25,7 @@ export default class Operations extends React.Component {
authActions,
authSelectors,
getConfigs,
filter,
fn
} = this.props
@@ -33,7 +35,19 @@ export default class Operations extends React.Component {
const Collapse = getComponent("Collapse")
let showSummary = layoutSelectors.showSummary()
let { docExpansion, displayOperationId, displayRequestDuration } = getConfigs()
let { docExpansion, displayOperationId, displayRequestDuration, maxDisplayedTags } = getConfigs()
if (filter) {
if (filter !== true) {
taggedOps = taggedOps.filter((tagObj, tag) => {
return tag.indexOf(filter) !== -1
})
}
}
if (maxDisplayedTags && !isNaN(maxDisplayedTags) && maxDisplayedTags >= 0) {
taggedOps = taggedOps.slice(0, maxDisplayedTags)
}
return (
<div>

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", "urls", "urls.primaryName", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion",
const CONFIGS = [ "url", "urls", "urls.primaryName", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion", "maxDisplayedTags", "filter",
"apisSorter", "operationsSorter", "supportedSubmitMethods", "dom_id", "defaultModelRendering", "oauth2RedirectUrl",
"showRequestHeaders", "custom", "modelPropertyMacro", "parameterMacro", "displayOperationId" , "displayRequestDuration"]
@@ -26,6 +26,8 @@ module.exports = function SwaggerUI(opts) {
urls: null,
layout: "BaseLayout",
docExpansion: "list",
maxDisplayedTags: null,
filter: null,
validatorUrl: "https://online.swagger.io/validator",
configs: {},
custom: {},

View File

@@ -6,6 +6,11 @@ import Logo from "./logo_small.png"
export default class Topbar extends React.Component {
static propTypes = {
onFilterChange: PropTypes.func.isRequired,
filter: PropTypes.string.isRequired
}
constructor(props, context) {
super(props, context)
this.state = { url: props.specSelectors.url(), selectedIndex: 0 }
@@ -80,6 +85,11 @@ export default class Topbar extends React.Component {
}
}
onFilterChange =(e) => {
let {target: {value}} = e
this.props.onFilterChange(value)
}
render() {
let { getComponent, specSelectors, getConfigs } = this.props
const Button = getComponent("Button")
@@ -87,6 +97,7 @@ export default class Topbar extends React.Component {
let isLoading = specSelectors.loadingStatus() === "loading"
let isFailed = specSelectors.loadingStatus() === "failed"
let filter = this.props.filter
let inputStyle = {}
if(isFailed) inputStyle.color = "red"
@@ -124,6 +135,10 @@ export default class Topbar extends React.Component {
<img height="30" width="30" src={ Logo } alt="Swagger UX"/>
<span>swagger</span>
</Link>
{
filter === null || filter === false ? null :
<input className="operation-filter-input" placeholder="filter..." type="text" onChange={this.onFilterChange} value={filter === true ? "" : filter} disabled={isLoading} style={inputStyle} />
}
<form className="download-url-wrapper" onSubmit={formOnSubmit}>
{control}
</form>

View File

@@ -10,7 +10,23 @@ export default class StandaloneLayout extends React.Component {
specSelectors: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object.isRequired,
layoutActions: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired
}
constructor(props) {
super(props)
this.handleFilterChange = this.handleFilterChange.bind(this)
let { getConfigs } = this.props
let { filter } = getConfigs()
this.state = { filter: filter }
}
handleFilterChange(filter) {
this.setState({ filter: filter })
}
render() {
@@ -24,12 +40,14 @@ export default class StandaloneLayout extends React.Component {
const BaseLayout = getComponent("BaseLayout", true)
const OnlineValidatorBadge = getComponent("onlineValidatorBadge", true)
const filter = this.state.filter
const loadingStatus = specSelectors.loadingStatus()
return (
<Container className='swagger-ui'>
{ Topbar ? <Topbar/> : null }
{ Topbar ? <Topbar onFilterChange={this.handleFilterChange} filter={ filter } /> : null }
{ loadingStatus === "loading" &&
<div className="info">
<h4 className="title">Loading...</h4>
@@ -45,7 +63,7 @@ export default class StandaloneLayout extends React.Component {
<h4 className="title">Failed to load config.</h4>
</div>
}
{ !loadingStatus || loadingStatus === "success" && <BaseLayout/> }
{ !loadingStatus || loadingStatus === "success" && <BaseLayout filter={filter} /> }
<Row>
<Col>
<OnlineValidatorBadge />