docs: improve performance of API reference (#1247)
This commit is contained in:
@@ -1512,7 +1512,7 @@
|
||||
"/store/carts/{id}": {
|
||||
"post": {
|
||||
"operationId": "PostCartsCartPaymentMethodUpdate",
|
||||
"summary": "Update a Cart\"",
|
||||
"summary": "Update a Cart",
|
||||
"description": "Updates a Cart.",
|
||||
"parameters": [
|
||||
{
|
||||
|
||||
@@ -331,7 +331,7 @@ const createAllPages = (sections, api, siteData, createPage, template) => {
|
||||
api: api,
|
||||
title: edge.section.section_name,
|
||||
description: edge.section.schema ? edge.section.schema.description : "",
|
||||
to: { section: baseURL, method: null },
|
||||
to: { section: baseURL, method: null, sectionObj: edge.section },
|
||||
},
|
||||
})
|
||||
edge.section.paths.forEach(p => {
|
||||
@@ -345,7 +345,7 @@ const createAllPages = (sections, api, siteData, createPage, template) => {
|
||||
api: api,
|
||||
title: method.summary,
|
||||
description: method.description || "",
|
||||
to: { section: baseURL, method: methodURL },
|
||||
to: { section: baseURL, method: methodURL, sectionObj: edge.section },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from "react"
|
||||
import { Box, Flex } from "theme-ui"
|
||||
import Topbar from "../topbar"
|
||||
import Section from "./section"
|
||||
|
||||
const Content = ({ data, api }) => {
|
||||
import React from "react"
|
||||
import Section from "./section"
|
||||
import Topbar from "../topbar"
|
||||
|
||||
const Content = ({ data, currentSection, api }) => {
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
@@ -20,11 +21,7 @@ const Content = ({ data, api }) => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<main className="DocSearch-content">
|
||||
{data.sections.map((s, i) => {
|
||||
return <Section key={i} data={s} api={api} />
|
||||
})}
|
||||
</main>
|
||||
<Section data={currentSection} api={api} />
|
||||
</Box>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ import { formatMethodParams } from "../../utils/format-parameters"
|
||||
import { formatRoute } from "../../utils/format-route"
|
||||
import useInView from "../../hooks/use-in-view"
|
||||
|
||||
const Method = ({ data, section, pathname, api }) => {
|
||||
const Method = ({ data, section, sectionData, pathname, api }) => {
|
||||
const { parameters, requestBody, description, method, summary } = data
|
||||
const jsonResponse = data.responses[0].content?.[0].json
|
||||
const { updateHash, updateMetadata } = useContext(NavigationContext)
|
||||
@@ -27,7 +27,7 @@ const Method = ({ data, section, pathname, api }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (isInView) {
|
||||
updateHash(section, convertToKebabCase(summary))
|
||||
updateHash(section, convertToKebabCase(summary), sectionData)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isInView])
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import React, { useState, useRef, useEffect, useContext } from "react"
|
||||
import { Flex, Box, Heading, Text, Button } from "theme-ui"
|
||||
import Method from "./method"
|
||||
import Parameters from "./parameters"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
import EndpointContainer from "./endpoint-container"
|
||||
import Markdown from "react-markdown"
|
||||
import JsonContainer from "./json-container"
|
||||
import ResponsiveContainer from "./responsive-container"
|
||||
import Description from "./description"
|
||||
import NavigationContext from "../../context/navigation-context"
|
||||
import { Box, Button, Flex, Heading, Text } from "theme-ui"
|
||||
import React, { useContext, useEffect, useRef, useState } from "react"
|
||||
|
||||
import ChevronDown from "../icons/chevron-down"
|
||||
import Description from "./description"
|
||||
import EndpointContainer from "./endpoint-container"
|
||||
import JsonContainer from "./json-container"
|
||||
import Markdown from "react-markdown"
|
||||
import Method from "./method"
|
||||
import NavigationContext from "../../context/navigation-context"
|
||||
import Parameters from "./parameters"
|
||||
import ResponsiveContainer from "./responsive-container"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
import useInView from "../../hooks/use-in-view"
|
||||
|
||||
const Section = ({ data, api }) => {
|
||||
const { section } = data
|
||||
const section = data;
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
const { openSections, updateSection, updateMetadata } = useContext(
|
||||
const { openSections, updateSection, updateMetadata, updateHash } = useContext(
|
||||
NavigationContext
|
||||
)
|
||||
|
||||
@@ -61,6 +62,12 @@ const Section = ({ data, api }) => {
|
||||
}
|
||||
}, [section.section_name, openSections, openSections.length])
|
||||
|
||||
useEffect(() => {
|
||||
if (section.section_name) {
|
||||
updateHash(convertToKebabCase(section.section_name), section.paths && section.paths.length ? (section.paths[0].methods[0].path || '') : '', section)
|
||||
}
|
||||
}, [section.section_name])
|
||||
|
||||
const [containerRef, isInView] = useInView({
|
||||
root: null,
|
||||
rootMargin: "0px 0px -80% 0px",
|
||||
@@ -70,7 +77,7 @@ const Section = ({ data, api }) => {
|
||||
useEffect(() => {
|
||||
const handleInView = () => {
|
||||
if (isInView) {
|
||||
updateSection(convertToKebabCase(section.section_name))
|
||||
updateSection({id: convertToKebabCase(section.section_name), section})
|
||||
}
|
||||
}
|
||||
handleInView()
|
||||
@@ -188,6 +195,7 @@ const Section = ({ data, api }) => {
|
||||
key={i}
|
||||
data={m}
|
||||
section={convertToKebabCase(section.section_name)}
|
||||
sectionData={section}
|
||||
pathname={p.name}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
import { Box, Flex } from "theme-ui"
|
||||
|
||||
import React from "react"
|
||||
import { Flex, Box } from "theme-ui"
|
||||
import Sidebar from "./side-bar"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
const LayoutContainer = styled(Flex)`
|
||||
--side-bar-width: 220px;
|
||||
|
||||
@media screen and (min-width: 1680px) {
|
||||
--side-bar-width: 280px;
|
||||
}
|
||||
`
|
||||
|
||||
const ContentBox = styled(Box)`
|
||||
@media screen and (min-width: 849px) {
|
||||
width: calc(100% - var(--side-bar-width));
|
||||
}
|
||||
|
||||
@media screen and (max-width: 848px) {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
||||
const Layout = ({ data, api, children }) => {
|
||||
return (
|
||||
<Flex sx={{ p: "0", m: "0", overflow: "hidden" }}>
|
||||
<LayoutContainer sx={{ p: "0", m: "0", overflow: "hidden" }}>
|
||||
<Flex
|
||||
sx={{
|
||||
position: "absolute",
|
||||
@@ -17,9 +37,9 @@ const Layout = ({ data, api, children }) => {
|
||||
}}
|
||||
>
|
||||
<Sidebar data={data} api={api} />
|
||||
<Box>{children}</Box>
|
||||
<ContentBox>{children}</ContentBox>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</LayoutContainer>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useContext } from "react"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
|
||||
import NavigationContext from "../../context/navigation-context"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
import { navigate } from "gatsby"
|
||||
|
||||
const HitComponent = ({ hit, children }) => {
|
||||
const HitComponent = ({ hit, children, data }) => {
|
||||
const { goTo, api } = useContext(NavigationContext)
|
||||
let { url, type, hierarchy } = hit
|
||||
|
||||
@@ -20,13 +21,17 @@ const HitComponent = ({ hit, children }) => {
|
||||
*/
|
||||
const goToHierarchy = e => {
|
||||
e.preventDefault()
|
||||
//find section
|
||||
let section = data.sections.find((s) => s.section.section_name == hierarchy.lvl1);
|
||||
section = section ? section.section : {}
|
||||
if (hierarchy.lvl2) {
|
||||
goTo({
|
||||
section: convertToKebabCase(hierarchy.lvl1),
|
||||
method: convertToKebabCase(hierarchy.lvl2),
|
||||
sectionObj: section
|
||||
})
|
||||
} else {
|
||||
goTo({ section: convertToKebabCase(hierarchy.lvl1) })
|
||||
goTo({ section: convertToKebabCase(hierarchy.lvl1), sectionObj: section })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useContext } from "react"
|
||||
import { DocSearch } from "@docsearch/react"
|
||||
import "../../medusa-plugin-themes/docsearch/theme.css"
|
||||
|
||||
import React, { useContext } from "react"
|
||||
|
||||
import { DocSearch } from "@docsearch/react"
|
||||
import HitComponent from "./hit-component"
|
||||
import NavigationContext from "../../context/navigation-context"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
@@ -8,7 +10,7 @@ import { navigate } from "gatsby-link"
|
||||
|
||||
const algoliaApiKey = process.env.ALGOLIA_API_KEY || "temp"
|
||||
|
||||
const Search = () => {
|
||||
const Search = ({data}) => {
|
||||
const { goTo, api } = useContext(NavigationContext)
|
||||
|
||||
const getOtherAPI = () => {
|
||||
@@ -36,13 +38,17 @@ const Search = () => {
|
||||
*/
|
||||
const goToHierarchy = item => {
|
||||
const { hierarchy } = item
|
||||
//find section
|
||||
let section = data.sections.find((s) => s.section.section_name == hierarchy.lvl1);
|
||||
section = section ? section.section : {}
|
||||
if (hierarchy.lvl2) {
|
||||
goTo({
|
||||
section: convertToKebabCase(hierarchy.lvl1),
|
||||
method: convertToKebabCase(hierarchy.lvl2),
|
||||
sectionObj: section
|
||||
})
|
||||
} else {
|
||||
goTo({ section: convertToKebabCase(hierarchy.lvl1) })
|
||||
goTo({ section: convertToKebabCase(hierarchy.lvl1), sectionObj: section })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +73,7 @@ const Search = () => {
|
||||
<DocSearch
|
||||
apiKey={algoliaApiKey}
|
||||
indexName="medusa-commerce"
|
||||
hitComponent={HitComponent}
|
||||
hitComponent={({hit, children}) => <HitComponent data={data} hit={hit} children={children} />}
|
||||
navigator={{
|
||||
navigate({ item }) {
|
||||
if (item.url.includes(`api/${api}`)) {
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import { Box, Flex, Image } from "theme-ui"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { Flex, Image, Box } from "theme-ui"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
import Logo from "../../assets/logo.svg"
|
||||
import LogoMuted from "../../assets/logo-muted.svg"
|
||||
import SideBarItem from "./sidebar-item"
|
||||
import SideBarSelector from "./sidebar-selector"
|
||||
import { navigate } from "gatsby"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
const SideBarContainer = styled(Flex)`
|
||||
--side-bar-width: 220px;
|
||||
|
||||
@media screen and (min-width: 1680px) {
|
||||
--side-bar-width: 280px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 848px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useContext } from "react"
|
||||
import Collapsible from "react-collapsible"
|
||||
import { Flex, Box, Text } from "theme-ui"
|
||||
import styled from "@emotion/styled"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
import { Box, Flex, Text } from "theme-ui"
|
||||
import React, { useContext, useEffect, useState } from "react"
|
||||
|
||||
import ChevronDown from "../icons/chevron-down"
|
||||
import Collapsible from "react-collapsible"
|
||||
import NavigationContext from "../../context/navigation-context"
|
||||
import { convertToKebabCase } from "../../utils/convert-to-kebab-case"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
const StyledCollapsible = styled(Collapsible)`
|
||||
margin-bottom: 10px;
|
||||
@@ -26,6 +27,7 @@ const SideBarItem = ({ item }) => {
|
||||
currentSection,
|
||||
goTo,
|
||||
} = useContext(NavigationContext)
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { section } = item
|
||||
const subItems = section.paths
|
||||
.map(p => {
|
||||
@@ -47,16 +49,21 @@ const SideBarItem = ({ item }) => {
|
||||
if (element) {
|
||||
element.scrollIntoView()
|
||||
if (!openSections.includes(id)) {
|
||||
openSection(id)
|
||||
openSection({id, section})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubClick = path => {
|
||||
const id = convertToKebabCase(section.section_name)
|
||||
goTo({ section: id, method: path })
|
||||
goTo({ section: id, method: path, sectionObj: section })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setIsOpen(currentSection === convertToKebabCase(section.section_name) ||
|
||||
openSections.includes(convertToKebabCase(section.section_name)));
|
||||
}, [section.section_name, currentSection, openSections])
|
||||
|
||||
return (
|
||||
<Container id={`nav-${convertToKebabCase(section.section_name)}`}>
|
||||
<StyledCollapsible
|
||||
@@ -86,10 +93,7 @@ const SideBarItem = ({ item }) => {
|
||||
{section.section_name} <ChevronDown />
|
||||
</Flex>
|
||||
}
|
||||
open={
|
||||
currentSection === convertToKebabCase(section.section_name) ||
|
||||
openSections.includes(convertToKebabCase(section.section_name))
|
||||
}
|
||||
open={isOpen}
|
||||
onTriggerOpening={handleClick}
|
||||
transitionTime={1}
|
||||
>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Box, Flex, Link, Select } from "@theme-ui/components"
|
||||
import { navigate } from "gatsby-link"
|
||||
import React, { useContext } from "react"
|
||||
|
||||
import ChevronDown from "./icons/chevron-down"
|
||||
import GitHub from "../components/icons/github"
|
||||
import NavigationContext from "../context/navigation-context"
|
||||
import { convertToKebabCase } from "../utils/convert-to-kebab-case"
|
||||
import ChevronDown from "./icons/chevron-down"
|
||||
import Search from "./search"
|
||||
|
||||
import { convertToKebabCase } from "../utils/convert-to-kebab-case"
|
||||
import { navigate } from "gatsby-link"
|
||||
|
||||
const Topbar = ({ data, api }) => {
|
||||
const { goTo, reset, currentSection } = useContext(NavigationContext)
|
||||
@@ -15,7 +15,10 @@ const Topbar = ({ data, api }) => {
|
||||
const parts = e.target.value.split(" ")
|
||||
|
||||
if (parts[0] === api) {
|
||||
goTo({ section: parts[1] })
|
||||
//find section
|
||||
let sectionObj = data.sections.find((s) => convertToKebabCase(s.section.section_name) === parts[1]);
|
||||
sectionObj = sectionObj ? sectionObj.section : {};
|
||||
goTo({ section: parts[1], sectionObj })
|
||||
} else {
|
||||
reset()
|
||||
navigate(`/api/${api === "admin" ? "store" : "admin"}`)
|
||||
@@ -112,7 +115,7 @@ const Topbar = ({ data, api }) => {
|
||||
>
|
||||
<GitHub />
|
||||
</Link>
|
||||
<Search />
|
||||
<Search data={data} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useReducer } from "react"
|
||||
|
||||
import { checkDisplay } from "../utils/check-display"
|
||||
import scrollParent from "../utils/scroll-parent"
|
||||
import types from "./types"
|
||||
@@ -7,6 +8,11 @@ export const defaultNavigationContext = {
|
||||
api: "null",
|
||||
setApi: () => {},
|
||||
currentSection: null,
|
||||
currentSectionObj: {
|
||||
section_name: "",
|
||||
paths: [],
|
||||
schema: {}
|
||||
},
|
||||
updateSection: () => {},
|
||||
currentHash: null,
|
||||
updateHash: () => {},
|
||||
@@ -21,6 +27,7 @@ const NavigationContext = React.createContext(defaultNavigationContext)
|
||||
export default NavigationContext
|
||||
|
||||
const reducer = (state, action) => {
|
||||
let obj = []
|
||||
switch (action.type) {
|
||||
case types.SET_API: {
|
||||
return {
|
||||
@@ -29,23 +36,30 @@ const reducer = (state, action) => {
|
||||
}
|
||||
}
|
||||
case types.UPDATE_HASH:
|
||||
return {
|
||||
...state,
|
||||
currentSection: action.payload.section,
|
||||
currentHash: action.payload.method,
|
||||
}
|
||||
case types.UPDATE_SECTION:
|
||||
return {
|
||||
...state,
|
||||
currentSection: action.payload,
|
||||
currentHash: null,
|
||||
}
|
||||
case types.OPEN_SECTION:
|
||||
const obj = state.openSections
|
||||
obj.push(action.payload)
|
||||
obj.push(action.payload.section)
|
||||
return {
|
||||
...state,
|
||||
openSections: obj,
|
||||
currentSection: action.payload.section,
|
||||
currentHash: action.payload.method,
|
||||
currentSectionObj: action.payload.sectionObj
|
||||
}
|
||||
case types.UPDATE_SECTION:
|
||||
obj.push(action.payload.id)
|
||||
return {
|
||||
...state,
|
||||
openSections: obj,
|
||||
currentSection: action.payload.id,
|
||||
currentHash: null,
|
||||
currentSectionObj: action.payload.section
|
||||
}
|
||||
case types.OPEN_SECTION:
|
||||
obj.push(action.payload.id)
|
||||
return {
|
||||
...state,
|
||||
openSections: obj,
|
||||
currentSection: action.payload.id,
|
||||
currentSectionObj: action.payload.section
|
||||
}
|
||||
case types.RESET:
|
||||
return {
|
||||
@@ -53,6 +67,11 @@ const reducer = (state, action) => {
|
||||
openSections: [],
|
||||
currentSection: null,
|
||||
currentHash: null,
|
||||
currentSectionObj: {
|
||||
section_name: "",
|
||||
paths: [],
|
||||
schema: {}
|
||||
}
|
||||
}
|
||||
case types.UPDATE_METADATA:
|
||||
return {
|
||||
@@ -108,10 +127,10 @@ export const NavigationProvider = ({ children }) => {
|
||||
dispatch({ type: types.UPDATE_METADATA, payload: metadata })
|
||||
}
|
||||
|
||||
const updateHash = (section, method) => {
|
||||
const updateHash = (section, method, sectionObj) => {
|
||||
dispatch({
|
||||
type: types.UPDATE_HASH,
|
||||
payload: { method: method, section: section },
|
||||
payload: { method: method, section: section, sectionObj },
|
||||
})
|
||||
window.history.replaceState(
|
||||
null,
|
||||
@@ -121,21 +140,21 @@ export const NavigationProvider = ({ children }) => {
|
||||
scrollNav(method)
|
||||
}
|
||||
|
||||
const updateSection = section => {
|
||||
dispatch({ type: types.UPDATE_SECTION, payload: section })
|
||||
window.history.replaceState(null, "", `/api/${state.api}/${section}`)
|
||||
scrollNav(section)
|
||||
const updateSection = ({id, section}) => {
|
||||
dispatch({ type: types.UPDATE_SECTION, payload: {id, section} })
|
||||
window.history.replaceState(null, "", `/api/${state.api}/${id}`)
|
||||
scrollNav(id)
|
||||
}
|
||||
|
||||
const openSection = sectionName => {
|
||||
dispatch({ type: types.OPEN_SECTION, payload: sectionName })
|
||||
const openSection = ({id, section}) => {
|
||||
dispatch({ type: types.OPEN_SECTION, payload: {id, section} })
|
||||
}
|
||||
|
||||
const goTo = to => {
|
||||
const { section, method } = to
|
||||
const { section, method, sectionObj } = to
|
||||
|
||||
if (!state.openSections.includes(section)) {
|
||||
openSection(section)
|
||||
openSection({id: section, section: sectionObj})
|
||||
}
|
||||
scrollToElement(method || section)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React, { useContext, useEffect, useState } from "react"
|
||||
import { Helmet } from "react-helmet"
|
||||
|
||||
import Layout from "../components/layout"
|
||||
import Content from "../components/content"
|
||||
import { Helmet } from "react-helmet"
|
||||
import Layout from "../components/layout"
|
||||
import NavigationContext from "../context/navigation-context"
|
||||
import { convertToKebabCase } from "../utils/convert-to-kebab-case"
|
||||
|
||||
export default function ReferencePage({
|
||||
pageContext: { data, api, title, description, to },
|
||||
}) {
|
||||
const { setApi, goTo, metadata } = useContext(NavigationContext)
|
||||
const { setApi, goTo, metadata, currentSection, currentSectionObj } = useContext(NavigationContext)
|
||||
const [siteData, setSiteData] = useState({
|
||||
title: title,
|
||||
description: description,
|
||||
@@ -18,6 +19,14 @@ export default function ReferencePage({
|
||||
setApi(api)
|
||||
if (to) {
|
||||
goTo(to)
|
||||
} else if (data.sections && data.sections.length) {
|
||||
//go to the first section
|
||||
const firstSection = data.sections[0].section;
|
||||
goTo({
|
||||
section: convertToKebabCase(firstSection.section_name),
|
||||
method: firstSection.paths && firstSection.paths.length ? firstSection.paths[0].methods[0].method : '',
|
||||
sectionObj: firstSection
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
@@ -34,10 +43,10 @@ export default function ReferencePage({
|
||||
return (
|
||||
<Layout data={data} api={api}>
|
||||
<Helmet>
|
||||
<title>{`API | Medusa Commerce API Reference`}</title>
|
||||
<title>{`API | Medusa API Reference`}</title>
|
||||
<meta name="description" content={siteData.description} />
|
||||
</Helmet>
|
||||
<Content data={data} api={api} />
|
||||
<Content data={data} currentSection={currentSectionObj} api={api} />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user