Merge branch 'master' into clickfix
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,25 +10,27 @@ 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) {
|
||||
super(props, context)
|
||||
let { name, schema, authorized } = this.props
|
||||
let { name, schema, authorized, authSelectors } = this.props
|
||||
let auth = authorized && authorized.get(name)
|
||||
let authConfigs = authSelectors.getConfigs() || {}
|
||||
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 clientId = auth && auth.get("clientId") || authConfigs.clientId || ""
|
||||
let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || ""
|
||||
let passwordType = auth && auth.get("passwordType") || "basic"
|
||||
|
||||
this.state = {
|
||||
appName: authConfigs.appName,
|
||||
name: name,
|
||||
schema: schema,
|
||||
scopes: [],
|
||||
@@ -41,11 +43,12 @@ export default class Oauth2 extends React.Component {
|
||||
}
|
||||
|
||||
authorize =() => {
|
||||
let { authActions, errActions, getConfigs } = this.props
|
||||
let { authActions, errActions, getConfigs, authSelectors } = this.props
|
||||
let configs = getConfigs()
|
||||
let authConfigs = authSelectors.getConfigs()
|
||||
|
||||
errActions.clear({authId: name,type: "auth", source: "auth"})
|
||||
oauth2Authorize(this.state, authActions, errActions, configs)
|
||||
oauth2Authorize({auth: this.state, authActions, errActions, configs, authConfigs })
|
||||
}
|
||||
|
||||
onScopeChange =(e) => {
|
||||
@@ -98,6 +101,7 @@ export default class Oauth2 extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
|
||||
{ !this.state.appName ? null : <h5>Application: { this.state.appName } </h5> }
|
||||
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}}
|
||||
source={ schema.get("description") } />
|
||||
|
||||
@@ -108,82 +112,92 @@ 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 }
|
||||
value={ this.state.clientId }
|
||||
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"
|
||||
value={ this.state.clientSecret }
|
||||
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 (
|
||||
<Row key={ name }>
|
||||
<div className="checkbox">
|
||||
<Input data-value={ name }
|
||||
id={`${name}-checkbox`}
|
||||
id={`${name}-checkbox-${this.state.name}`}
|
||||
disabled={ isAuthorized }
|
||||
type="checkbox"
|
||||
onChange={ this.onScopeChange }/>
|
||||
<label htmlFor={`${name}-checkbox`}>
|
||||
<label htmlFor={`${name}-checkbox-${this.state.name}`}>
|
||||
<span className="item"></span>
|
||||
<div className="text">
|
||||
<p className="name">{name}</p>
|
||||
@@ -205,7 +219,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,19 +1,22 @@
|
||||
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 {
|
||||
|
||||
static propTypes = {
|
||||
jumpToLine: PropTypes.func,
|
||||
editorActions: PropTypes.object,
|
||||
errSelectors: PropTypes.object.isRequired,
|
||||
layoutSelectors: PropTypes.object.isRequired,
|
||||
layoutActions: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
let { jumpToLine, errSelectors, layoutSelectors, layoutActions } = this.props
|
||||
let { editorActions, errSelectors, layoutSelectors, layoutActions } = this.props
|
||||
|
||||
if(editorActions && editorActions.jumpToLine) {
|
||||
var jumpToLine = editorActions.jumpToLine
|
||||
}
|
||||
|
||||
let errors = errSelectors.allErrors()
|
||||
|
||||
@@ -38,10 +41,11 @@ export default class Errors extends React.Component {
|
||||
<Collapse isOpened={ isVisible } animated >
|
||||
<div className="errors">
|
||||
{ sortedJSErrors.map((err, i) => {
|
||||
if(err.get("type") === "thrown") {
|
||||
let type = err.get("type")
|
||||
if(type === "thrown" || type === "auth") {
|
||||
return <ThrownErrorItem key={ i } error={ err.get("error") || err } jumpToLine={jumpToLine} />
|
||||
}
|
||||
if(err.get("type") === "spec") {
|
||||
if(type === "spec") {
|
||||
return <SpecErrorItem key={ i } error={ err } jumpToLine={jumpToLine} />
|
||||
}
|
||||
}) }
|
||||
@@ -69,7 +73,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,13 +82,25 @@ 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>
|
||||
<div style={{ "text-decoration": "underline", "cursor": "pointer" }}>
|
||||
{ jumpToLine ? (
|
||||
<a onClick={jumpToLine.bind(null, error.get("line"))}>Jump to line { error.get("line") }</a>
|
||||
) : null }
|
||||
@@ -107,6 +123,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
|
||||
|
||||
@@ -127,7 +127,7 @@ export const Input = (props) => <input {...props} />
|
||||
|
||||
export class Select extends React.Component {
|
||||
static propTypes = {
|
||||
allowedValues: PropTypes.object,
|
||||
allowedValues: PropTypes.array,
|
||||
value: PropTypes.any,
|
||||
onChange: PropTypes.func,
|
||||
multiple: PropTypes.bool,
|
||||
|
||||
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()
|
||||
|
||||
@@ -58,12 +56,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})
|
||||
|
||||
@@ -28,11 +28,25 @@ export default class ParameterRow extends Component {
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
let { specSelectors, pathMethod, param } = props
|
||||
let example = param.get("example")
|
||||
let defaultValue = param.get("default")
|
||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"))
|
||||
let value = parameter ? parameter.get("value") : ""
|
||||
if ( defaultValue !== undefined && value === undefined ) {
|
||||
this.onChangeWrapper(defaultValue)
|
||||
let paramValue = parameter ? parameter.get("value") : undefined
|
||||
let enumValue = parameter ? parameter.get("enum") : undefined
|
||||
let value
|
||||
|
||||
if ( paramValue !== undefined ) {
|
||||
value = paramValue
|
||||
} else if ( example !== undefined ) {
|
||||
value = example
|
||||
} else if ( defaultValue !== undefined) {
|
||||
value = defaultValue
|
||||
} else if ( param.get("required") && enumValue && enumValue.size ) {
|
||||
value = enumValue.first()
|
||||
}
|
||||
|
||||
if ( value !== undefined ) {
|
||||
this.onChangeWrapper(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user