Merge branch 'master' into searchbar-update
This commit is contained in:
@@ -64,11 +64,10 @@ export default class ApiKeyAuth extends React.Component {
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Value:</label>
|
||||
<Col>
|
||||
{
|
||||
value || <Input type="text" onChange={ this.onChange }/>
|
||||
}
|
||||
</Col>
|
||||
{
|
||||
value ? <code> ****** </code>
|
||||
: <Col><Input type="text" onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
errors.valueSeq().map( (error, key) => {
|
||||
|
||||
@@ -6,7 +6,7 @@ export default class AuthorizeBtn extends React.Component {
|
||||
}
|
||||
|
||||
onClick =() => {
|
||||
let { authActions, authSelectors, errActions} = this.props
|
||||
let { authActions, authSelectors } = this.props
|
||||
let definitions = authSelectors.definitionsToAuthorize()
|
||||
|
||||
authActions.showDefinitions(definitions)
|
||||
|
||||
@@ -16,6 +16,10 @@ export default class AuthorizeOperationBtn extends React.Component {
|
||||
|
||||
let isAuthorized = authSelectors.isAuthorized(security)
|
||||
|
||||
if(isAuthorized === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={isAuthorized ? "authorization__btn locked" : "authorization__btn unlocked"} onClick={ this.onClick }>
|
||||
<svg width="20" height="20">
|
||||
|
||||
@@ -42,14 +42,12 @@ export default class Auths extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { definitions, getComponent, authSelectors, errSelectors, specSelectors } = this.props
|
||||
let { definitions, getComponent, authSelectors, errSelectors } = this.props
|
||||
const ApiKeyAuth = getComponent("apiKeyAuth")
|
||||
const BasicAuth = getComponent("basicAuth")
|
||||
const Oauth2 = getComponent("oauth2", true)
|
||||
const Button = getComponent("Button")
|
||||
const JumpToPath = getComponent("JumpToPath", true)
|
||||
|
||||
let specStr = specSelectors.specStr()
|
||||
let authorized = authSelectors.authorized()
|
||||
|
||||
let authorizedAuth = definitions.filter( (definition, key) => {
|
||||
|
||||
@@ -63,19 +63,23 @@ export default class BasicAuth extends React.Component {
|
||||
source={ schema.get("description") } />
|
||||
</Row>
|
||||
<Row>
|
||||
<Col tablet={2} desktop={2}>username:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
username || <Input type="text" required="required" name="username" onChange={ this.onChange }/>
|
||||
}
|
||||
</Col>
|
||||
<label>Username:</label>
|
||||
{
|
||||
username ? <code> { username } </code>
|
||||
: <Col><Input type="text" required="required" name="username" onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Password:</label>
|
||||
{
|
||||
username ? <code> ****** </code>
|
||||
: <Col><Input required="required"
|
||||
autoComplete="new-password"
|
||||
name="password"
|
||||
type="password"
|
||||
onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
!username && <Row>
|
||||
<Col tablet={2} desktop={2}>password:</Col>
|
||||
<Col tablet={10} desktop={10}><Input required="required" autoComplete="new-password" name="password" type="password" onChange={ this.onChange }/></Col>
|
||||
</Row>
|
||||
}
|
||||
{
|
||||
errors.valueSeq().map( (error, key) => {
|
||||
return <AuthError error={ error }
|
||||
|
||||
@@ -10,13 +10,13 @@ export default class Oauth2 extends React.Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string,
|
||||
authorized: PropTypes.object,
|
||||
configs: PropTypes.object,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
schema: PropTypes.object.isRequired,
|
||||
authSelectors: PropTypes.object.isRequired,
|
||||
authActions: PropTypes.object.isRequired,
|
||||
errSelectors: PropTypes.object.isRequired,
|
||||
errActions: PropTypes.object.isRequired
|
||||
errActions: PropTypes.object.isRequired,
|
||||
getConfigs: PropTypes.any
|
||||
}
|
||||
|
||||
constructor(props, context) {
|
||||
@@ -26,7 +26,7 @@ export default class Oauth2 extends React.Component {
|
||||
let username = auth && auth.get("username") || ""
|
||||
let clientId = auth && auth.get("clientId") || ""
|
||||
let clientSecret = auth && auth.get("clientSecret") || ""
|
||||
let passwordType = auth && auth.get("passwordType") || "none"
|
||||
let passwordType = auth && auth.get("passwordType") || "basic"
|
||||
|
||||
this.state = {
|
||||
name: name,
|
||||
@@ -108,71 +108,74 @@ export default class Oauth2 extends React.Component {
|
||||
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
||||
|
||||
{
|
||||
flow === PASSWORD && ( !isAuthorized || isAuthorized && this.state.username) && <Row>
|
||||
<Col tablet={2} desktop={2}>username:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
flow !== PASSWORD ? null
|
||||
: <Row>
|
||||
<Row>
|
||||
<label htmlFor="oauth_username">username:</label>
|
||||
{
|
||||
isAuthorized ? <code> { this.state.username } </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="oauth_username" type="text" data-name="username" onChange={ this.onInputChange }/>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.username }</span>
|
||||
: <input type="text" data-name="username" onChange={ this.onInputChange }/>
|
||||
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<label htmlFor="oauth_password">password:</label>
|
||||
{
|
||||
isAuthorized ? <code> ****** </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="oauth_password" type="password" data-name="password" onChange={ this.onInputChange }/>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
<Row>
|
||||
<label htmlFor="password_type">type:</label>
|
||||
{
|
||||
isAuthorized ? <code> { this.state.passwordType } </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<select id="password_type" data-name="passwordType" onChange={ this.onInputChange }>
|
||||
<option value="basic">Basic auth</option>
|
||||
<option value="request-body">Request body</option>
|
||||
<option value="query">Query parameters</option>
|
||||
</select>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
flow === PASSWORD && !isAuthorized && <Row>
|
||||
<Col tablet={2} desktop={2}>password:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
<input type="password" data-name="password" onChange={ this.onInputChange }/>
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
flow === PASSWORD && <Row>
|
||||
<Col tablet={2} desktop={2}>type:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.passwordType }</span>
|
||||
: <select data-name="passwordType" onChange={ this.onInputChange }>
|
||||
<option value="none">None or other</option>
|
||||
<option value="basic">Basic auth</option>
|
||||
<option value="request">Request body</option>
|
||||
</select>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
( flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) &&
|
||||
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) &&
|
||||
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
|
||||
<label htmlFor="client_id">client_id:</label>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.clientId }</span>
|
||||
: <input id="client_id" type="text" required={ flow === PASSWORD } data-name="clientId"
|
||||
{
|
||||
isAuthorized ? <code> ****** </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="client_id" type="text" required={ flow === PASSWORD } data-name="clientId"
|
||||
onChange={ this.onInputChange }/>
|
||||
}
|
||||
</Col>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
( flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) && <Row>
|
||||
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && <Row>
|
||||
<label htmlFor="client_secret">client_secret:</label>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.clientSecret }</span>
|
||||
: <input id="client_secret" type="text" data-name="clientSecret"
|
||||
{
|
||||
isAuthorized ? <code> ****** </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="client_secret" type="text" data-name="clientSecret"
|
||||
onChange={ this.onInputChange }/>
|
||||
}
|
||||
</Col>
|
||||
</Col>
|
||||
}
|
||||
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
!isAuthorized && flow !== PASSWORD && scopes && scopes.size ? <div className="scopes">
|
||||
!isAuthorized && scopes && scopes.size ? <div className="scopes">
|
||||
<h2>Scopes:</h2>
|
||||
{ scopes.map((description, name) => {
|
||||
return (
|
||||
@@ -205,7 +208,7 @@ export default class Oauth2 extends React.Component {
|
||||
} )
|
||||
}
|
||||
<div className="auth-btn-wrapper">
|
||||
{ isValid && flow !== APPLICATION &&
|
||||
{ isValid &&
|
||||
( isAuthorized ? <Button className="btn modal-btn auth authorize" onClick={ this.logout }>Logout</Button>
|
||||
: <Button className="btn modal-btn auth authorize" onClick={ this.authorize }>Authorize</Button>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { PropTypes } from "react"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import { fromJS } from 'immutable'
|
||||
import { fromJS } from "immutable"
|
||||
|
||||
const noop = ()=>{}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export default class Curl extends React.Component {
|
||||
<div>
|
||||
<h4>Curl</h4>
|
||||
<div className="copy-paste">
|
||||
<textarea onFocus={this.handleFocus} className="curl" style={{ whiteSpace: "normal" }} defaultValue={curl}></textarea>
|
||||
<textarea onFocus={this.handleFocus} className="curl" style={{ whiteSpace: "normal" }} value={curl}></textarea>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { PropTypes } from "react"
|
||||
import Im, { List } from "immutable"
|
||||
import { List } from "immutable"
|
||||
import Collapse from "react-collapse"
|
||||
import sortBy from "lodash/sortBy"
|
||||
|
||||
export default class Errors extends React.Component {
|
||||
|
||||
@@ -69,7 +68,7 @@ const ThrownErrorItem = ( { error, jumpToLine } ) => {
|
||||
{ error.get("message") }
|
||||
</span>
|
||||
<div>
|
||||
{ errorLine ? <a onClick={jumpToLine.bind(null, errorLine)}>Jump to line { errorLine }</a> : null }
|
||||
{ errorLine && jumpToLine ? <a onClick={jumpToLine.bind(null, errorLine)}>Jump to line { errorLine }</a> : null }
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -78,11 +77,23 @@ const ThrownErrorItem = ( { error, jumpToLine } ) => {
|
||||
}
|
||||
|
||||
const SpecErrorItem = ( { error, jumpToLine } ) => {
|
||||
let locationMessage = null
|
||||
|
||||
if(error.get("path")) {
|
||||
if(List.isList(error.get("path"))) {
|
||||
locationMessage = <small>at { error.get("path").join(".") }</small>
|
||||
} else {
|
||||
locationMessage = <small>at { error.get("path") }</small>
|
||||
}
|
||||
} else if(error.get("line") && !jumpToLine) {
|
||||
locationMessage = <small>on line { error.get("line") }</small>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="error-wrapper">
|
||||
{ !error ? null :
|
||||
<div>
|
||||
<h4>{ toTitleCase(error.get("source")) + " " + error.get("level") }{ error.get("path") ? <small> at {List.isList(error.get("path")) ? error.get("path").join(".") : error.get("path")}</small>: null }</h4>
|
||||
<h4>{ toTitleCase(error.get("source")) + " " + error.get("level") } { locationMessage }</h4>
|
||||
<span style={{ whiteSpace: "pre-line"}}>{ error.get("message") }</span>
|
||||
<div>
|
||||
{ jumpToLine ? (
|
||||
@@ -107,6 +118,10 @@ ThrownErrorItem.propTypes = {
|
||||
jumpToLine: PropTypes.func
|
||||
}
|
||||
|
||||
ThrownErrorItem.defaultProps = {
|
||||
jumpToLine: null
|
||||
}
|
||||
|
||||
SpecErrorItem.propTypes = {
|
||||
error: PropTypes.object.isRequired,
|
||||
jumpToLine: PropTypes.func
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { Component, PropTypes } from "react"
|
||||
import { fromJS } from "immutable"
|
||||
|
||||
export default class Execute extends Component {
|
||||
|
||||
@@ -29,9 +28,6 @@ export default class Execute extends Component {
|
||||
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue([this.props.path, this.props.method], val)
|
||||
|
||||
render(){
|
||||
let { getComponent, operation, specActions, path, method } = this.props
|
||||
const ContentType = getComponent( "contentType" )
|
||||
|
||||
return (
|
||||
<button className="btn execute opblock-control__btn" onClick={ this.onClick }>
|
||||
Execute
|
||||
|
||||
@@ -58,7 +58,7 @@ class License extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
url ? <a href={ url }>{ name }</a>
|
||||
url ? <a target="_blank" href={ url }>{ name }</a>
|
||||
: <span>{ name }</span>
|
||||
}
|
||||
</div>
|
||||
@@ -95,7 +95,7 @@ export default class Info extends React.Component {
|
||||
{ version && <small><pre className="version"> { version } </pre></small> }
|
||||
</h2>
|
||||
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
|
||||
{ url && <a href={ url }><span className="url"> { url } </span></a> }
|
||||
{ url && <a target="_blank" href={ url }><span className="url"> { url } </span></a> }
|
||||
</hgroup>
|
||||
|
||||
<div className="description">
|
||||
@@ -104,7 +104,7 @@ export default class Info extends React.Component {
|
||||
|
||||
{
|
||||
termsOfService && <div>
|
||||
<a href={ termsOfService }>Terms of service</a>
|
||||
<a target="_blank" href={ termsOfService }>Terms of service</a>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ import React, { PropTypes } from "react"
|
||||
import OriCollapse from "react-collapse"
|
||||
import _Markdown from "react-remarkable"
|
||||
|
||||
const noop = () => {}
|
||||
|
||||
function xclass(...args) {
|
||||
return args.filter(a => !!a).join(" ").trim()
|
||||
}
|
||||
@@ -18,7 +16,7 @@ export class Container extends React.Component {
|
||||
if(fullscreen)
|
||||
return <section {...rest}/>
|
||||
|
||||
let containerClass = "container" + (full ? "-full" : "")
|
||||
let containerClass = "swagger-container" + (full ? "-full" : "")
|
||||
return (
|
||||
<section {...rest} className={xclass(rest.className, containerClass)}/>
|
||||
)
|
||||
@@ -44,12 +42,14 @@ export class Col extends React.Component {
|
||||
const {
|
||||
hide,
|
||||
keepContents,
|
||||
|
||||
mobile, /* we don't want these in the final component, since React now complains. So we extract them */
|
||||
/* we don't want these in the `rest` object that passes to the final component,
|
||||
since React now complains. So we extract them */
|
||||
/* eslint-disable no-unused-vars */
|
||||
mobile,
|
||||
tablet,
|
||||
desktop,
|
||||
large,
|
||||
|
||||
/* eslint-enable no-unused-vars */
|
||||
...rest
|
||||
} = this.props
|
||||
|
||||
|
||||
80
src/core/components/layouts/base.jsx
Normal file
80
src/core/components/layouts/base.jsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import React, { PropTypes } from "react"
|
||||
|
||||
export default class BaseLayout extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
errSelectors: PropTypes.object.isRequired,
|
||||
errActions: PropTypes.object.isRequired,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
let { specSelectors, specActions, getComponent } = this.props
|
||||
|
||||
let info = specSelectors.info()
|
||||
let url = specSelectors.url()
|
||||
let basePath = specSelectors.basePath()
|
||||
let host = specSelectors.host()
|
||||
let securityDefinitions = specSelectors.securityDefinitions()
|
||||
let externalDocs = specSelectors.externalDocs()
|
||||
let schemes = specSelectors.schemes()
|
||||
|
||||
let Info = getComponent("info")
|
||||
let Operations = getComponent("operations", true)
|
||||
let Models = getComponent("models", true)
|
||||
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
||||
let Row = getComponent("Row")
|
||||
let Col = getComponent("Col")
|
||||
let Errors = getComponent("errors", true)
|
||||
const Schemes = getComponent("schemes")
|
||||
|
||||
const isSpecEmpty = !specSelectors.specStr()
|
||||
|
||||
if(isSpecEmpty) {
|
||||
return <h4>No spec provided.</h4>
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
<div className='swagger-ui'>
|
||||
<div>
|
||||
<Errors/>
|
||||
<Row className="information-container">
|
||||
<Col mobile={12}>
|
||||
{ info.count() ? (
|
||||
<Info info={ info } url={ url } host={ host } basePath={ basePath } externalDocs={externalDocs} getComponent={getComponent}/>
|
||||
) : null }
|
||||
</Col>
|
||||
</Row>
|
||||
{ schemes && schemes.size || securityDefinitions ? (
|
||||
<div className="scheme-container">
|
||||
<Col className="schemes wrapper" mobile={12}>
|
||||
{ schemes && schemes.size ? (
|
||||
<Schemes schemes={ schemes } specActions={ specActions } />
|
||||
) : null }
|
||||
{ securityDefinitions ? (
|
||||
<AuthorizeBtn />
|
||||
) : null }
|
||||
</Col>
|
||||
</div>
|
||||
) : null }
|
||||
|
||||
<Row>
|
||||
<Col mobile={12} desktop={12} >
|
||||
<Operations/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col mobile={12} desktop={12} >
|
||||
<Models/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { Component, PropTypes } from "react"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import isObject from "lodash/isObject"
|
||||
import { List } from "immutable"
|
||||
const braceOpen = "{"
|
||||
const braceClose = "}"
|
||||
|
||||
const propStyle = { color: "#999", fontStyle: "italic" }
|
||||
|
||||
const EnumModel = ({ value }) => {
|
||||
let collapsedContent = <span>Array [ { value.count() } ]</span>
|
||||
return <span className="prop-enum">
|
||||
@@ -128,10 +129,8 @@ class Primitive extends Component {
|
||||
let format = schema.get("format")
|
||||
let xml = schema.get("xml")
|
||||
let enumArray = schema.get("enum")
|
||||
let description = schema.get("description")
|
||||
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "$$ref"].indexOf(key) === -1 )
|
||||
let style = required ? { fontWeight: "bold" } : {}
|
||||
let propStyle = { color: "#999", fontStyle: "italic" }
|
||||
|
||||
return <span className="prop">
|
||||
<span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>}
|
||||
@@ -169,12 +168,23 @@ class ArrayModel extends Component {
|
||||
render(){
|
||||
let { required, schema, depth, expandDepth } = this.props
|
||||
let items = schema.get("items")
|
||||
let properties = schema.filter( ( v, key) => ["type", "items", "$$ref"].indexOf(key) === -1 )
|
||||
|
||||
return <span>
|
||||
return <span className="model">
|
||||
<span className="model-title">
|
||||
<span className="model-title__text">{ schema.get("title") }</span>
|
||||
</span>
|
||||
<Collapse collapsed={ depth > expandDepth } collapsedContent="[...]">
|
||||
[
|
||||
<span><Model { ...this.props } schema={ items } required={ false }/></span>
|
||||
]
|
||||
{
|
||||
properties.size ? <span>
|
||||
{ properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={propStyle}>
|
||||
<br />{ `${key}:`}{ String(v) }</span>)
|
||||
}<br /></span>
|
||||
: null
|
||||
}
|
||||
</Collapse>
|
||||
{ required && <span style={{ color: "red" }}>*</span>}
|
||||
</span>
|
||||
@@ -251,9 +261,6 @@ export default class ModelComponent extends Component {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { name, schema } = this.props
|
||||
let title = schema.get("title") || name
|
||||
|
||||
return <div className="model-box">
|
||||
<Model { ...this.props } depth={ 1 } expandDepth={ this.props.expandDepth || 0 }/>
|
||||
</div>
|
||||
|
||||
@@ -4,13 +4,15 @@ import React, { Component, PropTypes } from "react"
|
||||
export default class Models extends Component {
|
||||
static propTypes = {
|
||||
getComponent: PropTypes.func,
|
||||
specSelectors: PropTypes.object
|
||||
specSelectors: PropTypes.object,
|
||||
layoutSelectors: PropTypes.object,
|
||||
layoutActions: PropTypes.object
|
||||
}
|
||||
|
||||
render(){
|
||||
let { specSelectors, getComponent, layoutSelectors, layoutActions } = this.props
|
||||
let definitions = specSelectors.definitions()
|
||||
let showModels = layoutSelectors.isShown('models', true)
|
||||
let showModels = layoutSelectors.isShown("models", true)
|
||||
|
||||
const Model = getComponent("model")
|
||||
const Collapse = getComponent("Collapse")
|
||||
@@ -18,7 +20,7 @@ export default class Models extends Component {
|
||||
if (!definitions.size) return null
|
||||
|
||||
return <section className={ showModels ? "models is-open" : "models"}>
|
||||
<h4 onClick={() => layoutActions.show('models', !showModels)}>
|
||||
<h4 onClick={() => layoutActions.show("models", !showModels)}>
|
||||
<span>Models</span>
|
||||
<svg width="20" height="20">
|
||||
<use xlinkHref="#large-arrow" />
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import React from "react"
|
||||
import React, { PropTypes } from "react"
|
||||
|
||||
export default class OnlineValidatorBadge extends React.Component {
|
||||
static propTypes = {
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
let { specSelectors, getConfigs } = props
|
||||
let { validatorUrl } = getConfigs()
|
||||
this.state = {
|
||||
url: specSelectors.url(),
|
||||
validatorUrl: validatorUrl
|
||||
validatorUrl: validatorUrl === undefined ? "https://online.swagger.io/validator" : validatorUrl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +23,7 @@ export default class OnlineValidatorBadge extends React.Component {
|
||||
|
||||
this.setState({
|
||||
url: specSelectors.url(),
|
||||
validatorUrl: validatorUrl
|
||||
validatorUrl: validatorUrl === undefined ? "https://online.swagger.io/validator" : validatorUrl
|
||||
})
|
||||
}
|
||||
|
||||
@@ -27,14 +33,72 @@ export default class OnlineValidatorBadge extends React.Component {
|
||||
|
||||
if ( typeof spec === "object" && Object.keys(spec).length) return null
|
||||
|
||||
if (!this.state.url) {
|
||||
if (!this.state.url || !this.state.validatorUrl || this.state.url.indexOf("localhost") >= 0
|
||||
|| this.state.url.indexOf("127.0.0.1") >= 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (<span style={{ float: "right"}}>
|
||||
return (<span style={{ float: "right"}}>
|
||||
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}>
|
||||
<img alt="Online validator badge" src={`${ this.state.validatorUrl }?url=${ this.state.url }`} />
|
||||
<ValidatorImage src={`${ this.state.validatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
|
||||
</a>
|
||||
</span>)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ValidatorImage extends React.Component {
|
||||
static propTypes = {
|
||||
src: PropTypes.string,
|
||||
alt: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
loaded: false,
|
||||
error: false
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const img = new Image()
|
||||
img.onload = () => {
|
||||
this.setState({
|
||||
loaded: true
|
||||
})
|
||||
}
|
||||
img.onerror = () => {
|
||||
this.setState({
|
||||
error: true
|
||||
})
|
||||
}
|
||||
img.src = this.props.src
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.src !== this.props.src) {
|
||||
const img = new Image()
|
||||
img.onload = () => {
|
||||
this.setState({
|
||||
loaded: true
|
||||
})
|
||||
}
|
||||
img.onerror = () => {
|
||||
this.setState({
|
||||
error: true
|
||||
})
|
||||
}
|
||||
img.src = nextProps.src
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return <img alt={"Error"} />
|
||||
} else if (!this.state.loaded) {
|
||||
return <img alt= {"Loading..."} />
|
||||
}
|
||||
return <img src={this.props.src} alt={this.props.alt} />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { PropTypes } from "react"
|
||||
import { Map, fromJS } from "immutable"
|
||||
import shallowCompare from "react-addons-shallow-compare"
|
||||
import { getList } from "core/utils"
|
||||
import * as CustomPropTypes from "core/proptypes"
|
||||
@@ -112,9 +111,7 @@ export default class Operation extends React.Component {
|
||||
specActions,
|
||||
specSelectors,
|
||||
authActions,
|
||||
authSelectors,
|
||||
layoutSelectors,
|
||||
layoutActions,
|
||||
authSelectors
|
||||
} = this.props
|
||||
|
||||
let summary = operation.get("summary")
|
||||
@@ -205,11 +202,12 @@ export default class Operation extends React.Component {
|
||||
pathMethod={ [path, method] }
|
||||
/>
|
||||
|
||||
{!tryItOutEnabled || !allowTryItOut ? null : schemes && schemes.size ? <Schemes schemes={ schemes }
|
||||
path={ path }
|
||||
method={ method }
|
||||
specActions={ specActions }/>
|
||||
: null
|
||||
{!tryItOutEnabled || !allowTryItOut ? null : schemes && schemes.size ? <div className="opblock-schemes">
|
||||
<Schemes schemes={ schemes }
|
||||
path={ path }
|
||||
method={ method }
|
||||
specActions={ specActions }/>
|
||||
</div> : null
|
||||
}
|
||||
|
||||
<div className={(!tryItOutEnabled || !response || !allowTryItOut) ? "execute-wrapper" : "btn-group"}>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { PropTypes } from "react"
|
||||
import {presets} from "react-motion"
|
||||
|
||||
export default class Operations extends React.Component {
|
||||
|
||||
@@ -33,7 +32,6 @@ export default class Operations extends React.Component {
|
||||
|
||||
const Operation = getComponent("operation")
|
||||
const Collapse = getComponent("Collapse")
|
||||
const Schemes = getComponent("schemes")
|
||||
|
||||
let showSummary = layoutSelectors.showSummary()
|
||||
|
||||
@@ -59,12 +57,6 @@ export default class Operations extends React.Component {
|
||||
</small>
|
||||
}
|
||||
|
||||
<button className="expand-methods" title="Expand all methods">
|
||||
<svg className="expand" width="20" height="20">
|
||||
<use xlinkHref="#expand" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button className="expand-operation" title="Expand operation" onClick={() => layoutActions.show(isShownKey, !showTag)}>
|
||||
<svg className="arrow" width="20" height="20">
|
||||
<use xlinkHref={showTag ? "#large-arrow-down" : "#large-arrow"} />
|
||||
|
||||
@@ -30,7 +30,6 @@ export default class Overview extends React.Component {
|
||||
{
|
||||
taggedOps.map( (tagObj, tag) => {
|
||||
let operations = tagObj.get("operations")
|
||||
let tagDetails = tagObj.get("tagDetails")
|
||||
|
||||
let showTagId = ["overview-tags", tag]
|
||||
let showTag = layoutSelectors.isShown(showTagId, true)
|
||||
@@ -45,7 +44,7 @@ export default class Overview extends React.Component {
|
||||
<Collapse isOpened={showTag} animated>
|
||||
{
|
||||
operations.map( op => {
|
||||
let { path, method, operation, id } = op.toObject() // toObject is shallow
|
||||
let { path, method, id } = op.toObject() // toObject is shallow
|
||||
let showOpIdPrefix = "operations"
|
||||
let showOpId = id
|
||||
let shown = layoutSelectors.isShown([showOpIdPrefix, showOpId])
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component, PropTypes } from "react"
|
||||
import shallowCompare from "react-addons-shallow-compare"
|
||||
import { Set, fromJS, List } from "immutable"
|
||||
import { fromJS, List } from "immutable"
|
||||
import { getSampleSchema } from "core/utils"
|
||||
|
||||
const NOOP = Function.prototype
|
||||
@@ -50,14 +50,15 @@ export default class ParamBody extends Component {
|
||||
}
|
||||
|
||||
updateValues = (props) => {
|
||||
let { specSelectors, pathMethod, param, isExecute, consumesValue="", onChangeConsumes } = props
|
||||
let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props
|
||||
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name")) : {}
|
||||
let isXml = /xml/i.test(consumesValue)
|
||||
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")
|
||||
|
||||
if ( paramValue ) {
|
||||
this.setState({ value: paramValue })
|
||||
this.onChange(paramValue, {isXml: isXml, isEditBox: isExecute})
|
||||
if ( paramValue !== undefined ) {
|
||||
let val = !paramValue && !isXml ? "{}" : paramValue
|
||||
this.setState({ value: val })
|
||||
this.onChange(val, {isXml: isXml, isEditBox: isExecute})
|
||||
} else {
|
||||
if (isXml) {
|
||||
this.onChange(this.sample("xml"), {isXml: isXml, isEditBox: isExecute})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component, PropTypes } from "react"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import Im, { fromJS } from "immutable"
|
||||
import Im from "immutable"
|
||||
|
||||
// More readable, just iterate over maps, only
|
||||
const eachMap = (iterable, fn) => iterable.valueSeq().filter(Im.Map.isMap).map(fn)
|
||||
@@ -87,7 +87,7 @@ export default class Parameters extends Component {
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
eachMap(parameters, (parameter, k) => (
|
||||
eachMap(parameters, (parameter) => (
|
||||
<ParameterRow fn={ fn }
|
||||
getComponent={ getComponent }
|
||||
param={ parameter }
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import React, { PropTypes } from "react"
|
||||
import { fromJS } from 'immutable'
|
||||
import { fromJS } from "immutable"
|
||||
import { getSampleSchema } from "core/utils"
|
||||
|
||||
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
|
||||
if ( examples && examples.size ) {
|
||||
return examples.entrySeq().map( ([ key, example ]) => {
|
||||
let exampleValue
|
||||
try {
|
||||
exampleValue = example && example.toJS ? example.toJS() : example
|
||||
exampleValue = JSON.stringify(exampleValue)
|
||||
}
|
||||
catch(e) {
|
||||
exampleValue = String(example)
|
||||
}
|
||||
return (<div key={ key }>
|
||||
<h5>{ key }</h5>
|
||||
<HighlightCode className="example" value={ example } />
|
||||
<HighlightCode className="example" value={ exampleValue } />
|
||||
</div>)
|
||||
}).toArray()
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ export default class Schemes extends React.Component {
|
||||
}
|
||||
|
||||
onChange =( e ) => {
|
||||
let { path, method, specActions } = this.props
|
||||
|
||||
this.setScheme( e.target.value )
|
||||
}
|
||||
|
||||
@@ -33,7 +31,7 @@ export default class Schemes extends React.Component {
|
||||
|
||||
return (
|
||||
<label htmlFor="schemes">
|
||||
<span>Schemes</span>
|
||||
<span className="schemes-title">Schemes</span>
|
||||
<select onChange={ this.onChange }>
|
||||
{ schemes.valueSeq().map(
|
||||
( scheme ) => <option value={ scheme } key={ scheme }>{ scheme }</option>
|
||||
|
||||
@@ -4,11 +4,13 @@ export default class TryItOutButton extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
onTryoutClick: PropTypes.func,
|
||||
onCancelClick: PropTypes.func,
|
||||
enabled: PropTypes.bool, // Try it out is enabled, ie: the user has access to the form
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onTryoutClick: Function.prototype,
|
||||
onCancelClick: Function.prototype,
|
||||
enabled: false,
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ export default function curl( request ){
|
||||
let headers = request.get("headers")
|
||||
curlified.push( "curl" )
|
||||
curlified.push( "-X", request.get("method") )
|
||||
curlified.push( request.get("url") )
|
||||
curlified.push( `"${request.get("url")}"`)
|
||||
|
||||
if ( headers && headers.size ) {
|
||||
for( let p of request.get("headers").entries() ){
|
||||
|
||||
@@ -4,6 +4,7 @@ import System from "core/system"
|
||||
import ApisPreset from "core/presets/apis"
|
||||
import * as AllPlugins from "core/plugins/all"
|
||||
import { filterConfigs } from "plugins/configs"
|
||||
import { parseSeach } from "core/utils"
|
||||
|
||||
module.exports = function SwaggerUI(opts) {
|
||||
|
||||
@@ -12,9 +13,9 @@ module.exports = function SwaggerUI(opts) {
|
||||
dom_id: null,
|
||||
spec: {},
|
||||
url: "",
|
||||
layout: "Layout",
|
||||
layout: "BaseLayout",
|
||||
validatorUrl: "https://online.swagger.io/validator",
|
||||
configs: {
|
||||
validatorUrl: "https://online.swagger.io/validator"
|
||||
},
|
||||
|
||||
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
|
||||
@@ -35,79 +36,73 @@ module.exports = function SwaggerUI(opts) {
|
||||
store: { },
|
||||
}
|
||||
|
||||
const config = deepExtend({}, defaults, opts)
|
||||
const constructorConfig = deepExtend({}, defaults, opts)
|
||||
|
||||
const storeConfigs = deepExtend({}, config.store, {
|
||||
const storeConfigs = deepExtend({}, constructorConfig.store, {
|
||||
system: {
|
||||
configs: config.configs
|
||||
configs: constructorConfig.configs
|
||||
},
|
||||
plugins: config.presets,
|
||||
plugins: constructorConfig.presets,
|
||||
state: {
|
||||
layout: {
|
||||
layout: config.layout
|
||||
layout: constructorConfig.layout
|
||||
},
|
||||
spec: {
|
||||
spec: "",
|
||||
url: config.url
|
||||
url: constructorConfig.url
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let inlinePlugin = ()=> {
|
||||
return {
|
||||
fn: config.fn,
|
||||
components: config.components,
|
||||
state: config.state,
|
||||
fn: constructorConfig.fn,
|
||||
components: constructorConfig.components,
|
||||
state: constructorConfig.state,
|
||||
}
|
||||
}
|
||||
|
||||
var store = new System(storeConfigs)
|
||||
store.register([config.plugins, inlinePlugin])
|
||||
store.register([constructorConfig.plugins, inlinePlugin])
|
||||
|
||||
var system = store.getSystem()
|
||||
let queryConfig = parseSeach()
|
||||
|
||||
const downloadSpec = (configs) => {
|
||||
if(typeof config !== "object") {
|
||||
const downloadSpec = (fetchedConfig) => {
|
||||
if(typeof constructorConfig !== "object") {
|
||||
return system
|
||||
}
|
||||
|
||||
let localConfig = system.specSelectors.getLocalConfig ? system.specSelectors.getLocalConfig() : {}
|
||||
let mergedConfig = deepExtend({}, config, configs, localConfig)
|
||||
let mergedConfig = deepExtend({}, constructorConfig, localConfig, fetchedConfig || {}, queryConfig)
|
||||
store.setConfigs(filterConfigs(mergedConfig))
|
||||
|
||||
if(typeof mergedConfig.spec === "object" && Object.keys(mergedConfig.spec).length) {
|
||||
system.specActions.updateUrl("")
|
||||
system.specActions.updateLoadingStatus("success");
|
||||
system.specActions.updateSpec(JSON.stringify(mergedConfig.spec))
|
||||
} else if(mergedConfig.url) {
|
||||
system.specActions.updateUrl(mergedConfig.url)
|
||||
system.specActions.download(mergedConfig.url)
|
||||
if (fetchedConfig !== null) {
|
||||
if (!queryConfig.url && typeof mergedConfig.spec === "object" && Object.keys(mergedConfig.spec).length) {
|
||||
system.specActions.updateUrl("")
|
||||
system.specActions.updateLoadingStatus("success")
|
||||
system.specActions.updateSpec(JSON.stringify(mergedConfig.spec))
|
||||
} else if (system.specActions.download && mergedConfig.url) {
|
||||
system.specActions.updateUrl(mergedConfig.url)
|
||||
system.specActions.download(mergedConfig.url)
|
||||
}
|
||||
}
|
||||
|
||||
if(mergedConfig.dom_id)
|
||||
if(mergedConfig.dom_id) {
|
||||
system.render(mergedConfig.dom_id, "App")
|
||||
} else {
|
||||
console.error("Skipped rendering: no `dom_id` was specified")
|
||||
}
|
||||
|
||||
return system
|
||||
}
|
||||
|
||||
if (system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl(downloadSpec)) {
|
||||
return downloadSpec(config)
|
||||
let configUrl = queryConfig.config || constructorConfig.configUrl
|
||||
|
||||
if (!configUrl || !system.specActions.getConfigByUrl || system.specActions.getConfigByUrl && !system.specActions.getConfigByUrl(configUrl, downloadSpec)) {
|
||||
return downloadSpec()
|
||||
}
|
||||
|
||||
if (system.specActions.download && config.url) {
|
||||
system.specActions.download(config.url)
|
||||
}
|
||||
|
||||
if(config.spec && typeof config.spec === "string")
|
||||
system.specActions.updateSpec(config.spec)
|
||||
|
||||
if(config.dom_id) {
|
||||
system.render(config.dom_id, "App")
|
||||
} else {
|
||||
console.error("Skipped rendering: no `dom_id` was specified")
|
||||
}
|
||||
|
||||
return system
|
||||
}
|
||||
|
||||
// Add presets
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React, { PropTypes, Component } from "react"
|
||||
import { arrayify } from "core/utils"
|
||||
import shallowCompare from "react-addons-shallow-compare"
|
||||
import { List, fromJS } from "immutable"
|
||||
import assign from "object-assign"
|
||||
//import "less/json-schema-form"
|
||||
|
||||
const noop = ()=> {}
|
||||
@@ -53,7 +51,7 @@ export class JsonSchema_string extends Component {
|
||||
}
|
||||
onEnumChange = (val) => this.props.onChange(val)
|
||||
render() {
|
||||
let { getComponent, value, schema, fn, required, description } = this.props
|
||||
let { getComponent, value, schema, required, description } = this.props
|
||||
let enumValue = schema["enum"]
|
||||
let errors = schema.errors || []
|
||||
|
||||
@@ -119,13 +117,13 @@ export class JsonSchema_array extends Component {
|
||||
}
|
||||
|
||||
onEnumChange = (value) => {
|
||||
this.setState(state => ({
|
||||
this.setState(() => ({
|
||||
value: value
|
||||
}), this.onChange)
|
||||
}
|
||||
|
||||
render() {
|
||||
let { getComponent, onChange, required, schema, fn } = this.props
|
||||
let { getComponent, required, schema, fn } = this.props
|
||||
|
||||
let itemSchema = fn.inferSchema(schema.items)
|
||||
|
||||
@@ -152,9 +150,9 @@ export class JsonSchema_array extends Component {
|
||||
(errors.length ? <span style={{ color: "red", fortWeight: "bold" }}>{ errors[0] }</span> : null) :
|
||||
value.map( (item,i) => {
|
||||
let schema = Object.assign({}, itemSchema)
|
||||
let err = errors.filter((err) => err.index === i)
|
||||
if ( err.length ) {
|
||||
schema.errors = [ err[0].error + i ]
|
||||
if ( errors.length ) {
|
||||
let err = errors.filter((err) => err.index === i)
|
||||
if (err.length) schema.errors = [ err[0].error + i ]
|
||||
}
|
||||
return (
|
||||
<div key={i} className="json-schema-form-item">
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import win from "core/window"
|
||||
import { btoa } from "core/utils"
|
||||
|
||||
export default function authorize ( auth, authActions, errActions, configs ) {
|
||||
let { schema, scopes, name, clientId } = auth
|
||||
|
||||
let redirectUrl = configs.oauth2RedirectUrl
|
||||
let scopeSeparator = " "
|
||||
let state = name
|
||||
let state = btoa(new Date())
|
||||
let flow = schema.get("flow")
|
||||
let url
|
||||
|
||||
@@ -14,6 +15,11 @@ export default function authorize ( auth, authActions, errActions, configs ) {
|
||||
return
|
||||
}
|
||||
|
||||
if (flow === "application") {
|
||||
authActions.authorizeApplication(auth)
|
||||
return
|
||||
}
|
||||
|
||||
// todo move to parser
|
||||
if ( !redirectUrl ) {
|
||||
errActions.newAuthErr( {
|
||||
@@ -39,7 +45,7 @@ export default function authorize ( auth, authActions, errActions, configs ) {
|
||||
win.swaggerUIRedirectOauth2 = {
|
||||
auth: auth,
|
||||
state: state,
|
||||
callback: authActions.preAuthorizeOauth2,
|
||||
callback: flow === "implicit" ? authActions.preAuthorizeImplicit : authActions.authorizeAccessCode,
|
||||
errCb: errActions.newAuthErr
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export function transformPathToArray(property, jsSpec) {
|
||||
return a.concat(b)
|
||||
}, [])
|
||||
.concat([""]) // add an empty item into the array, so we don't get stuck with something in our buffer below
|
||||
.reduce((buffer, curr, i, arr) => {
|
||||
.reduce((buffer, curr) => {
|
||||
let obj = pathArr.length ? get(jsSpec, pathArr) : jsSpec
|
||||
|
||||
if(get(obj, makeAccessArray(buffer, curr))) {
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import React, { PropTypes } from "react"
|
||||
|
||||
export default function (system) {
|
||||
return {
|
||||
components: {
|
||||
NoHostWarning,
|
||||
},
|
||||
statePlugins: {
|
||||
spec: {
|
||||
selectors: {
|
||||
allowTryItOutFor,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a quick style. How do we improve this?
|
||||
const style = {
|
||||
backgroundColor: "#e7f0f7",
|
||||
padding: "1rem",
|
||||
borderRadius: "3px",
|
||||
}
|
||||
|
||||
function NoHostWarning() {
|
||||
return (
|
||||
<div style={style}>Note: The interactive forms are disabled, as no `host` property was found in the specification. Please see: <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object" target="_blank">OAI 2.0/#swagger-object</a></div>
|
||||
)
|
||||
}
|
||||
|
||||
// Only allow if, there is a host field
|
||||
function allowTryItOutFor(state) {
|
||||
return ({specSelectors}) => {
|
||||
return specSelectors.hasHost(state)
|
||||
}
|
||||
}
|
||||
@@ -277,8 +277,6 @@ export let getLineNumberForPathAsync = promisifySyncFn(getLineNumberForPath)
|
||||
|
||||
function promisifySyncFn(fn) {
|
||||
return function(...args) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(fn(...args))
|
||||
})
|
||||
return new Promise((resolve) => resolve(fn(...args)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import win from "core/window"
|
||||
import btoa from "btoa"
|
||||
import { btoa, buildFormData } from "core/utils"
|
||||
|
||||
export const SHOW_AUTH_POPUP = "show_popup"
|
||||
export const AUTHORIZE = "authorize"
|
||||
@@ -8,6 +8,8 @@ export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2"
|
||||
export const AUTHORIZE_OAUTH2 = "authorize_oauth2"
|
||||
export const VALIDATE = "validate"
|
||||
|
||||
const scopeSeparator = " "
|
||||
|
||||
export function showDefinitions(payload) {
|
||||
return {
|
||||
type: SHOW_AUTH_POPUP,
|
||||
@@ -29,7 +31,7 @@ export function logout(payload) {
|
||||
}
|
||||
}
|
||||
|
||||
export const preAuthorizeOauth2 = (payload) => ( { authActions, errActions } ) => {
|
||||
export const preAuthorizeImplicit = (payload) => ( { authActions, errActions } ) => {
|
||||
let { auth , token, isValid } = payload
|
||||
let { schema, name } = auth
|
||||
let flow = schema.get("flow")
|
||||
@@ -66,28 +68,72 @@ export function authorizeOauth2(payload) {
|
||||
}
|
||||
}
|
||||
|
||||
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
|
||||
export const authorizePassword = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
||||
let req = {
|
||||
url: schema.get("tokenUrl"),
|
||||
method: "post",
|
||||
headers: {
|
||||
"content-type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
query: {
|
||||
grant_type: "password",
|
||||
username,
|
||||
password
|
||||
let form = {
|
||||
grant_type: "password",
|
||||
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
||||
}
|
||||
let query = {}
|
||||
let headers = {}
|
||||
|
||||
if ( passwordType === "basic") {
|
||||
headers.Authorization = "Basic " + btoa(username + ":" + password)
|
||||
} else {
|
||||
Object.assign(form, {username}, {password})
|
||||
if ( passwordType === "query") {
|
||||
if ( clientId ) { query.client_id = clientId }
|
||||
if ( clientSecret ) { query.client_secret = clientSecret }
|
||||
} else {
|
||||
Object.assign(form, {client_id: clientId}, {client_secret: clientSecret})
|
||||
}
|
||||
}
|
||||
|
||||
if ( passwordType === "basic") {
|
||||
req.headers.authorization = "Basic " + btoa(clientId + ":" + clientSecret)
|
||||
} else if ( passwordType === "request") {
|
||||
req.query = Object.assign(req.query, { client_id: clientId, client_secret: clientSecret })
|
||||
return authActions.authorizeRequest({ body: buildFormData(form), url: schema.get("tokenUrl"), name, headers, query, auth})
|
||||
}
|
||||
|
||||
export const authorizeApplication = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, scopes, name, clientId, clientSecret } = auth
|
||||
let form = {
|
||||
grant_type: "client_credentials",
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
scope: scopes.join(scopeSeparator)
|
||||
}
|
||||
return fn.fetch(req)
|
||||
.then(( response ) => {
|
||||
|
||||
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth })
|
||||
}
|
||||
|
||||
export const authorizeAccessCode = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, name, clientId, clientSecret } = auth
|
||||
let form = {
|
||||
grant_type: "authorization_code",
|
||||
code: auth.code,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
}
|
||||
|
||||
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth})
|
||||
|
||||
}
|
||||
|
||||
export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } ) => {
|
||||
let { body, query={}, headers={}, name, url, auth } = data
|
||||
|
||||
let _headers = Object.assign({
|
||||
"Accept":"application/json, text/plain, */*",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}, headers)
|
||||
|
||||
fn.fetch({
|
||||
url: url,
|
||||
method: "post",
|
||||
headers: _headers,
|
||||
query: query,
|
||||
body: body
|
||||
})
|
||||
.then(function (response) {
|
||||
let token = JSON.parse(response.data)
|
||||
let error = token && ( token.error || "" )
|
||||
let parseError = token && ( token.parseError || "" )
|
||||
@@ -112,7 +158,14 @@ export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } )
|
||||
return
|
||||
}
|
||||
|
||||
authActions.authorizeOauth2({ auth, token })
|
||||
authActions.authorizeOauth2({ auth, token})
|
||||
})
|
||||
.catch(err => { errActions.newAuthErr( err ) })
|
||||
.catch(e => {
|
||||
let err = new Error(e)
|
||||
errActions.newAuthErr( {
|
||||
authId: name,
|
||||
level: "error",
|
||||
source: "auth",
|
||||
message: err.message
|
||||
} ) })
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { fromJS, Map } from "immutable"
|
||||
import btoa from "btoa"
|
||||
import { btoa } from "core/utils"
|
||||
|
||||
import {
|
||||
SHOW_AUTH_POPUP,
|
||||
AUTHORIZE,
|
||||
PRE_AUTHORIZE_OAUTH2,
|
||||
AUTHORIZE_OAUTH2,
|
||||
LOGOUT
|
||||
} from "./actions"
|
||||
@@ -21,7 +20,6 @@ export default {
|
||||
// refactor withMutations
|
||||
securities.entrySeq().forEach( ([ key, security ]) => {
|
||||
let type = security.getIn(["schema", "type"])
|
||||
let name = security.get("name")
|
||||
|
||||
if ( type === "apiKey" ) {
|
||||
map = map.set(key, security)
|
||||
|
||||
@@ -10,7 +10,7 @@ export const shownDefinitions = createSelector(
|
||||
|
||||
export const definitionsToAuthorize = createSelector(
|
||||
state,
|
||||
auth =>( { specSelectors } ) => {
|
||||
() =>( { specSelectors } ) => {
|
||||
let definitions = specSelectors.securityDefinitions()
|
||||
let list = List()
|
||||
|
||||
@@ -66,7 +66,10 @@ export const authorized = createSelector(
|
||||
|
||||
export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
|
||||
let authorized = authSelectors.authorized()
|
||||
let isAuth = false
|
||||
|
||||
if(!List.isList(securities)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return !!securities.toJS().filter( ( security ) => {
|
||||
let isAuthorized = true
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Map } from "immutable"
|
||||
|
||||
// Add security to the final `execute` call ( via `extras` )
|
||||
export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path, method, operation, extras }) => {
|
||||
let securities = {
|
||||
@@ -10,4 +8,3 @@ export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path
|
||||
|
||||
return oriAction({ path, method, operation, securities, ...extras })
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,19 @@ import { createSelector } from "reselect"
|
||||
import { Map } from "immutable"
|
||||
|
||||
export default function downloadUrlPlugin (toolbox) {
|
||||
let { fn, Im } = toolbox
|
||||
let { fn } = toolbox
|
||||
|
||||
const actions = {
|
||||
download: (url)=> ({ errActions, specSelectors, specActions }) => {
|
||||
let { fetch } = fn
|
||||
url = url || specSelectors.url()
|
||||
specActions.updateLoadingStatus("loading")
|
||||
fetch(url, {
|
||||
fetch({
|
||||
url,
|
||||
loadSpec: true,
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
"Accept": "application/json,*/*"
|
||||
}
|
||||
}).then(next,next)
|
||||
|
||||
@@ -30,7 +33,7 @@ export default function downloadUrlPlugin (toolbox) {
|
||||
},
|
||||
|
||||
updateLoadingStatus: (status) => {
|
||||
let enums = [null, "loading", "failed", "success"]
|
||||
let enums = [null, "loading", "failed", "success", "failedConfig"]
|
||||
if(enums.indexOf(status) === -1) {
|
||||
console.error(`Error: ${status} is not one of ${JSON.stringify(enums)}`)
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ export function newThrownErrBatch(errors) {
|
||||
}
|
||||
}
|
||||
|
||||
export function newSpecErr(err, action) {
|
||||
export function newSpecErr(err) {
|
||||
return {
|
||||
type: NEW_SPEC_ERR,
|
||||
payload: err
|
||||
}
|
||||
}
|
||||
|
||||
export function newAuthErr(err, action) {
|
||||
export function newAuthErr(err) {
|
||||
return {
|
||||
type: NEW_AUTH_ERR,
|
||||
payload: err
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import concat from "lodash/concat"
|
||||
import reduce from "lodash/reduce"
|
||||
let request = require.context("./transformers/", true, /\.js$/)
|
||||
let errorTransformers = []
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import get from "lodash/get"
|
||||
import last from "lodash/get"
|
||||
import { fromJS, List } from "immutable"
|
||||
import { fromJS } from "immutable"
|
||||
|
||||
export function transform(errors, { jsSpec }) {
|
||||
// LOOK HERE THIS TRANSFORMER IS CURRENTLY DISABLED 😃
|
||||
|
||||
@@ -47,7 +47,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
||||
let obj = {}
|
||||
for (var name in props) {
|
||||
if ( !props[name].readOnly || includeReadOnly ) {
|
||||
obj[name] = sampleFromSchema(props[name])
|
||||
obj[name] = sampleFromSchema(props[name], { includeReadOnly: includeReadOnly })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
||||
obj.additionalProp1 = {}
|
||||
} else if ( additionalProperties ) {
|
||||
let additionalProps = objectify(additionalProperties)
|
||||
let additionalPropVal = sampleFromSchema(additionalProps)
|
||||
let additionalPropVal = sampleFromSchema(additionalProps, { includeReadOnly: includeReadOnly })
|
||||
|
||||
for (let i = 1; i < 4; i++) {
|
||||
obj["additionalProp" + i] = additionalPropVal
|
||||
@@ -65,7 +65,7 @@ export const sampleFromSchema = (schema, config={}) => {
|
||||
}
|
||||
|
||||
if(type === "array") {
|
||||
return [ sampleFromSchema(items) ]
|
||||
return [ sampleFromSchema(items, { includeReadOnly: includeReadOnly }) ]
|
||||
}
|
||||
|
||||
if(schema["enum"]) {
|
||||
@@ -127,8 +127,12 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
||||
|
||||
if (xml.wrapped) {
|
||||
res[displayName] = []
|
||||
if (Array.isArray(defaultValue)) {
|
||||
|
||||
if (Array.isArray(example)) {
|
||||
example.forEach((v)=>{
|
||||
items.example = v
|
||||
res[displayName].push(sampleXmlFromSchema(items, config))
|
||||
})
|
||||
} else if (Array.isArray(defaultValue)) {
|
||||
defaultValue.forEach((v)=>{
|
||||
items.default = v
|
||||
res[displayName].push(sampleXmlFromSchema(items, config))
|
||||
@@ -145,14 +149,20 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
||||
|
||||
let _res = []
|
||||
|
||||
if (Array.isArray(defaultValue)) {
|
||||
if (Array.isArray(example)) {
|
||||
example.forEach((v)=>{
|
||||
items.example = v
|
||||
_res.push(sampleXmlFromSchema(items, config))
|
||||
})
|
||||
return _res
|
||||
} else if (Array.isArray(defaultValue)) {
|
||||
defaultValue.forEach((v)=>{
|
||||
items.default = v
|
||||
_res.push(sampleXmlFromSchema(items, config))
|
||||
})
|
||||
return _res
|
||||
|
||||
}
|
||||
|
||||
return sampleXmlFromSchema(items, config)
|
||||
}
|
||||
}
|
||||
@@ -176,7 +186,13 @@ export const sampleXmlFromSchema = (schema, config={}) => {
|
||||
} else {
|
||||
props[propName].xml.name = props[propName].xml.name || propName
|
||||
props[propName].example = props[propName].example !== undefined ? props[propName].example : example[propName]
|
||||
res[displayName].push(sampleXmlFromSchema(props[propName]))
|
||||
let t = sampleXmlFromSchema(props[propName])
|
||||
if (Array.isArray(t)) {
|
||||
res[displayName] = res[displayName].concat(t)
|
||||
} else {
|
||||
res[displayName].push(t)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import YAML from "js-yaml"
|
||||
import parseUrl from "url-parse"
|
||||
import serializeError from "serialize-error"
|
||||
|
||||
// Actions conform to FSA (flux-standard-actions)
|
||||
@@ -184,8 +185,12 @@ export const logRequest = (req) => {
|
||||
|
||||
// Actually fire the request via fn.execute
|
||||
// (For debugging) and ease of testing
|
||||
export const executeRequest = (req) => ({fn, specActions, errActions}) => {
|
||||
export const executeRequest = (req) => ({fn, specActions, specSelectors}) => {
|
||||
let { pathName, method } = req
|
||||
|
||||
// if url is relative, parseUrl makes it absolute by inferring from `window.location`
|
||||
req.contextUrl = parseUrl(specSelectors.url()).toString()
|
||||
|
||||
let parsedRequest = Object.assign({}, req)
|
||||
if ( pathName && method ) {
|
||||
parsedRequest.operationId = method.toLowerCase() + "-" + pathName
|
||||
|
||||
@@ -51,7 +51,6 @@ export default {
|
||||
|
||||
[VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
||||
let operation = state.getIn( [ "resolved", "paths", ...pathMethod ] )
|
||||
let parameters = operation.get("parameters")
|
||||
let isXml = /xml/i.test(operation.get("consumes_value"))
|
||||
|
||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
||||
@@ -64,9 +63,6 @@ export default {
|
||||
})
|
||||
},
|
||||
[ClEAR_VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
||||
let operation = state.getIn( [ "resolved", "paths", ...pathMethod ] )
|
||||
let parameters = operation.get("parameters")
|
||||
|
||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
||||
return parameters.withMutations( parameters => {
|
||||
for ( let i = 0, len = parameters.count(); i < len; i++ ) {
|
||||
@@ -101,7 +97,11 @@ export default {
|
||||
},
|
||||
|
||||
[UPDATE_OPERATION_VALUE]: (state, { payload: { path, value, key } }) => {
|
||||
return state.setIn(["resolved", "paths", ...path, key], fromJS(value))
|
||||
let operationPath = ["resolved", "paths", ...path]
|
||||
if(!state.getIn(operationPath)) {
|
||||
return state
|
||||
}
|
||||
return state.setIn([...operationPath, key], fromJS(value))
|
||||
},
|
||||
|
||||
[CLEAR_RESPONSE]: (state, { payload: { path, method } } ) =>{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createSelector } from "reselect"
|
||||
import { sorters } from "core/utils"
|
||||
import { fromJS, Set, Map, List } from "immutable"
|
||||
|
||||
const DEFAULT_TAG = "default"
|
||||
@@ -198,13 +199,16 @@ export const operationsWithTags = createSelector(
|
||||
}
|
||||
)
|
||||
|
||||
export const taggedOperations = createSelector(
|
||||
state,
|
||||
operationsWithTags,
|
||||
(state, tagMap) => {
|
||||
return tagMap.map((ops, tag) => Map({tagDetails: tagDetails(state, tag), operations: ops}))
|
||||
}
|
||||
)
|
||||
export const taggedOperations = ( state ) =>( { getConfigs } ) => {
|
||||
let { operationsSorter }= getConfigs()
|
||||
|
||||
return operationsWithTags(state).map((ops, tag) => {
|
||||
let sortFn = typeof operationsSorter === "function" ? operationsSorter
|
||||
: sorters.operationsSorter[operationsSorter]
|
||||
let operations = !sortFn ? ops : ops.sort(sortFn)
|
||||
|
||||
return Map({tagDetails: tagDetails(state, tag), operations: operations})})
|
||||
}
|
||||
|
||||
export const responses = createSelector(
|
||||
state,
|
||||
@@ -224,7 +228,7 @@ export const requestFor = (state, path, method) => {
|
||||
return requests(state).getIn([path, method], null)
|
||||
}
|
||||
|
||||
export const allowTryItOutFor = (state, path, method ) => {
|
||||
export const allowTryItOutFor = () => {
|
||||
// This is just a hook for now.
|
||||
return true
|
||||
}
|
||||
@@ -291,7 +295,11 @@ export function operationConsumes(state, pathMethod) {
|
||||
}
|
||||
|
||||
export const operationScheme = ( state, path, method ) => {
|
||||
return state.getIn(["scheme", path, method]) || state.getIn(["scheme", "_defaultScheme"]) || "http"
|
||||
let url = state.get("url")
|
||||
let matchResult = url.match(/^([a-z][a-z0-9+\-.]*):/)
|
||||
let urlScheme = Array.isArray(matchResult) ? matchResult[1] : null
|
||||
|
||||
return state.getIn(["scheme", path, method]) || state.getIn(["scheme", "_defaultScheme"]) || urlScheme || ""
|
||||
}
|
||||
|
||||
export const canExecuteScheme = ( state, path, method ) => {
|
||||
|
||||
@@ -57,14 +57,14 @@ export default class SplitPaneMode extends React.Component {
|
||||
const mode = layoutSelectors.whatMode(MODE_KEY)
|
||||
const left = mode === MODE_RIGHT ? <noscript/> : children[0]
|
||||
const right = mode === MODE_LEFT ? <noscript/> : children[1]
|
||||
const size = this.sizeFromMode(mode, '50%')
|
||||
const size = this.sizeFromMode(mode, "50%")
|
||||
|
||||
return (
|
||||
<SplitPane
|
||||
disabledClass={''}
|
||||
ref={'splitPane'}
|
||||
disabledClass={""}
|
||||
ref={"splitPane"}
|
||||
split='vertical'
|
||||
defaultSize={'50%'}
|
||||
defaultSize={"50%"}
|
||||
primary="second"
|
||||
minSize={0}
|
||||
size={size}
|
||||
|
||||
@@ -3,10 +3,6 @@ import ReactDOM from "react-dom"
|
||||
import { connect, Provider } from "react-redux"
|
||||
import omit from "lodash/omit"
|
||||
|
||||
|
||||
const NotFoundComponent = name => ()=> <span style={{color: "red"}}> "{name}" component not found </span>
|
||||
|
||||
|
||||
const SystemWrapper = (getSystem, ComponentToWrap ) => class extends Component {
|
||||
render() {
|
||||
return <ComponentToWrap {...getSystem() } {...this.props} {...this.context} />
|
||||
@@ -75,10 +71,10 @@ const createClass = component => React.createClass({
|
||||
}
|
||||
})
|
||||
|
||||
const Fallback = ({ error, name }) => <div style={{ // eslint-disable-line react/prop-types
|
||||
const Fallback = ({ name }) => <div style={{ // eslint-disable-line react/prop-types
|
||||
padding: "1em",
|
||||
"color": "#aaa"
|
||||
}}>😱 <i>Could not render { name ? name : "this component" }, see console.</i></div>
|
||||
}}>😱 <i>Could not render { name === "t" ? "this component" : name }, see the console.</i></div>
|
||||
|
||||
const wrapRender = (component) => {
|
||||
const isStateless = component => !(component.prototype && component.prototype.isReactComponent)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import BasePreset from "./base"
|
||||
|
||||
import allowTryItOutIfHost from "core/plugins/allow-try-it-out-if-host"
|
||||
// Just the base, for now.
|
||||
|
||||
export default function PresetApis() {
|
||||
|
||||
return [
|
||||
BasePreset,
|
||||
allowTryItOutIfHost,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ import Model from "core/components/model"
|
||||
import Models from "core/components/models"
|
||||
import TryItOutButton from "core/components/try-it-out-button"
|
||||
|
||||
import BaseLayout from "core/components/layouts/base"
|
||||
|
||||
import * as LayoutUtils from "core/components/layout-utils"
|
||||
import * as JsonSchemaComponents from "core/json-schema-components"
|
||||
|
||||
@@ -87,6 +89,7 @@ export default function() {
|
||||
model: Model,
|
||||
models: Models,
|
||||
TryItOutButton,
|
||||
BaseLayout
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { createStore, applyMiddleware, bindActionCreators, compose } from "redux"
|
||||
import Im, { fromJS, Map } from "immutable"
|
||||
import deepExtend from "deep-extend"
|
||||
import createLogger from "redux-logger"
|
||||
import { combineReducers } from "redux-immutable"
|
||||
import assign from "object-assign"
|
||||
import serializeError from "serialize-error"
|
||||
|
||||
@@ -135,12 +135,11 @@ export function getList(iterable, keys) {
|
||||
// Adapted from http://stackoverflow.com/a/2893259/454004
|
||||
// Note: directly ported from CoffeeScript
|
||||
export function formatXml (xml) {
|
||||
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp
|
||||
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, reg, transitions, wsexp
|
||||
reg = /(>)(<)(\/*)/g
|
||||
wsexp = /[ ]*(.*)[ ]+\n/g
|
||||
contexp = /(<.+>)(.+\n)/g
|
||||
xml = xml.replace(/\r\n/g, "\n").replace(reg, "$1\n$2$3").replace(wsexp, "$1\n").replace(contexp, "$1\n$2")
|
||||
pad = 0
|
||||
formatted = ""
|
||||
lines = xml.split("\n")
|
||||
indent = 0
|
||||
@@ -164,7 +163,7 @@ export function formatXml (xml) {
|
||||
"other->other": 0
|
||||
}
|
||||
fn = function(ln) {
|
||||
var fromTo, j, key, padding, type, types, value
|
||||
var fromTo, key, padding, type, types, value
|
||||
types = {
|
||||
single: Boolean(ln.match(/<.+\/>/)),
|
||||
closing: Boolean(ln.match(/<\/.+>/)),
|
||||
@@ -187,11 +186,13 @@ export function formatXml (xml) {
|
||||
padding = ""
|
||||
indent += transitions[fromTo]
|
||||
padding = ((function() {
|
||||
var m, ref1, results
|
||||
/* eslint-disable no-unused-vars */
|
||||
var m, ref1, results, j
|
||||
results = []
|
||||
for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {
|
||||
results.push(" ")
|
||||
}
|
||||
/* eslint-enable no-unused-vars */
|
||||
return results
|
||||
})()).join("")
|
||||
if (fromTo === "opening->closing") {
|
||||
@@ -215,19 +216,9 @@ export function formatXml (xml) {
|
||||
export function highlight (el) {
|
||||
const MAX_LENGTH = 5000
|
||||
var
|
||||
_window = window,
|
||||
_document = document,
|
||||
appendChild = "appendChild",
|
||||
test = "test",
|
||||
// style and color templates
|
||||
textShadow = ";text-shadow:",
|
||||
opacity = "opacity:.",
|
||||
_0px_0px = " 0px 0px ",
|
||||
_3px_0px_5 = "3px 0px 5",
|
||||
brace = ")",
|
||||
|
||||
i,
|
||||
microlighted
|
||||
test = "test"
|
||||
|
||||
if (!el) return ""
|
||||
if (el.textContent.length > MAX_LENGTH) { return el.textContent }
|
||||
@@ -260,14 +251,7 @@ export function highlight (el) {
|
||||
lastTokenType,
|
||||
// flag determining if token is multi-character
|
||||
multichar,
|
||||
node,
|
||||
|
||||
// calculating the colors for the style templates
|
||||
colorArr = /(\d*\, \d*\, \d*)(, ([.\d]*))?/g.exec(
|
||||
_window.getComputedStyle(el).color
|
||||
),
|
||||
pxColor = "px rgba("+colorArr[1]+",",
|
||||
alpha = colorArr[3]||1
|
||||
node
|
||||
|
||||
// running through characters and highlighting
|
||||
while (prev2 = prev1,
|
||||
@@ -468,6 +452,17 @@ export const propChecker = (props, nextProps, objectList=[], ignoreList=[]) => {
|
||||
|| objectList.some( objectPropName => !eq(props[objectPropName], nextProps[objectPropName])))
|
||||
}
|
||||
|
||||
const validateNumber = ( val ) => {
|
||||
if ( !/^-?\d+(.?\d+)?$/.test(val)) {
|
||||
return "Value must be a number"
|
||||
}
|
||||
}
|
||||
|
||||
const validateInteger = ( val ) => {
|
||||
if ( !/^-?\d+$/.test(val)) {
|
||||
return "Value must be integer"
|
||||
}
|
||||
}
|
||||
|
||||
// validation of parameters before execute
|
||||
export const validateParam = (param, isXml) => {
|
||||
@@ -517,29 +512,16 @@ export const validateParam = (param, isXml) => {
|
||||
return errors
|
||||
}
|
||||
|
||||
const validateNumber = ( val ) => {
|
||||
if ( !/^\d+(.?\d+)?$/.test(val)) {
|
||||
return "Value must be a number"
|
||||
}
|
||||
}
|
||||
|
||||
const validateInteger = ( val ) => {
|
||||
if ( !/^\d+$/.test(val)) {
|
||||
return "Value must be integer"
|
||||
}
|
||||
}
|
||||
|
||||
export const getSampleSchema = (schema, contentType="", config={}) => {
|
||||
if (/xml/.test(contentType)) {
|
||||
if (!schema.xml || !schema.xml.name) {
|
||||
let name
|
||||
schema.xml = schema.xml || {}
|
||||
|
||||
if (schema.$$ref) {
|
||||
let match = schema.$$ref.match(/\S*\/(\S+)$/)
|
||||
schema.xml.name = match[1]
|
||||
} else if (schema.type || schema.items || schema.properties || schema.additionalProperties) {
|
||||
return '<?xml version="1.0" encoding="UTF-8"?>\n<!-- XML example cannot be generated -->'
|
||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- XML example cannot be generated -->"
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
@@ -549,3 +531,50 @@ export const getSampleSchema = (schema, contentType="", config={}) => {
|
||||
|
||||
return JSON.stringify(memoizedSampleFromSchema(schema, config), null, 2)
|
||||
}
|
||||
|
||||
export const parseSeach = () => {
|
||||
let map = {}
|
||||
let search = window.location.search
|
||||
|
||||
if ( search != "" ) {
|
||||
let params = search.substr(1).split("&")
|
||||
|
||||
for (let i in params) {
|
||||
i = params[i].split("=")
|
||||
map[decodeURIComponent(i[0])] = decodeURIComponent(i[1])
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
export const btoa = (str) => {
|
||||
let buffer
|
||||
|
||||
if (str instanceof Buffer) {
|
||||
buffer = str
|
||||
} else {
|
||||
buffer = new Buffer(str.toString(), "utf-8")
|
||||
}
|
||||
|
||||
return buffer.toString("base64")
|
||||
}
|
||||
|
||||
export const sorters = {
|
||||
operationsSorter: {
|
||||
alpha: (a, b) => a.get("path").localeCompare(b.get("path")),
|
||||
method: (a, b) => a.get("method").localeCompare(b.get("method"))
|
||||
}
|
||||
}
|
||||
|
||||
export const buildFormData = (data) => {
|
||||
let formArr = []
|
||||
|
||||
for (let name in data) {
|
||||
let val = data[name]
|
||||
if (val !== undefined && val !== "") {
|
||||
formArr.push([name, "=", encodeURIComponent(val).replace(/%20/g,"+")].join(""))
|
||||
}
|
||||
}
|
||||
return formArr.join("&")
|
||||
}
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
var win = {
|
||||
location: {},
|
||||
history: {},
|
||||
open: () => {},
|
||||
close: () => {}
|
||||
}
|
||||
|
||||
try {
|
||||
win = window
|
||||
var props = ["File", "Blob", "FormData"]
|
||||
for (var prop of props) {
|
||||
if (prop in window) {
|
||||
win[prop] = window[prop]
|
||||
}
|
||||
function makeWindow() {
|
||||
var win = {
|
||||
location: {},
|
||||
history: {},
|
||||
open: () => {},
|
||||
close: () => {}
|
||||
}
|
||||
} catch( e ) {
|
||||
console.error(e)
|
||||
|
||||
if(typeof window === "undefined") {
|
||||
return win
|
||||
}
|
||||
|
||||
try {
|
||||
win = window
|
||||
var props = ["File", "Blob", "FormData"]
|
||||
for (var prop of props) {
|
||||
if (prop in window) {
|
||||
win[prop] = window[prop]
|
||||
}
|
||||
}
|
||||
} catch( e ) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
return win
|
||||
}
|
||||
|
||||
export default win
|
||||
module.exports = makeWindow()
|
||||
|
||||
@@ -16,22 +16,6 @@ const parseYamlConfig = (yaml, system) => {
|
||||
}
|
||||
}
|
||||
|
||||
const parseSeach = () => {
|
||||
let map = {}
|
||||
let search = window.location.search
|
||||
|
||||
if ( search != "" ) {
|
||||
let params = search.substr(1).split("&");
|
||||
|
||||
for (let i in params) {
|
||||
i = params[i].split("=");
|
||||
map[decodeURIComponent(i[0])] = decodeURIComponent(i[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
export default function configPlugin (toolbox) {
|
||||
let { fn } = toolbox
|
||||
@@ -42,9 +26,7 @@ export default function configPlugin (toolbox) {
|
||||
return fetch(url)
|
||||
},
|
||||
|
||||
getConfigByUrl: (callback)=> ({ specActions }) => {
|
||||
let config = parseSeach()
|
||||
let configUrl = config.config
|
||||
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => {
|
||||
if (configUrl) {
|
||||
return specActions.downloadConfig(configUrl).then(next, next)
|
||||
}
|
||||
@@ -52,9 +34,12 @@ export default function configPlugin (toolbox) {
|
||||
function next(res) {
|
||||
if (res instanceof Error || res.status >= 400) {
|
||||
specActions.updateLoadingStatus("failedConfig")
|
||||
console.log(res.statusText + " " + configUrl)
|
||||
specActions.updateLoadingStatus("failedConfig")
|
||||
specActions.updateUrl("")
|
||||
console.error(res.statusText + " " + configUrl)
|
||||
cb(null)
|
||||
} else {
|
||||
callback(parseYamlConfig(res.text))
|
||||
cb(parseYamlConfig(res.text))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,4 +70,4 @@ export function filterConfigs (configs) {
|
||||
}
|
||||
|
||||
return filteredConfigs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Topbar from './topbar.jsx'
|
||||
import Topbar from "./topbar.jsx"
|
||||
|
||||
export default function () {
|
||||
return {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import StandaloneLayout from './layout'
|
||||
import '../style/main.scss'
|
||||
import StandaloneLayout from "./layout"
|
||||
import "../style/main.scss"
|
||||
|
||||
import TopbarPlugin from "plugins/topbar"
|
||||
import ConfigsPlugin from "plugins/configs"
|
||||
|
||||
// the Standalone preset
|
||||
|
||||
let preset = [
|
||||
TopbarPlugin,
|
||||
ConfigsPlugin,
|
||||
() => {
|
||||
return {
|
||||
components: { StandaloneLayout }
|
||||
@@ -16,4 +14,4 @@ let preset = [
|
||||
}
|
||||
]
|
||||
|
||||
export default preset
|
||||
module.exports = preset
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import React, { PropTypes } from "react"
|
||||
|
||||
export default class StandaloneLayout extends React.Component {
|
||||
|
||||
@@ -6,35 +6,23 @@ export default class StandaloneLayout extends React.Component {
|
||||
errSelectors: PropTypes.object.isRequired,
|
||||
errActions: PropTypes.object.isRequired,
|
||||
specActions: PropTypes.object.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired
|
||||
layoutActions: PropTypes.object.isRequired,
|
||||
getComponent: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
let { specSelectors, specActions, getComponent, errSelectors, errActions, spec, readOnly } = this.props
|
||||
let { getComponent, specSelectors } = this.props
|
||||
|
||||
let info = specSelectors.info()
|
||||
let url = specSelectors.url()
|
||||
let basePath = specSelectors.basePath()
|
||||
let host = specSelectors.host()
|
||||
let securityDefinitions = specSelectors.securityDefinitions()
|
||||
let externalDocs = specSelectors.externalDocs()
|
||||
let schemes = specSelectors.schemes()
|
||||
|
||||
let Info = getComponent("info")
|
||||
let Operations = getComponent("operations", true)
|
||||
let Models = getComponent("models", true)
|
||||
let AuthorizeBtn = getComponent("authorizeBtn", true)
|
||||
let Container = getComponent("Container")
|
||||
let Row = getComponent("Row")
|
||||
let Col = getComponent("Col")
|
||||
let Button = getComponent("Button")
|
||||
let Errors = getComponent("errors", true)
|
||||
const SplitPaneMode = getComponent("SplitPaneMode", true)
|
||||
const Schemes = getComponent("schemes")
|
||||
|
||||
const Topbar = getComponent("Topbar", true)
|
||||
const BaseLayout = getComponent("BaseLayout", true)
|
||||
const OnlineValidatorBadge = getComponent("onlineValidatorBadge", true)
|
||||
|
||||
const loadingStatus = specSelectors.loadingStatus()
|
||||
|
||||
return (
|
||||
@@ -56,43 +44,12 @@ export default class StandaloneLayout extends React.Component {
|
||||
<h4 className="title">Failed to load config.</h4>
|
||||
</div>
|
||||
}
|
||||
{ loadingStatus === "success" &&
|
||||
<div>
|
||||
<Errors/>
|
||||
<Row className="information-container">
|
||||
<Col mobile={12}>
|
||||
{ info.count() ? (
|
||||
<Info info={ info } url={ url } host={ host } basePath={ basePath } externalDocs={externalDocs} getComponent={getComponent}/>
|
||||
) : null }
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="scheme-container">
|
||||
<Col className="schemes wrapper" mobile={12}>
|
||||
{ schemes && schemes.size ? (
|
||||
<Schemes schemes={ schemes } specActions={ specActions } />
|
||||
) : null }
|
||||
{ securityDefinitions ? (
|
||||
<AuthorizeBtn />
|
||||
) : null }
|
||||
</Col>
|
||||
</div>
|
||||
<Row>
|
||||
<Col mobile={12} desktop={12} >
|
||||
<Operations/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col mobile={12} desktop={12} >
|
||||
<Models/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div> }
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<OnlineValidatorBadge />
|
||||
</Col>
|
||||
</Row>
|
||||
{ !loadingStatus || loadingStatus === "success" && <BaseLayout/> }
|
||||
<Row>
|
||||
<Col>
|
||||
<OnlineValidatorBadge />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -136,8 +136,8 @@
|
||||
|
||||
svg
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,26 @@
|
||||
border-radius: 4px;
|
||||
background: rgba($_color-delete, .1);
|
||||
|
||||
.error-wrapper
|
||||
{
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.errors
|
||||
{
|
||||
h4
|
||||
{
|
||||
font-size: 14px;
|
||||
|
||||
margin: 0 0 10px 0;
|
||||
margin: 0;
|
||||
|
||||
@include text_code();
|
||||
}
|
||||
|
||||
small
|
||||
{
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
hgroup
|
||||
|
||||
@@ -286,12 +286,37 @@ body
|
||||
@include method($_color-get);
|
||||
}
|
||||
|
||||
&.opblock-patch
|
||||
{
|
||||
@include method($_color-patch);
|
||||
}
|
||||
|
||||
&.opblock-head
|
||||
{
|
||||
@include method($_color-head);
|
||||
}
|
||||
|
||||
&.opblock-options
|
||||
{
|
||||
@include method($_color-options);
|
||||
}
|
||||
|
||||
&.opblock-deprecated
|
||||
{
|
||||
opacity: .6;
|
||||
|
||||
@include method($_color-disabled);
|
||||
}
|
||||
|
||||
.opblock-schemes
|
||||
{
|
||||
padding: 8px 20px;
|
||||
|
||||
.schemes-title
|
||||
{
|
||||
padding: 0 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -467,6 +492,8 @@ body
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
|
||||
white-space: pre-wrap;
|
||||
|
||||
border-radius: 4px;
|
||||
background: #41444e;
|
||||
|
||||
@@ -475,6 +502,11 @@ body
|
||||
{
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.headerline
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.scheme-container
|
||||
|
||||
Reference in New Issue
Block a user