Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5bd9846
default to empty `ImmutableMap` when grabbing op metadata
shockey Jan 26, 2018
5730288
pass `errors` into JsonSchema components
shockey Jan 26, 2018
46b9790
Account for Immutable data structure in JavaScriptonSchema...
shockey Jan 26, 2018
0589349
Pass ImmutableList through to JsonSchema child components
shockey Jan 26, 2018
017556d
Merge branch 'master' of github.com:swagger-api/swagger-ui
shockey Jan 27, 2018
11c14ea
Merge branch 'master' of github.com:swagger-api/swagger-ui
shockey Jan 27, 2018
d3a31e5
Merge branch 'master' of github.com:swagger-api/swagger-ui
shockey Feb 3, 2018
c86e9a8
Add lazy resolving spec state extensions
shockey Feb 9, 2018
d642b57
TEMPORARY: disable conventional resolved spec
shockey Feb 9, 2018
22a64fd
WIP
shockey Feb 10, 2018
f31b6c0
Use resolveSubtree in Operation display
shockey Feb 12, 2018
13cf9b9
Freebie: short-circuit Markdown component if it is given plaintext
shockey Feb 12, 2018
ff90ef3
NEW DEFAULT BEHAVIOR: `defaultModelsExpandDepth: 1` does not expand i…
shockey Feb 13, 2018
ec06826
Render faked Model expander to trigger resolution
shockey Feb 14, 2018
860a868
Baseline support for Editor lifecycles
shockey Feb 16, 2018
e3514d5
Display operation summaries before the operation is resolved
shockey Feb 16, 2018
f76e928
Test migrations
shockey Feb 16, 2018
d1f235d
WIP
shockey Feb 17, 2018
1235932
Swagger2 TIO Body params
shockey Feb 21, 2018
4e1a36e
a bit of cleanup
shockey Feb 21, 2018
d35abfe
Debounce string param inputs
shockey Feb 21, 2018
cd73087
Reach into unresolved operation for deprecated flag, if available
shockey Feb 21, 2018
762d8f1
Fire subtree request outside of render
shockey Feb 21, 2018
579dfb9
Remove debugging flags
shockey Feb 21, 2018
a44017b
Merge branch 'master' of github.com:swagger-api/swagger-ui into featu…
shockey Feb 21, 2018
795a595
Fix logical errors in spec statePlugins
shockey Feb 23, 2018
9015026
TODOs become TODONEs!
shockey Feb 23, 2018
e419594
Migrate deeplinking feature to non-resolved spec action
shockey Feb 23, 2018
496ed42
ESLint fixes
shockey Feb 23, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"react-addons-shallow-compare": "0.14.8",
"react-addons-test-utils": "^15.6.2",
"react-collapse": "^4.0.3",
"react-debounce-input": "^3.2.0",
"react-dom": "^15.6.2",
"react-height": "^2.0.0",
"react-hot-loader": "1.3.1",
Expand Down
36 changes: 27 additions & 9 deletions src/core/components/model-collapse.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ export default class ModelCollapse extends Component {
children: PropTypes.any,
title: PropTypes.element,
modelName: PropTypes.string,
onToggle: PropTypes.func
classes: PropTypes.string,
onToggle: PropTypes.func,
hideSelfOnExpand: PropTypes.bool,
}

static defaultProps = {
collapsedContent: "{...}",
expanded: false,
title: null,
onToggle: () => {}
onToggle: () => {},
hideSelfOnExpand: false
}

constructor(props, context) {
Expand All @@ -29,17 +32,23 @@ export default class ModelCollapse extends Component {
}
}

