improve: lazy resolver (#4253)
* default to empty `ImmutableMap` when grabbing op metadata
* pass `errors` into JsonSchema components
* Account for Immutable data structure in JavaScriptonSchema...
...and create empty Lists instead of Maps by default.
* Pass ImmutableList through to JsonSchema child components
* Add lazy resolving spec state extensions
* TEMPORARY: disable conventional resolved spec
* WIP
* Use resolveSubtree in Operation display
* Freebie: short-circuit Markdown component if it is given plaintext
* NEW DEFAULT BEHAVIOR: `defaultModelsExpandDepth: 1` does not expand individual models
* Render faked Model expander to trigger resolution
* Baseline support for Editor lifecycles
* Display operation summaries before the operation is resolved
* Test migrations
* WIP
* Swagger2 TIO Body params
* a bit of cleanup
* Debounce string param inputs
* Reach into unresolved operation for deprecated flag, if available
* Fire subtree request outside of render
* Remove debugging flags
* Fix logical errors in spec statePlugins
* TODOs become TODONEs!
* Migrate deeplinking feature to non-resolved spec action
* ESLint fixes
* Reduce action dispatch volume; run resolver on next tick
* Batch resolver requests; use batch progressive results in later iterations
* Add loading states to Model and Operation views
* Preserve object order; remove dupl. import; add warning for action
* LINTER!
* Use require to load SVG
Works around Webpack weirdness
This commit is contained in:
@@ -49,6 +49,17 @@ export default class Model extends ImmutablePureComponent {
|
|||||||
schema = this.getRefSchema( name )
|
schema = this.getRefSchema( name )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!schema) {
|
||||||
|
return <span className="model model-title">
|
||||||
|
<span className="model-title__text">{ name }</span>
|
||||||
|
<img src={require("core/../img/rolling-load.svg")} height={"20px"} width={"20px"} style={{
|
||||||
|
marginLeft: "1em",
|
||||||
|
position: "relative",
|
||||||
|
bottom: "0px"
|
||||||
|
}} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
const deprecated = specSelectors.isOAS3() && schema.get("deprecated")
|
const deprecated = specSelectors.isOAS3() && schema.get("deprecated")
|
||||||
isRef = isRef !== undefined ? isRef : !!$$ref
|
isRef = isRef !== undefined ? isRef : !!$$ref
|
||||||
type = schema && schema.get("type") || type
|
type = schema && schema.get("type") || type
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { getExtensions, sanitizeUrl } from "core/utils"
|
|||||||
import { Iterable, List } from "immutable"
|
import { Iterable, List } from "immutable"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
|
|
||||||
|
|
||||||
export default class Operation extends PureComponent {
|
export default class Operation extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
specPath: ImPropTypes.list.isRequired,
|
specPath: ImPropTypes.list.isRequired,
|
||||||
@@ -155,6 +156,9 @@ export default class Operation extends PureComponent {
|
|||||||
|
|
||||||
<Collapse isOpened={isShown}>
|
<Collapse isOpened={isShown}>
|
||||||
<div className="opblock-body">
|
<div className="opblock-body">
|
||||||
|
{ operation && operation.size ? null :
|
||||||
|
<img height={"32px"} width={"32px"} src={require("core/../img/rolling-load.svg")} className="opblock-loading-animation" />
|
||||||
|
}
|
||||||
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>}
|
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>}
|
||||||
{ description &&
|
{ description &&
|
||||||
<div className="opblock-description-wrapper">
|
<div className="opblock-description-wrapper">
|
||||||
@@ -176,6 +180,7 @@ export default class Operation extends PureComponent {
|
|||||||
</div> : null
|
</div> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ !operation || !operation.size ? null :
|
||||||
<Parameters
|
<Parameters
|
||||||
parameters={parameters}
|
parameters={parameters}
|
||||||
specPath={specPath.push("parameters")}
|
specPath={specPath.push("parameters")}
|
||||||
@@ -193,6 +198,7 @@ export default class Operation extends PureComponent {
|
|||||||
pathMethod={ [path, method] }
|
pathMethod={ [path, method] }
|
||||||
getConfigs={ getConfigs }
|
getConfigs={ getConfigs }
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
{ !tryItOutEnabled ? null :
|
{ !tryItOutEnabled ? null :
|
||||||
<OperationServers
|
<OperationServers
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ export default function downloadUrlPlugin (toolbox) {
|
|||||||
}
|
}
|
||||||
specActions.updateLoadingStatus("success")
|
specActions.updateLoadingStatus("success")
|
||||||
specActions.updateSpec(res.text)
|
specActions.updateSpec(res.text)
|
||||||
|
if(specSelectors.url() !== url) {
|
||||||
specActions.updateUrl(url)
|
specActions.updateUrl(url)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import YAML from "js-yaml"
|
import YAML from "js-yaml"
|
||||||
|
import { Map } from "immutable"
|
||||||
import parseUrl from "url-parse"
|
import parseUrl from "url-parse"
|
||||||
import serializeError from "serialize-error"
|
import serializeError from "serialize-error"
|
||||||
import { Map } from "immutable"
|
|
||||||
import isString from "lodash/isString"
|
import isString from "lodash/isString"
|
||||||
|
import debounce from "lodash/debounce"
|
||||||
|
import set from "lodash/set"
|
||||||
import { isJSONObject } from "core/utils"
|
import { isJSONObject } from "core/utils"
|
||||||
|
|
||||||
// Actions conform to FSA (flux-standard-actions)
|
// Actions conform to FSA (flux-standard-actions)
|
||||||
@@ -133,9 +135,18 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const requestResolvedSubtree = path => system => {
|
let requestBatch = []
|
||||||
|
|
||||||
|
const debResolveSubtrees = debounce(async () => {
|
||||||
|
const system = requestBatch.system // Just a reference to the "latest" system
|
||||||
|
|
||||||
|
if(!system) {
|
||||||
|
console.error("debResolveSubtrees: don't have a system to operate on, aborting.")
|
||||||
|
return
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
errActions,
|
errActions,
|
||||||
|
errSelectors,
|
||||||
fn: {
|
fn: {
|
||||||
resolveSubtree,
|
resolveSubtree,
|
||||||
AST: { getLineNumberForPath }
|
AST: { getLineNumberForPath }
|
||||||
@@ -144,28 +155,28 @@ export const requestResolvedSubtree = path => system => {
|
|||||||
specActions,
|
specActions,
|
||||||
} = system
|
} = system
|
||||||
|
|
||||||
const specStr = specSelectors.specStr()
|
|
||||||
|
|
||||||
if(!resolveSubtree) {
|
if(!resolveSubtree) {
|
||||||
console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing.")
|
console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentValue = specSelectors.specResolvedSubtree(path)
|
const specStr = specSelectors.specStr()
|
||||||
|
|
||||||
if(currentValue) {
|
try {
|
||||||
return
|
var batchResult = await requestBatch.reduce(async (prev, path) => {
|
||||||
}
|
const { resultMap, specWithCurrentSubtrees } = await prev
|
||||||
|
|
||||||
return resolveSubtree(specSelectors.specJson().toJS(), path)
|
const { errors, spec } = await resolveSubtree(specWithCurrentSubtrees, path)
|
||||||
.then(({ spec, errors }) => {
|
|
||||||
|
if(errSelectors.allErrors().size) {
|
||||||
errActions.clear({
|
errActions.clear({
|
||||||
type: "thrown"
|
type: "thrown"
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if(Array.isArray(errors) && errors.length > 0) {
|
if(Array.isArray(errors) && errors.length > 0) {
|
||||||
let preparedErrors = errors
|
let preparedErrors = errors
|
||||||
.map(err => {
|
.map(err => {
|
||||||
console.error(err)
|
|
||||||
err.line = err.fullPath ? getLineNumberForPath(specStr, err.fullPath) : null
|
err.line = err.fullPath ? getLineNumberForPath(specStr, err.fullPath) : null
|
||||||
err.path = err.fullPath ? err.fullPath.join(".") : null
|
err.path = err.fullPath ? err.fullPath.join(".") : null
|
||||||
err.level = "error"
|
err.level = "error"
|
||||||
@@ -177,9 +188,31 @@ export const requestResolvedSubtree = path => system => {
|
|||||||
errActions.newThrownErrBatch(preparedErrors)
|
errActions.newThrownErrBatch(preparedErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
return specActions.updateResolvedSubtree(path, spec)
|
set(resultMap, path, spec)
|
||||||
})
|
set(specWithCurrentSubtrees, path, spec)
|
||||||
.catch(e => console.error(e))
|
|
||||||
|
return {
|
||||||
|
resultMap,
|
||||||
|
specWithCurrentSubtrees
|
||||||
|
}
|
||||||
|
}, Promise.resolve({
|
||||||
|
resultMap: (specSelectors.specResolvedSubtree([]) || Map()).toJS(),
|
||||||
|
specWithCurrentSubtrees: specSelectors.specJson().toJS()
|
||||||
|
}))
|
||||||
|
|
||||||
|
delete requestBatch.system
|
||||||
|
requestBatch = [] // Clear stack
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
specActions.updateResolvedSubtree([], batchResult.resultMap)
|
||||||
|
}, 35)
|
||||||
|
|
||||||
|
export const requestResolvedSubtree = path => system => {
|
||||||
|
requestBatch.push(path)
|
||||||
|
requestBatch.system = system
|
||||||
|
debResolveSubtrees()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeParam( path, paramName, paramIn, value, isXml ){
|
export function changeParam( path, paramName, paramIn, value, isXml ){
|
||||||
|
|||||||
1
src/img/rolling-load.svg
Normal file
1
src/img/rolling-load.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="200px" height="200px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-rolling" style="background-image: none; background-position: initial initial; background-repeat: initial initial;"><circle cx="50" cy="50" fill="none" ng-attr-stroke="{{config.color}}" ng-attr-stroke-width="{{config.width}}" ng-attr-r="{{config.radius}}" ng-attr-stroke-dasharray="{{config.dasharray}}" stroke="#555555" stroke-width="10" r="35" stroke-dasharray="164.93361431346415 56.97787143782138"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform></circle></svg>
|
||||||
|
After Width: | Height: | Size: 734 B |
@@ -586,6 +586,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opblock-body
|
||||||
|
{
|
||||||
|
.opblock-loading-animation
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
margin: 3em;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.opblock-body pre
|
.opblock-body pre
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user