feat(oas31): add support for Schema Object discriminator keyword (#8658)

Refs #8513
This commit is contained in:
Vladimír Gorej
2023-05-11 17:20:23 +02:00
committed by GitHub
parent 9bb5a210c0
commit 11bb4f9b30
6 changed files with 125 additions and 5 deletions

View File

@@ -52,6 +52,7 @@ import {
import { selectLicenseUrl as selectOAS31LicenseUrl } from "./selectors"
import JSONSchema202012KeywordExample from "./json-schema-2020-12-extensions/components/keywords/Example"
import JSONSchema202012KeywordXml from "./json-schema-2020-12-extensions/components/keywords/Xml"
import JSONSchema202012KeywordDiscriminator from "./json-schema-2020-12-extensions/components/keywords/Discriminator/Discriminator"
import JSONSchema202012KeywordDescriptionWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Description"
import JSONSchema202012KeywordDefaultWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Default"
import { makeIsExpandable } from "./json-schema-2020-12-extensions/fn"
@@ -86,6 +87,7 @@ const OAS31Plugin = ({ getSystem }) => {
OAS31Models: Models,
JSONSchema202012KeywordExample,
JSONSchema202012KeywordXml,
JSONSchema202012KeywordDiscriminator,
},
wrapComponents: {
InfoContainer: InfoWrapper,

View File

@@ -0,0 +1,76 @@
/**
* @prettier
*/
import React, { useCallback, useState } from "react"
import PropTypes from "prop-types"
import classNames from "classnames"
import DiscriminatorMapping from "./DiscriminatorMapping"
const Discriminator = ({ schema, getSystem }) => {
const discriminator = schema?.discriminator || {}
const { fn, getComponent } = getSystem()
const { useIsExpandedDeeply, useComponent } = fn.jsonSchema202012
const isExpandedDeeply = useIsExpandedDeeply()
const [expanded, setExpanded] = useState(isExpandedDeeply)
const [expandedDeeply, setExpandedDeeply] = useState(false)
const Accordion = useComponent("Accordion")
const ExpandDeepButton = useComponent("ExpandDeepButton")
const JSONSchemaDeepExpansionContext = getComponent(
"JSONSchema202012DeepExpansionContext"
)()
/**
* Event handlers.
*/
const handleExpansion = useCallback(() => {
setExpanded((prev) => !prev)
}, [])
const handleExpansionDeep = useCallback((e, expandedDeepNew) => {
setExpanded(expandedDeepNew)
setExpandedDeeply(expandedDeepNew)
}, [])
/**
* Rendering.
*/
if (Object.keys(discriminator).length === 0) {
return null
}
return (
<JSONSchemaDeepExpansionContext.Provider value={expandedDeeply}>
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--discriminator">
<Accordion expanded={expanded} onChange={handleExpansion}>
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--secondary">
Discriminator
</span>
</Accordion>
<ExpandDeepButton expanded={expanded} onClick={handleExpansionDeep} />
{discriminator.propertyName && (
<span className="json-schema-2020-12__attribute json-schema-2020-12__attribute--muted">
{discriminator.propertyName}
</span>
)}
<ul
className={classNames("json-schema-2020-12-keyword__children", {
"json-schema-2020-12-keyword__children--collapsed": !expanded,
})}
>
{expanded && (
<li className="json-schema-2020-12-property">
<DiscriminatorMapping discriminator={discriminator} />
</li>
)}
</ul>
</div>
</JSONSchemaDeepExpansionContext.Provider>
)
}
Discriminator.propTypes = {
schema: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
getSystem: PropTypes.func.isRequired,
}
export default Discriminator

View File

@@ -0,0 +1,36 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const DiscriminatorMapping = ({ discriminator }) => {
const mapping = discriminator?.mapping || {}
if (Object.keys(mapping).length === 0) {
return null
}
return Object.entries(mapping).map(([key, value]) => (
<div key={`${key}-${value}`} className="json-schema-2020-12-keyword">
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--secondary">
{key}
</span>
<span className="json-schema-2020-12-keyword__value json-schema-2020-12-keyword__value--secondary">
{value}
</span>
</div>
))
}
DiscriminatorMapping.propTypes = {
discriminator: PropTypes.shape({
mapping: PropTypes.any,
}),
}
DiscriminatorMapping.defaultProps = {
mapping: undefined,
}
export default DiscriminatorMapping

View File

@@ -12,7 +12,7 @@ const Example = ({ schema, getSystem }) => {
return (
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--example">
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--primary">
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--secondary">
Example
</span>
<span className="json-schema-2020-12-keyword__value json-schema-2020-12-keyword__value--const">

View File

@@ -76,7 +76,8 @@ const Xml = ({ schema, getSystem }) => {
</span>
</div>
)}
</li>
<li className="json-schema-2020-12-property">
{xml.namespace && (
<div className="json-schema-2020-12-keyword">
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--secondary">
@@ -87,7 +88,8 @@ const Xml = ({ schema, getSystem }) => {
</span>
</div>
)}
</li>
<li className="json-schema-2020-12-property">
{xml.prefix && (
<div className="json-schema-2020-12-keyword">
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--secondary">

View File

@@ -7,14 +7,18 @@ import { createOnlyOAS31ComponentWrapper } from "../../../fn"
const DefaultWrapper = createOnlyOAS31ComponentWrapper(
({ schema, getSystem, originalComponent: KeywordDefault }) => {
const { getComponent } = getSystem()
const KeywordExample = getComponent("JSONSchema202012KeywordExample")
const KeywordDiscriminator = getComponent(
"JSONSchema202012KeywordDiscriminator"
)
const KeywordXml = getComponent("JSONSchema202012KeywordXml")
const KeywordExample = getComponent("JSONSchema202012KeywordExample")
return (
<>
<KeywordDefault schema={schema} />
<KeywordExample schema={schema} getSystem={getSystem} />
<KeywordDiscriminator schema={schema} getSystem={getSystem} />
<KeywordXml schema={schema} getSystem={getSystem} />
<KeywordExample schema={schema} getSystem={getSystem} />
</>
)
}