componentWillReceiveProps(nextProps){
componentDidMount() {
const { hideSelfOnExpand, expanded, modelName } = this.props
if(hideSelfOnExpand && expanded) {
// We just mounted pre-expanded, and we won't be going back..
// So let's give our parent an `onToggle` call..
// Since otherwise it will never be called.
this.props.onToggle(modelName, expanded)
}
}

if(this.props.expanded!= nextProps.expanded){
componentWillReceiveProps(nextProps){
if(this.props.expanded !== nextProps.expanded){
this.setState({expanded: nextProps.expanded})
}

}

toggleCollapsed=()=>{


if(this.props.onToggle){
this.props.onToggle(this.props.modelName,!this.state.expanded)
}
Expand All @@ -50,9 +59,18 @@ export default class ModelCollapse extends Component {
}

render () {
const {title} = this.props
const { title, classes } = this.props

if(this.state.expanded ) {
if(this.props.hideSelfOnExpand) {
return <span className={classes || ""}>
{this.props.children}
</span>
}
}

return (
<span>
<span className={classes || ""}>
{ title && <span onClick={this.toggleCollapsed} style={{ "cursor": "pointer" }}>{title}</span> }
<span onClick={ this.toggleCollapsed } style={{ "cursor": "pointer" }}>
<span className={ "model-toggle" + ( this.state.expanded ? "" : " collapsed" ) }></span>
Expand Down
63 changes: 52 additions & 11 deletions src/core/components/models.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,41 @@ export default class Models extends Component {
static propTypes = {
getComponent: PropTypes.func,
specSelectors: PropTypes.object,
specActions: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object,
layoutActions: PropTypes.object,
getConfigs: PropTypes.func.isRequired
}

getSchemaBasePath = () => {
const isOAS3 = this.props.specSelectors.isOAS3()
return isOAS3 ? ["components", "schemas"] : ["definitions"]
}

getCollapsedContent = () => {
return " "
}

handleToggle = (name, isExpanded) => {
const { layoutActions } = this.props
layoutActions.show(["models", name], isExpanded)
if(isExpanded) {
this.props.specActions.requestResolvedSubtree([...this.getSchemaBasePath(), name])
}
}

render(){
let { specSelectors, getComponent, layoutSelectors, layoutActions, getConfigs } = this.props
let definitions = specSelectors.definitions()
let { docExpansion, defaultModelsExpandDepth } = getConfigs()
if (!definitions.size || defaultModelsExpandDepth < 0) return null

let showModels = layoutSelectors.isShown("models", defaultModelsExpandDepth > 0 && docExpansion !== "none")
const specPathBase = specSelectors.isOAS3() ? ["components", "schemas"] : ["definitions"]
const specPathBase = this.getSchemaBasePath()

const ModelWrapper = getComponent("ModelWrapper")
const Collapse = getComponent("Collapse")
const ModelCollapse = getComponent("ModelCollapse")

return <section className={ showModels ? "models is-open" : "models"}>
<h4 onClick={() => layoutActions.show("models", !showModels)}>
Expand All @@ -32,18 +51,40 @@ export default class Models extends Component {
</h4>
<Collapse isOpened={showModels}>
{
definitions.entrySeq().map( ( [ name, model ])=>{
definitions.entrySeq().map( ( [ name ])=>{

const schema = specSelectors.specResolvedSubtree([...specPathBase, name])

if(layoutSelectors.isShown(["models", name], false) && schema === undefined) {
// Firing an action in a container render is not great,
// but it works for now.
this.props.specActions.requestResolvedSubtree([...this.getSchemaBasePath(), name])
}

const content = <ModelWrapper name={ name }
expandDepth={ defaultModelsExpandDepth }
schema={ schema }
specPath={Im.List([...specPathBase, name])}
getComponent={ getComponent }
specSelectors={ specSelectors }
getConfigs = {getConfigs}
layoutSelectors = {layoutSelectors}
layoutActions = {layoutActions}/>

const title = <span className="model-box">
<span className="model model-title">{name}</span>
</span>

return <div id={ `model-${name}` } className="model-container" key={ `models-section-${name}` }>
<ModelWrapper name={ name }
expandDepth={ defaultModelsExpandDepth }
schema={ model }
specPath={Im.List([...specPathBase, name])}
getComponent={ getComponent }
specSelectors={ specSelectors }
getConfigs = {getConfigs}
layoutSelectors = {layoutSelectors}
layoutActions = {layoutActions}/>
<ModelCollapse
classes="model-box"
collapsedContent={this.getCollapsedContent(name)}
onToggle={this.handleToggle}
title={title}
modelName={name}
hideSelfOnExpand={true}
expanded={defaultModelsExpandDepth > 1}
>{content}</ModelCollapse>
</div>
}).toArray()
}
Expand Down
15 changes: 9 additions & 6 deletions src/core/components/operation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default class Operation extends PureComponent {
static propTypes = {
specPath: ImPropTypes.list.isRequired,
operation: PropTypes.instanceOf(Iterable).isRequired,
summary: PropTypes.string,
response: PropTypes.instanceOf(Iterable),
request: PropTypes.instanceOf(Iterable),

Expand All @@ -34,7 +35,8 @@ export default class Operation extends PureComponent {
operation: null,
response: null,
request: null,
specPath: List()
specPath: List(),
summary: ""
}

render() {
Expand All @@ -59,6 +61,8 @@ export default class Operation extends PureComponent {
let operationProps = this.props.operation

let {
summary,
deprecated,
isShown,
isAuthorized,
path,
Expand All @@ -76,14 +80,13 @@ export default class Operation extends PureComponent {
} = operationProps.toJS()

let {
summary,
summary: resolvedSummary,
description,
deprecated,
externalDocs,
schemes
} = op.operation
} = op

let operation = operationProps.getIn(["op", "operation"])
let operation = operationProps.getIn(["op"])
let security = operationProps.get("security")
let responses = operation.get("responses")
let produces = operation.get("produces")
Expand Down Expand Up @@ -132,7 +135,7 @@ export default class Operation extends PureComponent {

{ !showSummary ? null :
<div className="opblock-summary-description">
{ summary }
{ resolvedSummary || summary }
</div>
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/components/param-body.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default class ParamBody extends PureComponent {

updateValues = (props) => {
let { specSelectors, pathMethod, param, isExecute, consumesValue="" } = props
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) : fromJS({})
let parameter = specSelectors ? specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) : fromJS({})
let isXml = /xml/i.test(consumesValue)
let isJson = /json/i.test(consumesValue)
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")
Expand Down Expand Up @@ -107,7 +107,7 @@ export default class ParamBody extends PureComponent {
const HighlightCode = getComponent("highlightCode")
const ContentType = getComponent("contentType")
// for domains where specSelectors not passed
let parameter = specSelectors ? specSelectors.getParameter(pathMethod, param.get("name"), param.get("in")) : param
let parameter = specSelectors ? specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in")) : param
let errors = parameter.get("errors", List())
let consumesValue = specSelectors.contentTypeValues(pathMethod).get("requestContentType")
let consumes = this.props.consumes && this.props.consumes.size ? this.props.consumes : ParamBody.defaultProp.consumes
Expand Down
7 changes: 3 additions & 4 deletions src/core/components/parameter-row.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default class ParameterRow extends Component {

let { specSelectors, pathMethod, param } = props
let defaultValue = param.get("default")
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
let value = parameter ? parameter.get("value") : ""
if ( defaultValue !== undefined && value === undefined ) {
this.onChangeWrapper(defaultValue)
Expand All @@ -37,7 +37,7 @@ export default class ParameterRow extends Component {

let example = param.get("example")
let defaultValue = param.get("default")
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
let enumValue

if(isOAS3()) {
Expand Down Expand Up @@ -104,8 +104,7 @@ export default class ParameterRow extends Component {
let isFormDataSupported = "FormData" in win
let required = param.get("required")
let itemType = param.getIn(isOAS3 && isOAS3() ? ["schema", "items", "type"] : ["items", "type"])
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
let value = parameter ? parameter.get("value") : ""
let value = param ? param.get("value") : ""
let extensions = getExtensions(param)


Expand Down
2 changes: 1 addition & 1 deletion src/core/components/parameters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default class Parameters extends Component {
specPath={specPath.push(i.toString())}
getComponent={ getComponent }
getConfigs={ getConfigs }
param={ parameter }
param={ specSelectors.parameterWithMeta(pathMethod, parameter.get("name"), parameter.get("in")) }
key={ `${parameter.get( "in" )}.${parameter.get("name")}` }
onChange={ this.onChange }
onChangeConsumes={this.onChangeConsumesWrapper}
Expand Down
10 changes: 10 additions & 0 deletions src/core/components/providers/markdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@ import PropTypes from "prop-types"
import Remarkable from "remarkable"
import sanitize from "sanitize-html"

// eslint-disable-next-line no-useless-escape
const isPlainText = (str) => /^[A-Z\s0-9!?\.]+$/gi.test(str)

function Markdown({ source }) {
if(isPlainText(source)) {
// If the source text is not Markdown,
// let's save some time and just render it.
return <div className="markdown">
{source}
</div>
}
const html = new Remarkable({
html: true,
typographer: true,
Expand Down
25 changes: 20 additions & 5 deletions src/core/containers/OperationContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { helpers } from "swagger-client"
import { Iterable, fromJS } from "immutable"
import { Iterable, fromJS, Map } from "immutable"

const { opId } = helpers

Expand Down Expand Up @@ -82,13 +82,24 @@ export default class OperationContainer extends PureComponent {
}

componentWillReceiveProps(nextProps) {
if(nextProps.response !== this.props.response) {
const { path, method, specActions, specSelectors, response, isShown } = nextProps
const resolvedSubtree = specSelectors.specResolvedSubtree(["paths", path, method])

if(response !== this.props.response) {
this.setState({ executeInProgress: false })
}

if(isShown && resolvedSubtree === undefined) {
specActions.requestResolvedSubtree(["paths", path, method])
}
}

toggleShown =() => {
let { layoutActions, tag, operationId, isShown } = this.props
let { layoutActions, specActions, tag, operationId, path, method, isShown } = this.props
if(!isShown) {
// transitioning from collapsed to expanded
specActions.requestResolvedSubtree(["paths", path, method])
}
layoutActions.show(["operations", tag, operationId], !isShown)
}

Expand All @@ -108,7 +119,7 @@ export default class OperationContainer extends PureComponent {

render() {
let {
op,
op: unresolvedOp,
tag,
path,
method,
Expand Down Expand Up @@ -140,10 +151,14 @@ export default class OperationContainer extends PureComponent {

const Operation = getComponent( "operation" )

const resolvedSubtree = specSelectors.specResolvedSubtree(["paths", path, method]) || Map()

const operationProps = fromJS({
op,
op: resolvedSubtree || Map(),
tag,
path,
summary: unresolvedOp.getIn(["operation", "summary"]) || "",
deprecated: resolvedSubtree.get("deprecated") || unresolvedOp.getIn(["operation", "deprecated"]) || false,
method,
security,
isAuthorized,
Expand Down
6 changes: 5 additions & 1 deletion src/core/json-schema-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { PureComponent, Component } from "react"
import PropTypes from "prop-types"
import { List, fromJS } from "immutable"
import ImPropTypes from "react-immutable-proptypes"
import DebounceInput from "react-debounce-input"
//import "less/json-schema-form"

const noop = ()=> {}
Expand Down Expand Up @@ -79,10 +80,13 @@ export class JsonSchema_string extends Component {
disabled={isDisabled}/>)
}
else {
return (<Input type={ schema.format === "password" ? "password" : "text" }
return (<DebounceInput
type={ schema.format === "password" ? "password" : "text" }
className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
value={value}
minLength={0}
debounceTimeout={350}
placeholder={description}
onChange={ this.onChange }
disabled={isDisabled}/>)
Expand Down
2 changes: 1 addition & 1 deletion src/core/plugins/deep-linking/spec-wrap-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { escapeDeepLinkPath } from "core/utils"
let hasHashBeenParsed = false //TODO this forces code to only run once which may prevent scrolling if page not refreshed


export const updateResolved = (ori, { layoutActions, getConfigs }) => (...args) => {
export const updateJsonSpec = (ori, { layoutActions, getConfigs }) => (...args) => {
ori(...args)

const isDeepLinkingEnabled = getConfigs().deepLinking
Expand Down
Loading