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 )
|
||||
}
|
||||
|
||||
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")
|
||||
isRef = isRef !== undefined ? isRef : !!$$ref
|
||||
type = schema && schema.get("type") || type
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getExtensions, sanitizeUrl } from "core/utils"
|
||||
import { Iterable, List } from "immutable"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
|
||||
|
||||
export default class Operation extends PureComponent {
|
||||
static propTypes = {
|
||||
specPath: ImPropTypes.list.isRequired,
|
||||
@@ -155,6 +156,9 @@ export default class Operation extends PureComponent {
|
||||
|
||||
<Collapse isOpened={isShown}>
|
||||
<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>}
|
||||
{ description &&
|
||||
<div className="opblock-description-wrapper">
|
||||
@@ -176,23 +180,25 @@ export default class Operation extends PureComponent {
|
||||
</div> : null
|
||||
}
|
||||
|
||||
<Parameters
|
||||
parameters={parameters}
|
||||
specPath={specPath.push("parameters")}
|
||||
operation={operation}
|
||||
onChangeKey={onChangeKey}
|
||||
onTryoutClick = { onTryoutClick }
|
||||
onCancelClick = { onCancelClick }
|
||||
tryItOutEnabled = { tryItOutEnabled }
|
||||
allowTryItOut={allowTryItOut}
|
||||
{ !operation || !operation.size ? null :
|
||||
<Parameters
|
||||
parameters={parameters}
|
||||
specPath={specPath.push("parameters")}
|
||||
operation={operation}
|
||||
onChangeKey={onChangeKey}
|
||||
onTryoutClick = { onTryoutClick }
|
||||
onCancelClick = { onCancelClick }
|
||||
tryItOutEnabled = { tryItOutEnabled }
|
||||
allowTryItOut={allowTryItOut}
|
||||
|
||||
fn={fn}
|
||||
getComponent={ getComponent }
|
||||
specActions={ specActions }
|
||||
specSelectors={ specSelectors }
|
||||
pathMethod={ [path, method] }
|
||||
getConfigs={ getConfigs }
|
||||
/>
|
||||
fn={fn}
|
||||
getComponent={ getComponent }
|
||||
specActions={ specActions }
|
||||
specSelectors={ specSelectors }
|
||||
pathMethod={ [path, method] }
|
||||
getConfigs={ getConfigs }
|
||||
/>
|
||||
}
|
||||
|
||||
{ !tryItOutEnabled ? null :
|
||||
<OperationServers
|
||||
|
||||
@@ -30,7 +30,9 @@ export default function downloadUrlPlugin (toolbox) {
|
||||
}
|
||||
specActions.updateLoadingStatus("success")
|
||||
specActions.updateSpec(res.text)
|
||||
specActions.updateUrl(url)
|
||||
if(specSelectors.url() !== url) {
|
||||
specActions.updateUrl(url)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import YAML from "js-yaml"
|
||||
import { Map } from "immutable"
|
||||
import parseUrl from "url-parse"
|
||||
import serializeError from "serialize-error"
|
||||
import { Map } from "immutable"
|
||||
import isString from "lodash/isString"
|
||||
import debounce from "lodash/debounce"
|
||||
import set from "lodash/set"
|
||||
import { isJSONObject } from "core/utils"
|
||||
|
||||
// Actions conform to FSA (flux-standard-actions)
|
||||
@@ -133,39 +135,48 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio
|
||||
})
|
||||
}
|
||||
|
||||
export const requestResolvedSubtree = path => system => {
|
||||
const {
|
||||
errActions,
|
||||
fn: {
|
||||
resolveSubtree,
|
||||
AST: { getLineNumberForPath }
|
||||
},
|
||||
specSelectors,
|
||||
specActions,
|
||||
} = system
|
||||
let requestBatch = []
|
||||
|
||||
const specStr = specSelectors.specStr()
|
||||
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 {
|
||||
errActions,
|
||||
errSelectors,
|
||||
fn: {
|
||||
resolveSubtree,
|
||||
AST: { getLineNumberForPath }
|
||||
},
|
||||
specSelectors,
|
||||
specActions,
|
||||
} = system
|
||||
|
||||
if(!resolveSubtree) {
|
||||
console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing.")
|
||||
return
|
||||
}
|
||||
|
||||
const currentValue = specSelectors.specResolvedSubtree(path)
|
||||
const specStr = specSelectors.specStr()
|
||||
|
||||
if(currentValue) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
var batchResult = await requestBatch.reduce(async (prev, path) => {
|
||||
const { resultMap, specWithCurrentSubtrees } = await prev
|
||||
|
||||
const { errors, spec } = await resolveSubtree(specWithCurrentSubtrees, path)
|
||||
|
||||
if(errSelectors.allErrors().size) {
|
||||
errActions.clear({
|
||||
type: "thrown"
|
||||
})
|
||||
}
|
||||
|
||||
return resolveSubtree(specSelectors.specJson().toJS(), path)
|
||||
.then(({ spec, errors }) => {
|
||||
errActions.clear({
|
||||
type: "thrown"
|
||||
})
|
||||
if(Array.isArray(errors) && errors.length > 0) {
|
||||
let preparedErrors = errors
|
||||
.map(err => {
|
||||
console.error(err)
|
||||
err.line = err.fullPath ? getLineNumberForPath(specStr, err.fullPath) : null
|
||||
err.path = err.fullPath ? err.fullPath.join(".") : null
|
||||
err.level = "error"
|
||||
@@ -177,9 +188,31 @@ export const requestResolvedSubtree = path => system => {
|
||||
errActions.newThrownErrBatch(preparedErrors)
|
||||
}
|
||||
|
||||
return specActions.updateResolvedSubtree(path, spec)
|
||||
})
|
||||
.catch(e => console.error(e))
|
||||
set(resultMap, path, spec)
|
||||
set(specWithCurrentSubtrees, path, spec)
|
||||
|
||||
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 ){
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user