Merge branch 'master' of https://github.com/medusajs/medusa into docs/shipping-overview

This commit is contained in:
Shahed Nasser committed 2022-04-12 22:02:26 +03:00
commit e2568cb3c9
30 files changed
+5972 -3298

No files matched your search

+8
View File
@@ -1,3 +1,11 @@
# Website
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
## Note Before Development
If you have installed the dependencies in the root of this repository (i.e., if you have a `node_modules` directory at the root of this repository), this will cause an error when running this documentation website. This is because the content resides in `docs/content` and when that content is being imported from there, a mix up can happen between the dependencies which will cause an `invalid hook call` error.
For that reason, we added a `clean-node-modules` script that deletes the `node_modules` directory, and we call that script before the `start` and `build` scripts are ran.
So, everytime you run these 2 scripts, the `node_modules` directory at the root will be deleted.
+14 -9
View File
@@ -6,7 +6,7 @@ const algoliaApiKey = process.env.ALGOLIA_API_KEY || "temp"
/** @type {import('@docusaurus/types').DocusaurusConfig} */
module.exports = {
title: "Medusa Commerce",
title: "Medusa",
tagline: "Explore and learn how to use Medusa",
url: "https://docs.medusajs.com",
baseUrl: "/",
@@ -25,18 +25,22 @@ module.exports = {
],
],
themeConfig: {
disableSwitch: true,
colorMode: {
defaultMode: 'light',
disableSwitch: true,
},
algolia: {
apiKey: algoliaApiKey,
indexName: "medusa-commerce",
placeholder: "Search docs...",
appId: algoliaAppId,
contextualSearch: false,
},
prism: {
defaultLanguage: "js",
plugins: ["line-numbers", "show-language"],
theme: require("@kiwicopple/prism-react-renderer/themes/vsDark"),
darkTheme: require("@kiwicopple/prism-react-renderer/themes/vsDark"),
theme: require("prism-react-renderer/themes/vsDark"),
darkTheme: require("prism-react-renderer/themes/vsDark"),
},
navbar: {
hideOnScroll: true,
@@ -44,6 +48,7 @@ module.exports = {
alt: "Medusa Commerce",
src: "img/logo.svg",
srcDark: "img/logo.svg",
width: 100
},
items: [
{
@@ -98,12 +103,12 @@ module.exports = {
title: "More",
items: [
{
label: "Contact",
href: "https://medusa-commere.com",
label: "Medusa Home",
href: "https://medusajs.com",
},
{
label: "Privacy & Terms",
href: "https://medusa-commere.com",
label: "Contact",
href: "https://ky5eo2x1u81.typeform.com/get-in-touch",
},
{
label: "GitHub",
@@ -112,7 +117,7 @@ module.exports = {
],
},
],
copyright: `© ${new Date().getFullYear()} Medusa Commerce`,
copyright: `© ${new Date().getFullYear()} Medusa`,
},
},
presets: [
+8 -8
View File
@@ -4,7 +4,10 @@
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"clean-node-modules": "rm -rf ../../node_modules",
"prestart": "yarn clean-node-modules",
"start": "docusaurus clear && docusaurus start",
"prebuild": "yarn clean-node-modules",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
@@ -14,17 +17,14 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.3",
"@docusaurus/preset-classic": "2.0.0-beta.3",
"@docusaurus/theme-search-algolia": "^2.0.0-beta.3",
"@kiwicopple/prism-react-renderer": "github:kiwicopple/prism-react-renderer",
"@mdx-js/react": "^1.6.21",
"@svgr/webpack": "^5.5.0",
"@docusaurus/core": "2.0.0-beta.17",
"@docusaurus/preset-classic": "2.0.0-beta.17",
"@svgr/webpack": "6.2.1",
"clsx": "^1.1.1",
"docusaurus2-dotenv": "^1.4.0",
"file-loader": "^6.2.0",
"lodash": "^4.17.21",
"prism-react-renderer": "^1.2.1",
"prism-react-renderer": "^1.3.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"url-loader": "^4.1.1"
@@ -44,4 +44,4 @@
"devDependencies": {
"prettier": "^2.3.2"
}
}
}
+123 -60
View File
@@ -63,6 +63,10 @@ module.exports = {
},
],
},
{
type: "doc",
id: "admin/quickstart",
},
{
type: "doc",
id: "how-to/create-medusa-app",
@@ -130,7 +134,7 @@ module.exports = {
{
type: "category",
label: 'Services',
collapsed: true,
collapsed: false,
items: [
{
type: "doc",
@@ -139,6 +143,18 @@ module.exports = {
},
]
},
{
type: "category",
label: 'Subscribers',
collapsed: false,
items: [
{
type: "doc",
id: "advanced/backend/subscribers/create-subscriber",
label: "Create a Subscriber"
},
]
},
{
type: "category",
label: 'Shipping',
@@ -187,82 +203,124 @@ module.exports = {
items: [
{
type: "category",
label: "Gatsby + Contentful + Medusa",
label: "Analytics",
items: [
{
type: "doc",
id: "how-to/headless-ecommerce-store-with-gatsby-contentful-medusa",
},
{
type: "doc",
id: "how-to/making-your-store-more-powerful-with-contentful",
id: "add-plugins/segment",
label: "Segment",
},
],
},
{
type: "doc",
id: "add-plugins/contentful",
label: "CMS: Contentful",
type: "category",
label: "Bot",
items: [
{
type: "doc",
id: "add-plugins/slack",
label: "Slack",
},
],
},
{
type: "doc",
id: "add-plugins/strapi",
label: "CMS: Strapi",
type: "category",
label: "CMS",
items: [
{
type: "doc",
id: "add-plugins/contentful",
label: "Contentful",
},
{
type: "doc",
id: "add-plugins/strapi",
label: "Strapi",
},
{
type: "category",
label: "Gatsby + Contentful + Medusa",
items: [
{
type: "doc",
id: "how-to/headless-ecommerce-store-with-gatsby-contentful-medusa",
},
{
type: "doc",
id: "how-to/making-your-store-more-powerful-with-contentful",
},
],
},
],
},
{
type: "doc",
id: "add-plugins/segment",
label: "Analytics: Segment",
type: "category",
label: "Notifications",
items: [
{
type: "doc",
id: "add-plugins/sendgrid",
label: "SendGrid",
},
],
},
{
type: "doc",
id: "add-plugins/meilisearch",
label: "Search: MeiliSearch",
type: "category",
label: "Payment",
items: [
{
type: "doc",
id: "add-plugins/klarna",
label: "Klarna",
},
{
type: "doc",
id: "add-plugins/paypal",
label: "PayPal",
},
{
type: "doc",
id: "add-plugins/stripe",
label: "Stripe",
},
],
},
{
type: "doc",
id: "add-plugins/algolia",
label: "Search: Algolia",
type: "category",
label: "Search",
items: [
{
type: "doc",
id: "add-plugins/algolia",
label: "Algolia",
},
{
type: "doc",
id: "add-plugins/meilisearch",
label: "MeiliSearch",
},
],
},
{
type: "doc",
id: "add-plugins/spaces",
label: "File: Spaces",
},
{
type: "doc",
id: "add-plugins/s3",
label: "File: S3",
},
{
type: "doc",
id: "add-plugins/minio",
label: "File: MinIO",
},
{
type: "doc",
id: "add-plugins/stripe",
label: "Payment: Stripe",
},
{
type: "doc",
id: "add-plugins/klarna",
label: "Payment: Klarna",
},
{
type: "doc",
id: "add-plugins/paypal",
label: "Payment: PayPal",
},
{
type: "doc",
id: "add-plugins/sendgrid",
label: "Notification: SendGrid",
},
{
type: "doc",
id: "add-plugins/slack",
label: "Bot: Slack",
type: "category",
label: "Storage",
items: [
{
type: "doc",
id: "add-plugins/minio",
label: "MinIO",
},
{
type: "doc",
id: "add-plugins/s3",
label: "S3",
},
{
type: "doc",
id: "add-plugins/spaces",
label: "Spaces",
},
],
},
],
},
@@ -295,6 +353,11 @@ module.exports = {
id: "troubleshooting/signing-in-to-admin",
label: "Signing in to Medusa Admin",
},
{
type: "doc",
id: "troubleshooting/documentation-error",
label: "Documentation Error",
},
],
},
],
+5 -4
View File
@@ -1,13 +1,14 @@
import React, { useEffect, useState } from "react"
import CloseIcon from "../close-icon"
import styles from "./banner.module.css"
import clsx from "clsx"
import useThemeContext from "@theme/hooks/useThemeContext"
import ConfLogo from "../../../static/img/logo.svg"
import clsx from "clsx"
import styles from "./banner.module.css"
import {useColorMode} from '@docusaurus/theme-common';
const Banner = (props) => {
const [isBannerVisible, setIsBannerVisible] = useState(true)
const { isDarkTheme } = useThemeContext()
const { isDarkTheme } = useColorMode()
const handleDismissBanner = () => {
setIsBannerVisible(false)
+12 -10
View File
@@ -62,12 +62,19 @@ p {
/* DocSearch */
html[data-theme="light"] .DocSearch-Button {
/* html[data-theme="light"] .DocSearch-Button {
--docsearch-searchbox-background: #fff;
}
html[data-theme="dark"] .DocSearch-Button {
--docsearch-searchbox-background: #1f1f1f;
} */
.DocSearch-Button {
width: 100%;
max-width: 175px;
border-radius: 8px !important;
--docsearch-container-background: #f5f6f7;
}
span.DocSearch-Button-Key {
@@ -90,11 +97,6 @@ html[data-theme="dark"] .docusaurus-highlight-code-line {
font-size: 14px;
}
/* Medusa logo */
.navbar__brand {
width: 100px;
}
.navbar-github-link:before {
content: "";
width: 24px;
@@ -203,10 +205,6 @@ footer .footer__items svg {
display: none;
}
footer .footer__item a:hover {
color: white;
}
@media screen and (min-width: 966px) {
footer .footer__col {
display: flex;
@@ -255,3 +253,7 @@ footer {
.prism-code div:active {
outline: none !important;
}
details summary {
cursor: pointer;
}
+5 -244
View File
@@ -1,249 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { DocSearchButton, useDocSearchKeyboardEvents } from "@docsearch/react"
import Head from "@docusaurus/Head"
import Link from "@docusaurus/Link"
import { useHistory } from "@docusaurus/router"
import { translate } from "@docusaurus/Translate"
import { useBaseUrlUtils } from "@docusaurus/useBaseUrl"
import useDocusaurusContext from "@docusaurus/useDocusaurusContext"
import useAlgoliaContextualFacetFilters from "@theme/hooks/useAlgoliaContextualFacetFilters"
import useSearchQuery from "@theme/hooks/useSearchQuery"
import React, { useCallback, useMemo, useRef, useState } from "react"
import { createPortal } from "react-dom"
import styles from "./styles.module.css"
let DocSearchModal = null
const convertToKebabCase = (string) => {
return string
.replace(/\s+/g, "-")
.replace("'", "")
.replace(".", "")
.replace('"', "")
.toLowerCase()
}
const replaceUrl = (item) => {
let { url, hierarchy } = item
if (url.includes("api/store") || url.includes("/api/admin")) {
url = url.replace("#", "")
if (hierarchy.lvl2) {
const index = url.lastIndexOf("/")
url =
url.substring(0, index) +
`/${convertToKebabCase(hierarchy.lvl1)}` +
url.substring(index)
}
}
return url
}
function Hit({ hit, children }) {
if (hit.url.includes("/api/store") || hit.url.includes("/api/admin")) {
const url = replaceUrl(hit)
return <a href={url}>{children}</a>
}
return <Link to={hit.url}>{children}</Link>
}
function ResultsFooter({ state, onClose }) {
const { generateSearchPageLink } = useSearchQuery()
return (
<Link to={generateSearchPageLink(state.query)} onClick={onClose}>
See all {state.context.nbHits} results
</Link>
)
}
function DocSearch({ contextualSearch, ...props }) {
const { siteMetadata } = useDocusaurusContext()
const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters()
const configFacetFilters = props.searchParameters?.facetFilters ?? []
const facetFilters = contextualSearch
? // Merge contextual search filters with config filters
[...contextualSearchFacetFilters, ...configFacetFilters]
: // ... or use config facetFilters
configFacetFilters
// we let user override default searchParameters if he wants to
const searchParameters = {
...props.searchParameters,
facetFilters,
}
const { withBaseUrl } = useBaseUrlUtils()
const history = useHistory()
const searchContainer = useRef(null)
const searchButtonRef = useRef(null)
const [isOpen, setIsOpen] = useState(false)
const [initialQuery, setInitialQuery] = useState(null)
const importDocSearchModalIfNeeded = useCallback(() => {
if (DocSearchModal) {
return Promise.resolve()
}
return Promise.all([
import("@docsearch/react/modal"),
import("@docsearch/react/style"),
import("./styles.css"),
]).then(([{ DocSearchModal: Modal }]) => {
DocSearchModal = Modal
})
}, [])
const onOpen = useCallback(() => {
importDocSearchModalIfNeeded().then(() => {
searchContainer.current = document.createElement("div")
document.body.insertBefore(
searchContainer.current,
document.body.firstChild
)
setIsOpen(true)
})
}, [importDocSearchModalIfNeeded, setIsOpen])
const onClose = useCallback(() => {
setIsOpen(false)
searchContainer.current.remove()
}, [setIsOpen])
const onInput = useCallback(
(event) => {
importDocSearchModalIfNeeded().then(() => {
setIsOpen(true)
setInitialQuery(event.key)
})
},
[importDocSearchModalIfNeeded, setIsOpen, setInitialQuery]
)
const navigator = useRef({
navigate({ item }) {
const url = replaceUrl(item)
// Need to type out the entire URL to prevent it from attempting to open the page
// as part of the docusaurus project. Which will fail.
window.location = `https://docs.medusajs.com${url}`
},
navigateNewTab({ item }) {
const url = replaceUrl(item)
const windowReference = window.open(url, "_blank", "noopener")
if (windowReference) {
windowReference.focus()
}
},
navigateNewWindow({ item }) {
const url = replaceUrl(item)
window.open(url, "_blank", "noopener")
},
}).current
const transformItems = useRef((items) => {
return items.map((item) => {
// We transform the absolute URL into a relative URL.
// Alternatively, we can use `new URL(item.url)` but it's not
// supported in IE.
const a = document.createElement("a")
a.href = item.url
return {
...item,
url: withBaseUrl(`${a.pathname}${a.hash}`),
}
})
}).current
const resultsFooterComponent = useMemo(
() => (footerProps) => <ResultsFooter {...footerProps} onClose={onClose} />,
[onClose]
)
const transformSearchClient = useCallback(
(searchClient) => {
searchClient.addAlgoliaAgent("docusaurus", siteMetadata.docusaurusVersion)
return searchClient
},
[siteMetadata.docusaurusVersion]
)
useDocSearchKeyboardEvents({
isOpen,
onOpen,
onClose,
onInput,
searchButtonRef,
})
const translatedSearchLabel = translate({
id: "theme.SearchBar.label",
message: "Search",
description: "The ARIA label and placeholder for search button",
})
import React from 'react';
import SearchBar from '@theme-original/SearchBar';
export default function SearchBarWrapper(props) {
return (
<>
<Head>
{/* This hints the browser that the website will load data from Algolia,
and allows it to preconnect to the DocSearch cluster. It makes the first
query faster, especially on mobile. */}
<link
rel="preconnect"
href={`https://${props.appId}-dsn.algolia.net`}
crossOrigin="anonymous"
/>
</Head>
<div className={styles.searchBox}>
<DocSearchButton
onTouchStart={importDocSearchModalIfNeeded}
onFocus={importDocSearchModalIfNeeded}
onMouseOver={importDocSearchModalIfNeeded}
onClick={onOpen}
ref={searchButtonRef}
translations={{
buttonText: translatedSearchLabel,
buttonAriaLabel: translatedSearchLabel,
}}
/>
</div>
{isOpen &&
createPortal(
<DocSearchModal
onClose={onClose}
initialScrollY={window.scrollY}
initialQuery={initialQuery}
navigator={navigator}
transformItems={transformItems}
hitComponent={Hit}
resultsFooterComponent={resultsFooterComponent}
transformSearchClient={transformSearchClient}
{...props}
searchParameters={searchParameters}
/>,
searchContainer.current
)}
<SearchBar {...props} />
</>
)
);
}
function SearchBar() {
const { siteConfig } = useDocusaurusContext()
return <DocSearch {...siteConfig.themeConfig.algolia} />
}
export default SearchBar
+1092 -2783
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -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])
+22 -14
View File
@@ -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}
/>
)
+24 -4
View File
@@ -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 })
}
}
+11 -5
View File
@@ -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}
>
+9 -6
View File
@@ -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>
)
+43 -24
View File
@@ -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)
}
+14 -5
View File
@@ -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>
)
}