refactor(oas31): change Info compnent to be smart (#8479)

Refs #8474
This commit is contained in:
Vladimír Gorej
2023-03-17 10:55:49 +01:00
committed by GitHub
parent a3d3f26c42
commit 865d98d6be
4 changed files with 154 additions and 146 deletions

View File

@@ -3,154 +3,90 @@
*/
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { sanitizeUrl } from "core/utils"
import { safeBuildUrl } from "core/utils/url"
export class InfoBasePath extends React.Component {
static propTypes = {
host: PropTypes.string,
basePath: PropTypes.string,
}
const Info = ({ getComponent, specSelectors }) => {
const version = specSelectors.version()
const url = specSelectors.url()
const basePath = specSelectors.basePath()
const host = specSelectors.host()
const summary = specSelectors.selectInfoSummaryField()
const description = specSelectors.selectInfoDescriptionField()
const title = specSelectors.selectInfoTitleField()
const termsOfServiceUrl = specSelectors.selectInfoTermsOfServiceUrl()
const externalDocsUrl = specSelectors.selectExternalDocsUrl()
const externalDocsDesc = specSelectors.selectExternalDocsDescriptionField()
const contact = specSelectors.contact()
const license = specSelectors.license()
render() {
const { host, basePath } = this.props
const Markdown = getComponent("Markdown", true)
const Link = getComponent("Link")
const VersionStamp = getComponent("VersionStamp")
const InfoUrl = getComponent("InfoUrl")
const InfoBasePath = getComponent("InfoBasePath")
const License = getComponent("License", true)
const Contact = getComponent("Contact", true)
return (
<pre className="base-url">
[ Base URL: {host}
{basePath} ]
</pre>
)
}
}
return (
<div className="info">
<hgroup className="main">
<h2 className="title">
{title}
{version && <VersionStamp version={version}></VersionStamp>}
</h2>
export class InfoUrl extends React.PureComponent {
static propTypes = {
url: PropTypes.string.isRequired,
getComponent: PropTypes.func.isRequired,
}
{(host || basePath) && <InfoBasePath host={host} basePath={basePath} />}
{url && <InfoUrl getComponent={getComponent} url={url} />}
</hgroup>
render() {
const { url, getComponent } = this.props
const Link = getComponent("Link")
{summary && <p className="info__summary">{summary}</p>}
return (
<Link target="_blank" href={sanitizeUrl(url)}>
<span className="url"> {url}</span>
</Link>
)
}
}
class Info extends React.Component {
static propTypes = {
title: PropTypes.any,
description: PropTypes.any,
version: PropTypes.any,
info: PropTypes.object,
url: PropTypes.string,
host: PropTypes.string,
basePath: PropTypes.string,
externalDocs: ImPropTypes.map,
getComponent: PropTypes.func.isRequired,
oas3selectors: PropTypes.func,
selectedServer: PropTypes.string,
}
render() {
const {
info,
url,
host,
basePath,
getComponent,
externalDocs,
selectedServer,
url: specUrl,
} = this.props
const version = info.get("version")
const summary = info.get("summary")
const description = info.get("description")
const title = info.get("title")
const termsOfServiceUrl = safeBuildUrl(
info.get("termsOfService"),
specUrl,
{ selectedServer }
)
const contactData = info.get("contact")
const licenseData = info.get("license")
const rawExternalDocsUrl = externalDocs && externalDocs.get("url")
const externalDocsUrl = safeBuildUrl(rawExternalDocsUrl, specUrl, {
selectedServer,
})
const externalDocsDescription =
externalDocs && externalDocs.get("description")
const Markdown = getComponent("Markdown", true)
const Link = getComponent("Link")
const VersionStamp = getComponent("VersionStamp")
const InfoUrl = getComponent("InfoUrl")
const InfoBasePath = getComponent("InfoBasePath")
const License = getComponent("License")
const Contact = getComponent("Contact")
return (
<div className="info">
<hgroup className="main">
<h2 className="title">
{title}
{version && <VersionStamp version={version}></VersionStamp>}
</h2>
{host || basePath ? (
<InfoBasePath host={host} basePath={basePath} />
) : null}
{url && <InfoUrl getComponent={getComponent} url={url} />}
</hgroup>
{summary && (
<div className="info__summary">
<Markdown source={summary} />
</div>
)}
<div className="description">
<Markdown source={description} />
</div>
{termsOfServiceUrl && (
<div className="info__tos">
<Link target="_blank" href={sanitizeUrl(termsOfServiceUrl)}>
Terms of service
</Link>
</div>
)}
{contactData?.size > 0 && (
<Contact
getComponent={getComponent}
data={contactData}
selectedServer={selectedServer}
url={url}
/>
)}
{licenseData?.size > 0 && (
<License
getComponent={getComponent}
license={licenseData}
selectedServer={selectedServer}
url={url}
/>
)}
{externalDocsUrl ? (
<Link
className="info__extdocs"
target="_blank"
href={sanitizeUrl(externalDocsUrl)}
>
{externalDocsDescription || externalDocsUrl}
</Link>
) : null}
<div className="info__description description">
<Markdown source={description} />
</div>
)
}
{termsOfServiceUrl && (
<div className="info__tos">
<Link target="_blank" href={sanitizeUrl(termsOfServiceUrl)}>
Terms of service
</Link>
</div>
)}
{contact.size > 0 && <Contact />}
{license.size > 0 && <License />}
{externalDocsUrl && (
<Link
className="info__extdocs"
target="_blank"
href={sanitizeUrl(externalDocsUrl)}
>
{externalDocsDesc || externalDocsUrl}
</Link>
)}
</div>
)
}
Info.propTypes = {
getComponent: PropTypes.func.isRequired,
specSelectors: PropTypes.shape({
version: PropTypes.func.isRequired,
url: PropTypes.func.isRequired,
basePath: PropTypes.func.isRequired,
host: PropTypes.func.isRequired,
selectInfoSummaryField: PropTypes.func.isRequired,
selectInfoDescriptionField: PropTypes.func.isRequired,
selectInfoTitleField: PropTypes.func.isRequired,
selectInfoTermsOfServiceUrl: PropTypes.func.isRequired,
selectExternalDocsUrl: PropTypes.func.isRequired,
selectExternalDocsDescriptionField: PropTypes.func.isRequired,
contact: PropTypes.func.isRequired,
license: PropTypes.func.isRequired,
}).isRequired,
}
export default Info

View File

@@ -21,6 +21,14 @@ import {
makeSelectContactUrl,
makeIsOAS31,
makeSelectLicenseUrl,
selectInfoTitleField,
selectInfoSummaryField,
selectInfoDescriptionField,
selectInfoTermsOfServiceField,
makeSelectInfoTermsOfServiceUrl as makeSelectTosUrl,
selectExternalDocsDescriptionField,
selectExternalDocsUrlField,
makeSelectExternalDocsUrl,
} from "./spec-extensions/selectors"
import {
isOAS3 as isOAS3Wrapper,
@@ -37,6 +45,8 @@ const OAS31Plugin = () => {
specSelectors.isOAS31 = makeIsOAS31(system)
specSelectors.selectLicenseUrl = makeSelectLicenseUrl(system)
specSelectors.selectContactUrl = makeSelectContactUrl(system)
specSelectors.selectInfoTermsOfServiceUrl = makeSelectTosUrl(system)
specSelectors.selectExternalDocsUrl = makeSelectExternalDocsUrl(system)
oas31Selectors.selectLicenseUrl = makeOAS31SelectLicenseUrl(system)
},
@@ -47,7 +57,7 @@ const OAS31Plugin = () => {
OAS31Contact: Contact,
},
wrapComponents: {
info: InfoWrapper,
InfoContainer: InfoWrapper,
License: LicenseWrapper,
Contact: ContactWrapper,
},
@@ -58,10 +68,20 @@ const OAS31Plugin = () => {
selectLicenseNameField,
selectLicenseUrlField,
selectLicenseIdentifierField,
contact,
selectContactNameField,
selectContactEmailField,
selectContactUrlField,
selectInfoTitleField,
selectInfoSummaryField,
selectInfoDescriptionField,
selectInfoTermsOfServiceField,
selectExternalDocsDescriptionField,
selectExternalDocsUrlField,
webhooks,
},
wrapSelectors: {

View File

@@ -20,10 +20,6 @@ export const license = () => (system) => {
return system.specSelectors.info().get("license", map)
}
export const contact = () => (system) => {
return system.specSelectors.info().get("contact", map)
}
export const selectLicenseNameField = () => (system) => {
return system.specSelectors.license().get("name", "License")
}
@@ -50,6 +46,10 @@ export const selectLicenseIdentifierField = onlyOAS31(() => (system) => {
return system.specSelectors.license().get("identifier")
})
export const contact = () => (system) => {
return system.specSelectors.info().get("contact", map)
}
export const selectContactNameField = () => (system) => {
return system.specSelectors.contact().get("name", "the developer")
}
@@ -75,3 +75,55 @@ export const makeSelectContactUrl = (system) =>
return undefined
}
)
export const selectInfoTitleField = () => (system) => {
return system.specSelectors.info().get("title")
}
export const selectInfoSummaryField = onlyOAS31(() => (system) => {
return system.specSelectors.info().get("summary")
})
export const selectInfoDescriptionField = () => (system) => {
return system.specSelectors.info().get("description")
}
export const selectInfoTermsOfServiceField = () => (system) => {
return system.specSelectors.info().get("termsOfService")
}
export const makeSelectInfoTermsOfServiceUrl = (system) =>
createSelector(
() => system.specSelectors.url(),
() => system.oas3Selectors.selectedServer(),
() => system.specSelectors.selectInfoTermsOfServiceField(),
(specUrl, selectedServer, termsOfService) => {
if (termsOfService) {
return safeBuildUrl(termsOfService, specUrl, { selectedServer })
}
return undefined
}
)
export const selectExternalDocsDescriptionField = () => (system) => {
return system.specSelectors.externalDocs().get("description")
}
export const selectExternalDocsUrlField = () => (system) => {
return system.specSelectors.externalDocs().get("url")
}
export const makeSelectExternalDocsUrl = (system) =>
createSelector(
() => system.specSelectors.url(),
() => system.oas3Selectors.selectedServer(),
() => system.specSelectors.selectExternalDocsUrlField(),
(specUrl, selectedServer, url) => {
if (url) {
return safeBuildUrl(url, specUrl, { selectedServer })
}
return undefined
}
)

View File

@@ -5,9 +5,9 @@ import React from "react"
const InfoWrapper = (Original, system) => (props) => {
if (system.specSelectors.isOAS31()) {
const OAS31Info = system.getComponent("OAS31Info")
const OAS31Info = system.getComponent("OAS31Info", true)
return <OAS31Info {...props} />
return <OAS31Info />
}
return <Original {...props} />