Feat/api reference curl examples (#720)
* curl reference initial * add tooltips to curl command * refactor copy component * move copy to copy component * formatting * always include required fields * add example values * format svg * fix property extraction * explainer comment
This commit is contained in:
@@ -38,10 +38,12 @@
|
|||||||
"preact-render-to-string": "^5.1.19",
|
"preact-render-to-string": "^5.1.19",
|
||||||
"prismjs": "^1.24.1",
|
"prismjs": "^1.24.1",
|
||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
|
"copy-to-clipboard": "^3.3.1",
|
||||||
"react-collapsible": "^2.8.1",
|
"react-collapsible": "^2.8.1",
|
||||||
"react-dom": "^16.12.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-highlight.js": "^1.0.7",
|
"react-highlight.js": "^1.0.7",
|
||||||
|
"react-tooltip": "^4.2.10",
|
||||||
"react-intersection-observer": "^8.29.0",
|
"react-intersection-observer": "^8.29.0",
|
||||||
"react-markdown": "^5.0.3",
|
"react-markdown": "^5.0.3",
|
||||||
"react-virtualized": "^9.22.3",
|
"react-virtualized": "^9.22.3",
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<svg height="10" width="10" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
|
<title>Clipboard</title>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M435.2,51.2H384v102.4H128V51.2H76.8c-15.36,0-25.6,10.24-25.6,25.6v409.6c0,15.36,10.24,25.6,25.6,25.6h358.4
|
||||||
|
c15.36,0,25.6-10.24,25.6-25.6V76.8C460.8,61.44,450.56,51.2,435.2,51.2z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M307.2,0H204.8c-15.36,0-25.6,10.24-25.6,25.6v76.8h153.6V25.6C332.8,10.24,322.56,0,307.2,0z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 695 B |
@@ -0,0 +1,76 @@
|
|||||||
|
import React, { useState } from "react"
|
||||||
|
import { Flex, Box, Text } from "theme-ui"
|
||||||
|
import Clipboard from '../icons/clipboard'
|
||||||
|
import ReactTooltip from "react-tooltip"
|
||||||
|
import styled from "@emotion/styled"
|
||||||
|
import copy from 'copy-to-clipboard'
|
||||||
|
|
||||||
|
const StyledTooltip = ({id, text}) => {
|
||||||
|
const StyledTooltip = styled(ReactTooltip)`
|
||||||
|
box-shadow: 0px 5px 15px 0px rgba(0, 0, 0, 0.08),
|
||||||
|
0px 0px 0px 1px rgba(136, 152, 170, 0.1),
|
||||||
|
0px 4px 4px 0px rgba(136, 152, 170, 0.1) !important;
|
||||||
|
padding: 8px 12px;
|
||||||
|
&:after {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
&.show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
return(
|
||||||
|
<StyledTooltip
|
||||||
|
place="top"
|
||||||
|
backgroundColor='#FFF'
|
||||||
|
textColor='black'
|
||||||
|
effect="solid"
|
||||||
|
id={id}
|
||||||
|
sx={{ boxShadow: `0px 5px 15px 0px rgba(0, 0, 0, 0.08),
|
||||||
|
0px 0px 0px 1px rgba(136, 152, 170, 0.1),
|
||||||
|
0px 4px 4px 0px rgba(136, 152, 170, 0.1) !important`,
|
||||||
|
padding: `8px 12px`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text>{text}</Text>
|
||||||
|
</StyledTooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const CopyToClipboard = ({text, copyText, tooltipText}) => {
|
||||||
|
const [copied, setCopied] = useState(false)
|
||||||
|
const id = (Math.random()*1000000).toString()
|
||||||
|
const forceTooltipRemount = copied ? "content-1" : "content-2"
|
||||||
|
|
||||||
|
const onCopyClicked = () => {
|
||||||
|
copy(copyText || tooltipText, {format: 'text/plain'})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
mr={1}
|
||||||
|
onMouseLeave={() => {setCopied(false)}}
|
||||||
|
onClick={() => {
|
||||||
|
setCopied(true)
|
||||||
|
onCopyClicked()
|
||||||
|
}}
|
||||||
|
data-for={id}
|
||||||
|
data-tip={forceTooltipRemount}
|
||||||
|
key={forceTooltipRemount}
|
||||||
|
sx={{cursor: 'pointer'}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
text && (
|
||||||
|
<Text variant="small" mr={2} sx={{ fontWeight: "300" }}>
|
||||||
|
{text.toUpperCase()}
|
||||||
|
</Text>)
|
||||||
|
}
|
||||||
|
<Clipboard/>
|
||||||
|
{copied ?
|
||||||
|
<StyledTooltip id={id} text={"Copied!"} />
|
||||||
|
:
|
||||||
|
<StyledTooltip id={id} text={tooltipText} />
|
||||||
|
}
|
||||||
|
</Box>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CopyToClipboard
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Flex, Box, Text } from "theme-ui"
|
import { Flex, Box, Text } from "theme-ui"
|
||||||
|
import CopyToClipboard from "../CopyToClipboard"
|
||||||
|
|
||||||
const CodeBox = ({ header, children }) => {
|
const CodeBox = ({ header, children, shell, content, allowCopy }) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -23,9 +24,25 @@ const CodeBox = ({ header, children }) => {
|
|||||||
borderRadius: "8px 8px 0 0",
|
borderRadius: "8px 8px 0 0",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text variant="small" sx={{ fontWeight: "400" }}>
|
<Flex
|
||||||
{header}
|
sx={{
|
||||||
</Text>
|
height: "100%",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "baseline",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text variant="small" sx={{ fontWeight: "400" }}>
|
||||||
|
{header.toUpperCase()}
|
||||||
|
</Text>
|
||||||
|
{allowCopy ? (
|
||||||
|
<CopyToClipboard
|
||||||
|
copyText={content}
|
||||||
|
tooltipText={"Copy to clipboard"}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const Content = ({ data, api }) => {
|
|||||||
>
|
>
|
||||||
<main className="DocSearch-content">
|
<main className="DocSearch-content">
|
||||||
{data.sections.map((s, i) => {
|
{data.sections.map((s, i) => {
|
||||||
return <Section key={i} data={s} />
|
return <Section key={i} data={s} api={api} />
|
||||||
})}
|
})}
|
||||||
</main>
|
</main>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -5,9 +5,15 @@ import Prism from "prismjs"
|
|||||||
import "prismjs/components/prism-json"
|
import "prismjs/components/prism-json"
|
||||||
import CodeBox from "./code-box"
|
import CodeBox from "./code-box"
|
||||||
|
|
||||||
const JsonContainer = ({ json, header }) => {
|
const JsonContainer = ({ json, header, language, allowCopy }) => {
|
||||||
const jsonRef = useRef()
|
const jsonRef = useRef()
|
||||||
|
|
||||||
|
const codeClass = language
|
||||||
|
? language === "shell"
|
||||||
|
? "language-shell"
|
||||||
|
: "language-json"
|
||||||
|
: "language-json"
|
||||||
|
|
||||||
//INVESTIGATE: @theme-ui/prism might be a better solution
|
//INVESTIGATE: @theme-ui/prism might be a better solution
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (jsonRef.current) {
|
if (jsonRef.current) {
|
||||||
@@ -19,9 +25,14 @@ const JsonContainer = ({ json, header }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box ref={jsonRef} sx={{ position: "sticky", top: "20px" }}>
|
<Box ref={jsonRef} sx={{ position: "sticky", top: "20px" }}>
|
||||||
<CodeBox header={header}>
|
<CodeBox
|
||||||
|
allowCopy={allowCopy}
|
||||||
|
content={json}
|
||||||
|
shell={language === "shell"}
|
||||||
|
header={header}
|
||||||
|
>
|
||||||
<pre>
|
<pre>
|
||||||
<code className={"language-json"}>{json}</code>
|
<code className={codeClass}>{json}</code>
|
||||||
</pre>
|
</pre>
|
||||||
</CodeBox>
|
</CodeBox>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -10,18 +10,19 @@ import ResponsiveContainer from "./responsive-container"
|
|||||||
import { formatMethodParams } from "../../utils/format-parameters"
|
import { formatMethodParams } from "../../utils/format-parameters"
|
||||||
import useInView from "../../hooks/use-in-view"
|
import useInView from "../../hooks/use-in-view"
|
||||||
import NavigationContext from "../../context/navigation-context"
|
import NavigationContext from "../../context/navigation-context"
|
||||||
|
import { formatRoute } from "../../utils/format-route"
|
||||||
|
|
||||||
const Method = ({ data, section, pathname }) => {
|
const Method = ({ data, section, pathname, api }) => {
|
||||||
const { parameters, requestBody, description, method, summary } = data
|
const { parameters, requestBody, description, method, summary } = data
|
||||||
const jsonResponse = data.responses[0].content?.[0].json
|
const jsonResponse = data.responses[0].content?.[0].json
|
||||||
const { updateHash, updateMetadata } = useContext(NavigationContext)
|
const { updateHash, updateMetadata } = useContext(NavigationContext)
|
||||||
const methodRef = useRef(null)
|
const methodRef = useRef(null)
|
||||||
|
|
||||||
const [containerRef, isInView] = useInView({
|
const [containerRef, isInView] = useInView({
|
||||||
root: null,
|
root: null,
|
||||||
rootMargin: "0px 0px -80% 0px",
|
rootMargin: "0px 0px -80% 0px",
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
})
|
})
|
||||||
|
const formattedParameters = formatMethodParams({ parameters, requestBody })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isInView) {
|
if (isInView) {
|
||||||
@@ -42,6 +43,129 @@ const Method = ({ data, section, pathname }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getExampleValues = (type, defaultExample) => {
|
||||||
|
switch (type) {
|
||||||
|
case "integer":
|
||||||
|
return 1000
|
||||||
|
case "boolean":
|
||||||
|
return false
|
||||||
|
case "object":
|
||||||
|
return {}
|
||||||
|
default:
|
||||||
|
return defaultExample
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract required properties or a non-required property from a json object
|
||||||
|
// based on the extraction method "getPropertyFromObject"
|
||||||
|
const getPropertiesFromObject = (
|
||||||
|
requiredProperties,
|
||||||
|
properties,
|
||||||
|
obj,
|
||||||
|
res,
|
||||||
|
getPropertyFromObject
|
||||||
|
) => {
|
||||||
|
for (const element of requiredProperties) {
|
||||||
|
try {
|
||||||
|
res[element.property] = getPropertyFromObject(obj, element.property)
|
||||||
|
} catch (err) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (Object.keys(res) === requiredProperties.map((p) => p.property)) {
|
||||||
|
// return res
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (const element of properties) {
|
||||||
|
try {
|
||||||
|
res[element.property] = getPropertyFromObject(obj, element.property)
|
||||||
|
break
|
||||||
|
} catch (err) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCurlJson = (properties, prefix, bodyParameters) => {
|
||||||
|
if (!properties[0]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const jsonObject = JSON.parse(jsonResponse)
|
||||||
|
const pathParts = pathname.split("/")
|
||||||
|
const requiredProperties = bodyParameters.filter((p) => p.required)
|
||||||
|
|
||||||
|
let res = {}
|
||||||
|
|
||||||
|
// if the endpoint is for a relation i.e. /orders/:id/shipment drill down into the properties of the json object
|
||||||
|
if (pathParts.length > 3) {
|
||||||
|
const propertyIndex = pathParts[2].match(/{[A-Za-z_]+}/) ? 3 : 2
|
||||||
|
|
||||||
|
try {
|
||||||
|
const obj =
|
||||||
|
jsonObject[pathParts[propertyIndex].replace("-", "_")] ||
|
||||||
|
jsonObject[Object.keys(jsonObject)[0]][
|
||||||
|
pathParts[propertyIndex].replace("-", "_")
|
||||||
|
]
|
||||||
|
|
||||||
|
res = getPropertiesFromObject(
|
||||||
|
requiredProperties,
|
||||||
|
properties,
|
||||||
|
obj,
|
||||||
|
res,
|
||||||
|
(obj, property) =>
|
||||||
|
Array.isArray(obj)
|
||||||
|
? obj.find((o) => o[property])[property]
|
||||||
|
: obj[property]
|
||||||
|
)
|
||||||
|
} catch (err) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if nothing was found drilling down look at the top level properties
|
||||||
|
if (JSON.stringify(res) === "{}") {
|
||||||
|
res = getPropertiesFromObject(
|
||||||
|
requiredProperties,
|
||||||
|
properties,
|
||||||
|
jsonObject,
|
||||||
|
res,
|
||||||
|
(jsonObject, property) =>
|
||||||
|
jsonObject[property] ||
|
||||||
|
jsonObject[Object.keys(jsonObject)[0]][property]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort, set the first property to an example
|
||||||
|
if (JSON.stringify(res) === "{}") {
|
||||||
|
res[properties[0].property] = getExampleValues(properties[0].type, `${prefix}_${properties[0].property}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add values to 'undefined' properties before returning due to JSON.stringify removing 'undefined' but not 'null'
|
||||||
|
return requiredProperties.reduce((prev, curr) => {
|
||||||
|
if(prev[curr.property] === undefined){
|
||||||
|
prev[curr.property] = getExampleValues(curr.type, `${prefix}_${curr.property}`)
|
||||||
|
}
|
||||||
|
return prev
|
||||||
|
}, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCurlCommand = (requestBody) => {
|
||||||
|
const body = JSON.stringify(
|
||||||
|
getCurlJson(
|
||||||
|
requestBody.properties,
|
||||||
|
`example_${section}`,
|
||||||
|
formattedParameters.body
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return `curl -X ${data.method.toUpperCase()} https://medusa-url.com/${api}${formatRoute(
|
||||||
|
pathname
|
||||||
|
)} \\
|
||||||
|
--header "Authorization: Bearer <ACCESS TOKEN>" ${
|
||||||
|
data.method.toUpperCase() === "POST" && requestBody.properties?.length > 0
|
||||||
|
? `\\
|
||||||
|
--header "content-type: application/json" \\
|
||||||
|
--data '${body}'`
|
||||||
|
: ""
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
py={"5vw"}
|
py={"5vw"}
|
||||||
@@ -89,18 +213,27 @@ const Method = ({ data, section, pathname }) => {
|
|||||||
<Markdown>{description}</Markdown>
|
<Markdown>{description}</Markdown>
|
||||||
</Text>
|
</Text>
|
||||||
</Description>
|
</Description>
|
||||||
<Box mt={4}>
|
<Box mt={2}>
|
||||||
<Parameters
|
<Parameters params={formattedParameters} type={"Parameters"} />
|
||||||
params={formatMethodParams({ parameters, requestBody })}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box className="code">
|
<Box className="code">
|
||||||
<JsonContainer
|
<Box>
|
||||||
json={jsonResponse}
|
<JsonContainer
|
||||||
header={"RESPONSE"}
|
json={getCurlCommand(requestBody)}
|
||||||
method={convertToKebabCase(summary)}
|
header={"cURL Example"}
|
||||||
/>
|
language={"shell"}
|
||||||
|
allowCopy={true}
|
||||||
|
method={convertToKebabCase(summary)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<JsonContainer
|
||||||
|
json={jsonResponse}
|
||||||
|
header={"RESPONSE"}
|
||||||
|
method={convertToKebabCase(summary)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -5,62 +5,77 @@ import NestedCollapsible from "./collapsible"
|
|||||||
import Description from "./description"
|
import Description from "./description"
|
||||||
|
|
||||||
const Parameters = ({ params, type }) => {
|
const Parameters = ({ params, type }) => {
|
||||||
|
const getDescriptions = (title, items) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{items?.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Text
|
||||||
|
sx={{ borderLeft: "2px solid gray", alignItems: "center" }}
|
||||||
|
my={3}
|
||||||
|
pl={2}
|
||||||
|
py={1}
|
||||||
|
>
|
||||||
|
{title === "attr" ? "Attributes" : title}
|
||||||
|
</Text>
|
||||||
|
{items.map((prop, i) => {
|
||||||
|
const nested = prop.nestedModel || prop.items?.properties || null
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
py={2}
|
||||||
|
pl={2}
|
||||||
|
sx={{
|
||||||
|
borderTop: "hairline",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
fontSize: "0",
|
||||||
|
}}
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<Flex sx={{ alignItems: "baseline", fontSize: "0" }}>
|
||||||
|
<Text mr={2}>{prop.property || prop.name}</Text>
|
||||||
|
<Text color={"gray"}>
|
||||||
|
{prop.type || prop.schema?.type || nested?.title}
|
||||||
|
</Text>
|
||||||
|
{prop.required ? (
|
||||||
|
<Text ml={1} variant="labels.required">
|
||||||
|
required
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</Flex>
|
||||||
|
<Description>
|
||||||
|
<Text
|
||||||
|
sx={{
|
||||||
|
fontSize: "0",
|
||||||
|
lineHeight: "26px",
|
||||||
|
fontFamily: "body",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Markdown>{prop.description}</Markdown>
|
||||||
|
</Text>
|
||||||
|
</Description>
|
||||||
|
{nested?.properties && (
|
||||||
|
<NestedCollapsible
|
||||||
|
properties={nested.properties}
|
||||||
|
title={nested.title}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
sx={{
|
sx={{
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text pb="2">{type === "attr" ? "Attributes" : "Parameters"}</Text>
|
{getDescriptions(type, params.properties)}
|
||||||
{params.properties.length > 0 ? (
|
{getDescriptions("Request body", params.body)}
|
||||||
params.properties.map((prop, i) => {
|
|
||||||
const nested = prop.nestedModel || prop.items?.properties || null
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
py={2}
|
|
||||||
sx={{
|
|
||||||
borderTop: "hairline",
|
|
||||||
fontFamily: "monospace",
|
|
||||||
fontSize: "0",
|
|
||||||
}}
|
|
||||||
key={i}
|
|
||||||
>
|
|
||||||
<Flex sx={{ alignItems: "baseline", fontSize: "0" }}>
|
|
||||||
<Text mr={2}>{prop.property || prop.name}</Text>
|
|
||||||
<Text color={"gray"}>
|
|
||||||
{prop.type || prop.schema?.type || nested?.title}
|
|
||||||
</Text>
|
|
||||||
{prop.required ? (
|
|
||||||
<Text ml={1} variant="labels.required">
|
|
||||||
required
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</Flex>
|
|
||||||
<Description>
|
|
||||||
<Text
|
|
||||||
sx={{
|
|
||||||
fontSize: "0",
|
|
||||||
lineHeight: "26px",
|
|
||||||
fontFamily: "body",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Markdown>{prop.description}</Markdown>
|
|
||||||
</Text>
|
|
||||||
</Description>
|
|
||||||
{nested?.properties && (
|
|
||||||
<NestedCollapsible
|
|
||||||
properties={nested.properties}
|
|
||||||
title={nested.title}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<Text sx={{ fontSize: "0", py: "3", fontFamily: "monospace" }}>
|
|
||||||
No parameters
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import NavigationContext from "../../context/navigation-context"
|
|||||||
import ChevronDown from "../icons/chevron-down"
|
import ChevronDown from "../icons/chevron-down"
|
||||||
import useInView from "../../hooks/use-in-view"
|
import useInView from "../../hooks/use-in-view"
|
||||||
|
|
||||||
const Section = ({ data }) => {
|
const Section = ({ data, api }) => {
|
||||||
const { section } = data
|
const { section } = data
|
||||||
const [isExpanded, setIsExpanded] = useState(false)
|
const [isExpanded, setIsExpanded] = useState(false)
|
||||||
const { openSections, updateSection, updateMetadata } = useContext(
|
const { openSections, updateSection, updateMetadata } = useContext(
|
||||||
@@ -20,11 +20,11 @@ const Section = ({ data }) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const endpoints = section.paths
|
const endpoints = section.paths
|
||||||
.map(p => {
|
.map((p) => {
|
||||||
let path = p.name
|
let path = p.name
|
||||||
let ep = []
|
let ep = []
|
||||||
|
|
||||||
p.methods.forEach(m => {
|
p.methods.forEach((m) => {
|
||||||
ep.push({ method: m.method, endpoint: path })
|
ep.push({ method: m.method, endpoint: path })
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -184,6 +184,7 @@ const Section = ({ data }) => {
|
|||||||
{p.methods.map((m, i) => {
|
{p.methods.map((m, i) => {
|
||||||
return (
|
return (
|
||||||
<Method
|
<Method
|
||||||
|
api={api}
|
||||||
key={i}
|
key={i}
|
||||||
data={m}
|
data={m}
|
||||||
section={convertToKebabCase(section.section_name)}
|
section={convertToKebabCase(section.section_name)}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Image } from "@theme-ui/components"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
import Logo from "../../assets/clipboard.svg"
|
||||||
|
|
||||||
|
const Clipboard = () => {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={Logo}
|
||||||
|
sx={{
|
||||||
|
height: "100%",
|
||||||
|
fill: "#000",
|
||||||
|
cursor: 'pointer'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Clipboard
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
export const formatMethodParams = method => {
|
export const formatMethodParams = (method) => {
|
||||||
const { parameters, requestBody } = method
|
const { parameters, requestBody } = method
|
||||||
|
|
||||||
const params = []
|
const params = []
|
||||||
|
const body = []
|
||||||
if (parameters && parameters.length > 0) {
|
if (parameters && parameters.length > 0) {
|
||||||
parameters.map(p => {
|
parameters.map((p) => {
|
||||||
return params.push({
|
return params.push({
|
||||||
property: p.name,
|
property: p.name,
|
||||||
description: p.description,
|
description: p.description,
|
||||||
@@ -14,16 +15,16 @@ export const formatMethodParams = method => {
|
|||||||
}
|
}
|
||||||
if (requestBody) {
|
if (requestBody) {
|
||||||
const { required, properties } = requestBody
|
const { required, properties } = requestBody
|
||||||
properties.map(p => {
|
properties.map((p) => {
|
||||||
return params.push({
|
return body.push({
|
||||||
property: p.property,
|
property: p.property,
|
||||||
description: p.description,
|
description: p.description,
|
||||||
required: required ? required.some(req => req === p.property) : false,
|
required: required ? required.some((req) => req === p.property) : false,
|
||||||
type: p.type,
|
type: p.type,
|
||||||
nestedModel: p.nestedModel,
|
nestedModel: p.nestedModel,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return { properties: params }
|
return { properties: params, body }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user