From 3e3b8a483fdaa738772bb37c9bdd2203a4daf1a9 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Mon, 13 May 2024 09:36:47 +0300 Subject: [PATCH 1/2] chore: add action to automatically label docs (#7284) * chore: add action to automatically label docs * removes the paths param --- .github/labeler.yml | 3 +++ .github/workflows/docs-pr-label.yml | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/docs-pr-label.yml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000000..08433dd1e59a6 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,3 @@ +'type: docs': +- changed-files: + - any-glob-to-any-file: www/** \ No newline at end of file diff --git a/.github/workflows/docs-pr-label.yml b/.github/workflows/docs-pr-label.yml new file mode 100644 index 0000000000000..770f2c9bde056 --- /dev/null +++ b/.github/workflows/docs-pr-label.yml @@ -0,0 +1,13 @@ +name: "Add Docs PR Label" +on: + pull_request: + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - id: label-the-PR + uses: actions/labeler@v5 \ No newline at end of file From 728c5ee53ca9860603d72aa2160408321217a9f7 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Mon, 13 May 2024 11:32:52 +0300 Subject: [PATCH 2/2] docs: preparations for preview (#7267) * configured base paths + added development banner * fix typelist site url * added navbar and sidebar badges * configure algolia filters * remove AI assistant * remove unused imports * change navbar text and badge * lint fixes * fix build error * add to api reference rewrites * fix build error * fix build errors in user-guide * fix feedback component * add parent title to pagination * added breadcrumbs component * remove user-guide links * resolve todos * fix details about authentication * change documentation title * lint content --- www/apps/api-reference/.env.sample | 3 +- .../api-reference/components/Navbar/index.tsx | 1 + www/apps/api-reference/config/index.ts | 4 +- www/apps/api-reference/next.config.mjs | 50 ++- www/apps/api-reference/providers/search.tsx | 4 +- www/apps/api-reference/providers/sidebar.tsx | 1 - www/apps/book/.env.sample | 3 +- .../api-routes/protected-routes/page.mdx | 33 +- .../data-models/soft-deletable/page.mdx | 2 +- .../data-payload/page.mdx | 6 +- .../modules/module-relationships/page.mdx | 24 +- .../modules/options/page.mdx | 2 +- .../workflows/advanced-example/page.mdx | 6 +- www/apps/book/app/layout.tsx | 3 +- www/apps/book/components/Feedback/index.tsx | 21 +- www/apps/book/components/Navbar/index.tsx | 8 +- www/apps/book/config/index.ts | 3 +- www/apps/book/config/sidebar.tsx | 4 +- www/apps/book/next.config.mjs | 30 +- www/apps/book/providers/search.tsx | 38 +- www/apps/book/utils/base-path-url.ts | 3 + .../app/configurations/medusa-admin/page.mdx | 3 +- www/apps/resources/app/js-client/page.mdx | 8 +- www/apps/resources/app/layout.tsx | 4 +- www/apps/resources/app/medusa-react/page.mdx | 4 +- .../resources/components/Feedback/index.tsx | 21 +- .../resources/components/Navbar/index.tsx | 3 +- .../resources/components/TypeList/index.tsx | 9 - www/apps/resources/config/index.ts | 5 +- www/apps/resources/mdx-options.mjs | 4 +- www/apps/resources/next.config.mjs | 4 +- www/apps/resources/providers/search.tsx | 35 +- www/apps/ui/.env.example | 3 +- www/apps/ui/src/config/docs.tsx | 14 +- www/apps/ui/src/config/site.ts | 1 + www/apps/ui/src/lib/base-path-url.ts | 2 +- www/apps/ui/src/providers/search.tsx | 4 +- .../user-guide/components/Feedback/index.tsx | 21 +- .../user-guide/components/Navbar/index.tsx | 1 + www/apps/user-guide/config/index.ts | 5 +- www/apps/user-guide/providers/search.tsx | 4 +- .../docs-ui/src/components/Bannerv2/index.tsx | 15 + .../src/components/Breadcrumbs/index.tsx | 76 ++++ .../src/components/Navbar/Link/index.tsx | 8 +- .../src/components/Navbar/Logo/index.tsx | 3 +- .../components/Navbar/NavbarDivider/index.tsx | 11 + .../docs-ui/src/components/Navbar/index.tsx | 22 +- .../src/components/Pagination/index.tsx | 2 + .../docs-ui/src/components/Search/index.tsx | 3 + .../src/components/Sidebar/Back/index.tsx | 2 +- .../src/components/Sidebar/Item/index.tsx | 14 +- .../src/components/Sidebar/Title/index.tsx | 4 +- .../docs-ui/src/components/Sidebar/index.tsx | 138 ++++--- .../src/components/TypeList/Items/index.tsx | 5 +- .../docs-ui/src/components/TypeList/index.tsx | 3 - www/packages/docs-ui/src/components/index.ts | 2 + www/packages/docs-ui/src/constants.ts | 198 ---------- www/packages/docs-ui/src/constants.tsx | 368 ++++++++++++++++++ .../src/providers/Pagination/index.tsx | 35 +- .../docs-ui/src/providers/Sidebar/index.tsx | 11 +- .../docs-ui/src/utils/get-navbar-items.ts | 26 +- www/packages/types/src/config.ts | 1 + 62 files changed, 850 insertions(+), 501 deletions(-) create mode 100644 www/apps/book/utils/base-path-url.ts delete mode 100644 www/apps/resources/components/TypeList/index.tsx create mode 100644 www/packages/docs-ui/src/components/Bannerv2/index.tsx create mode 100644 www/packages/docs-ui/src/components/Breadcrumbs/index.tsx create mode 100644 www/packages/docs-ui/src/components/Navbar/NavbarDivider/index.tsx delete mode 100644 www/packages/docs-ui/src/constants.ts create mode 100644 www/packages/docs-ui/src/constants.tsx diff --git a/www/apps/api-reference/.env.sample b/www/apps/api-reference/.env.sample index 28fb95f69d187..8431f8b0f80a2 100644 --- a/www/apps/api-reference/.env.sample +++ b/www/apps/api-reference/.env.sample @@ -15,4 +15,5 @@ ANALYZE_BUNDLE= NEXT_PUBLIC_AI_ASSISTANT_URL= NEXT_PUBLIC_AI_WEBSITE_ID= NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY= -NEXT_PUBLIC_VERSIONING= \ No newline at end of file +NEXT_PUBLIC_VERSIONING= +NEXT_PUBLIC_SHOW_V2= \ No newline at end of file diff --git a/www/apps/api-reference/components/Navbar/index.tsx b/www/apps/api-reference/components/Navbar/index.tsx index af9c540220e4a..c910b23ac0ef8 100644 --- a/www/apps/api-reference/components/Navbar/index.tsx +++ b/www/apps/api-reference/components/Navbar/index.tsx @@ -24,6 +24,7 @@ const Navbar = () => { getNavbarItems({ basePath: config.baseUrl, activePath: pathname, + version: process.env.NEXT_PUBLIC_SHOW_V2 ? "v1" : "legacy", }), [pathname] ) diff --git a/www/apps/api-reference/config/index.ts b/www/apps/api-reference/config/index.ts index 9f82fc084ac76..f0bf29ba1009c 100644 --- a/www/apps/api-reference/config/index.ts +++ b/www/apps/api-reference/config/index.ts @@ -1,5 +1,5 @@ import { DocsConfig } from "types" -import { mobileSidebarItems } from "docs-ui" +import { mobileSidebarItemsV1, legacyMobileSidebarItems } from "docs-ui" export const config: DocsConfig = { baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000", @@ -13,6 +13,6 @@ export const config: DocsConfig = { }, ], bottom: [], - mobile: mobileSidebarItems, + mobile: process.env.NEXT_PUBLIC_SHOW_V2 ? mobileSidebarItemsV1 : legacyMobileSidebarItems, }, } diff --git a/www/apps/api-reference/next.config.mjs b/www/apps/api-reference/next.config.mjs index 2f3135a8d49c0..a91e74502e293 100644 --- a/www/apps/api-reference/next.config.mjs +++ b/www/apps/api-reference/next.config.mjs @@ -4,30 +4,44 @@ import bundleAnalyzer from "@next/bundle-analyzer" /** @type {import('next').NextConfig} */ const nextConfig = { async rewrites() { - return { - fallback: [ + const fallbacks = [ + { + source: "/ui", + destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui`, + }, + { + source: "/ui/:path*", + destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui/:path*`, + }, + { + source: "/:path*", + destination: `${process.env.NEXT_PUBLIC_DOCS_URL}/:path*`, + }, + ] + + if (process.env.NEXT_PUBLIC_SHOW_V2) { + fallbacks.push( { - source: "/ui", - destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui`, + source: "/v2/resources", + destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2/resources`, }, { - source: "/ui/:path*", - destination: `${process.env.NEXT_PUBLIC_UI_URL}/ui/:path*`, + source: "/v2/resources/:path*", + destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2/resources/:path*`, }, - // TODO uncomment for v2 - // { - // source: "/v2", - // destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/resources`, - // }, - // { - // source: "/v2/:path*", - // destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/resources/:path*`, - // }, { - source: "/:path*", - destination: `${process.env.NEXT_PUBLIC_DOCS_URL}/:path*`, + source: "/v2", + destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2`, }, - ], + { + source: "/v2/:path*", + destination: `${process.env.NEXT_PUBLIC_DOCS_V2_URL}/v2/:path*`, + } + ) + } + + return { + fallback: fallbacks, } }, webpack: (config) => { diff --git a/www/apps/api-reference/providers/search.tsx b/www/apps/api-reference/providers/search.tsx index 354d724f245d7..1c3a2c20e74c2 100644 --- a/www/apps/api-reference/providers/search.tsx +++ b/www/apps/api-reference/providers/search.tsx @@ -5,7 +5,7 @@ import { SearchProvider as UiSearchProvider, AiAssistantCommandIcon, AiAssistantProvider, - searchFilters, + searchFiltersV1, } from "docs-ui" import { config } from "../config" @@ -53,7 +53,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => { checkInternalPattern: new RegExp( `^${config.baseUrl}/api/(admin|store)` ), - filterOptions: searchFilters, + filterOptions: searchFiltersV1, }} commands={[ { diff --git a/www/apps/api-reference/providers/sidebar.tsx b/www/apps/api-reference/providers/sidebar.tsx index a3ba38032936e..8a35e2fac572c 100644 --- a/www/apps/api-reference/providers/sidebar.tsx +++ b/www/apps/api-reference/providers/sidebar.tsx @@ -1,7 +1,6 @@ "use client" import { SidebarProvider as UiSidebarProvider, - mobileSidebarItems, usePageLoading, useScrollController, } from "docs-ui" diff --git a/www/apps/book/.env.sample b/www/apps/book/.env.sample index e0717e2fb07ef..6cd0d41119993 100644 --- a/www/apps/book/.env.sample +++ b/www/apps/book/.env.sample @@ -14,4 +14,5 @@ ANALYZE_BUNDLE= NEXT_PUBLIC_AI_ASSISTANT_URL= NEXT_PUBLIC_AI_WEBSITE_ID= NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY= -CLOUDINARY_CLOUD_NAME= \ No newline at end of file +CLOUDINARY_CLOUD_NAME= +NEXT_PUBLIC_BASE_PATH= \ No newline at end of file diff --git a/www/apps/book/app/advanced-development/api-routes/protected-routes/page.mdx b/www/apps/book/app/advanced-development/api-routes/protected-routes/page.mdx index df7eb8ed80452..7ef4562a2822d 100644 --- a/www/apps/book/app/advanced-development/api-routes/protected-routes/page.mdx +++ b/www/apps/book/app/advanced-development/api-routes/protected-routes/page.mdx @@ -118,36 +118,43 @@ In the route handler, you resolve the `UserService`, and then use it to retrieve ## Protect Custom API Routes -To protect custom API Routes that don’t start with `/store/me` or `/admin`, apply one of the following middlewares exported by the `@medusajs/medusa` package on your routes: - -- `authenticate`: only authenticated admin users can access the API Route. -- `authenticateCustomer`: customer authentication isn’t required, but if a customer is logged in, it attaches their ID to the `MedusaRequest` object's `user.customer_id`. -- `requireCustomerAuthentication`: only authenticated customers can access the API Route. +To protect custom API Routes that don’t start with `/store/me` or `/admin`, use the `authenticate` middleware imported from `@medusajs/medusa`. For example: export const highlights = [ ["11", "authenticate", "Only authenticated admin users can access routes starting with `/custom/admin`"], - ["15", "requireCustomerAuthentication", "Only authenticated customers can access routes starting with `/custom/customers`"] + ["17", "authenticate", "Only authenticated customers can access routes starting with `/custom/customers`"] ] ```ts title="src/api/middlewares.ts" highlights={highlights} -import { +// TODO update import +import { authenticate, - requireCustomerAuthentication, - type MiddlewaresConfig, -} from "@medusajs/medusa" +} from "@medusajs/medusa/dist/utils/authenticate-middleware" export const config: MiddlewaresConfig = { routes: [ { matcher: "/custom/admin*", - middlewares: [authenticate()], + middlewares: [ + authenticate("admin", ["session", "bearer", "api-key"]), + ], }, { matcher: "/custom/customer*", - middlewares: [requireCustomerAuthentication()], + middlewares: [ + authenticate("store", ["session", "bearer"]), + ], }, ], } -``` \ No newline at end of file +``` + +The `authenticate` middleware function accepts three parameters: + +1. The scope of authentication. Use `admin` for authenticating admin users, and `store` for authenticating customers. +2. An array of the types of authentication methods allowed. Both `admin` and `store` scopes support `session` and `bearer`. The `admin` scope also supports the `api-key` authentication method. +3. An optional object of options having the following properties: + 1. `allowUnauthenticated`: (default: `false`) A boolean indicating whether authentication is required. For example, you may have an API route where you want to access the logged-in customer if available, but guest customers can still access it too. In that case, enable the `allowUnauthenticated` option. + 2. `allowUnregistered`: (default: `false`) A boolean indicating whether new users can be authenticated. diff --git a/www/apps/book/app/advanced-development/data-models/soft-deletable/page.mdx b/www/apps/book/app/advanced-development/data-models/soft-deletable/page.mdx index 98060604a3e1c..183b718dda722 100644 --- a/www/apps/book/app/advanced-development/data-models/soft-deletable/page.mdx +++ b/www/apps/book/app/advanced-development/data-models/soft-deletable/page.mdx @@ -77,7 +77,7 @@ const deletedRecords = await helloModuleService .listMySoftDeletables({ // ... }, { - withDeleted: true + withDeleted: true, }) ``` diff --git a/www/apps/book/app/advanced-development/events-and-subscribers/data-payload/page.mdx b/www/apps/book/app/advanced-development/events-and-subscribers/data-payload/page.mdx index bfa0ffd09d06c..e4d884506f03b 100644 --- a/www/apps/book/app/advanced-development/events-and-subscribers/data-payload/page.mdx +++ b/www/apps/book/app/advanced-development/events-and-subscribers/data-payload/page.mdx @@ -39,8 +39,6 @@ export const config: SubscriberConfig = { This logs the product ID received in the `ProductService.Events.CREATED` (`product-created`) event’s data payload to the console. -{/* TODO check first if the events list is still correct */} +## List of Events with Data Payload -{/* ## List of Events with Data Payload - -Refer to [this reference](!resources!/events-reference) for a full list of events emitted by Medusa and their data payloads. */} \ No newline at end of file +Refer to [this reference](!resources!/events-reference) for a full list of events emitted by Medusa and their data payloads. \ No newline at end of file diff --git a/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx b/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx index 06b51ffdccd3f..120a2a869fbfd 100644 --- a/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx +++ b/www/apps/book/app/advanced-development/modules/module-relationships/page.mdx @@ -79,9 +79,9 @@ The `CustomProductData` data model has a `product_id` field to reference the pro When you add a new data model, make sure to: -- Create a migration for it. -- Add it to the second parameter of the main service's factory function. -- Add it to the container and connection loaders. +- [Create a migration for it.](../../../basics/data-models/page.mdx#create-a-migration) +- [Add it to the second parameter of the main service's factory function.](../service-factory/page.mdx#abstractModuleServiceFactory-parameters) +- Add it to the [container](../container/page.mdx) and [connection](../connection-loader/page.mdx) loaders. @@ -120,8 +120,8 @@ class HelloModuleService extends ModulesSdkUtils { name: ["my_custom"], args: { - entity: MyCustom.name - } + entity: MyCustom.name, + }, }, { name: ["custom_product_data"], @@ -157,23 +157,23 @@ This creates a relationship to the `Product` data model of the Product Module us name: "serviceName", type: "`string`", optional: false, - description: "The name of the module (as added in `medusa-config.js`)." + description: "The name of your module (as added in `medusa-config.js`)." }, { name: "primaryKeys", type: "`string[]`", optional: false, - description: "The primary key field names used in the module's data models.", + description: "The primary key field names used in your module's data models.", }, { name: "alias", type: "`object[]`", - description: "The alias definitions for each data model in the module. This allows other modules to reference your module's data models in relationships.", + description: "The alias definitions for each data model in your module. This allows other modules to reference your module's data models in relationships.", children: [ { name: "name", type: "`string[]`", - description: "The alias names used later when fetching or referencing the data in the model." + description: "The alias names of a data model used later when fetching or referencing the data model." }, { name: "args", @@ -197,19 +197,19 @@ This creates a relationship to the `Product` data model of the Product Module us { name: "relationships", type: "`object[]`", - description: "The module's relationships to other modules.", + description: "Your module's relationships to other modules.", children: [ { name: "serviceName", type: "`string`", optional: false, - description: "The name of the module (as added in `medusa-config.js`) that this relationship is referencing. If you’re referencing a Medusa commerce module, use the `Modules` enum imported from `@medusajs/modules-sdk`." + description: "The name of the module (as added in `medusa-config.js`) that this relationship is referencing. When referencing a Medusa commerce module, use the `Modules` enum imported from `@medusajs/modules-sdk`." }, { name: "alias", type: "`string`", optional: false, - description: "The alias of the data model you’re referencing in the other module. You can find it in the `__joinerConfig` method of the other module." + description: "The alias of the data model you’re referencing in the other module. You can find it in the `__joinerConfig` method of the other module's service." }, { name: "primaryKey", diff --git a/www/apps/book/app/advanced-development/modules/options/page.mdx b/www/apps/book/app/advanced-development/modules/options/page.mdx index 5f141db24359b..80bc9bea5719f 100644 --- a/www/apps/book/app/advanced-development/modules/options/page.mdx +++ b/www/apps/book/app/advanced-development/modules/options/page.mdx @@ -70,7 +70,7 @@ class HelloModuleService extends ModulesSdkUtils //... this.options_ = moduleOptions || { - capitalize: false + capitalize: false, } } } diff --git a/www/apps/book/app/advanced-development/workflows/advanced-example/page.mdx b/www/apps/book/app/advanced-development/workflows/advanced-example/page.mdx index 2040cdc2bbdd1..3e00b5c6f1e7a 100644 --- a/www/apps/book/app/advanced-development/workflows/advanced-example/page.mdx +++ b/www/apps/book/app/advanced-development/workflows/advanced-example/page.mdx @@ -98,14 +98,14 @@ const updateProduct = createStep( return { ...variant, - options: variantOptions + options: variantOptions, } }), options: options.map((option) => ({ ...option, - values: option.values.map((value) => value.value) + values: option.values.map((value) => value.value), })), - type_id: type.id + type_id: type.id, } ) } diff --git a/www/apps/book/app/layout.tsx b/www/apps/book/app/layout.tsx index 9db5ef718fc7f..1dfd2ea4b2553 100644 --- a/www/apps/book/app/layout.tsx +++ b/www/apps/book/app/layout.tsx @@ -4,7 +4,7 @@ import { Inter, Roboto_Mono } from "next/font/google" import Navbar from "@/components/Navbar" import Providers from "@/providers" import "./globals.css" -import { TightLayout } from "docs-ui" +import { Bannerv2, TightLayout } from "docs-ui" import { config } from "@/config" import clsx from "clsx" import Feedback from "@/components/Feedback" @@ -43,6 +43,7 @@ export default function RootLayout({ NavbarComponent={Navbar} sidebarProps={{ expandItems: true, + banner: , }} showPagination={true} bodyClassName={clsx(inter.variable, robotoMono.variable)} diff --git a/www/apps/book/components/Feedback/index.tsx b/www/apps/book/components/Feedback/index.tsx index cdf5cfa66d8d1..2b9b6686ad6e7 100644 --- a/www/apps/book/components/Feedback/index.tsx +++ b/www/apps/book/components/Feedback/index.tsx @@ -4,23 +4,34 @@ import { Feedback as UiFeedback, FeedbackProps as UiFeedbackProps, formatReportLink, + useIsBrowser, } from "docs-ui" import { usePathname } from "next/navigation" import { config } from "../../config" +import { basePathUrl } from "../../utils/base-path-url" +import { useMemo } from "react" type FeedbackProps = Omit const Feedback = (props: FeedbackProps) => { const pathname = usePathname() + const isBrowser = useIsBrowser() + + const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname]) + const reportLink = useMemo( + () => + formatReportLink( + config.titleSuffix || "", + isBrowser ? document.title : "" + ), + [isBrowser] + ) return ( diff --git a/www/apps/book/components/Navbar/index.tsx b/www/apps/book/components/Navbar/index.tsx index 8e0d9eff4a307..f6550b9dbacbd 100644 --- a/www/apps/book/components/Navbar/index.tsx +++ b/www/apps/book/components/Navbar/index.tsx @@ -4,6 +4,7 @@ import { Navbar as UiNavbar, getNavbarItems } from "docs-ui" import { useSidebar } from "docs-ui" import { useMemo } from "react" import { config } from "../../config" +import { basePathUrl } from "../../utils/base-path-url" const Navbar = () => { const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar() @@ -12,7 +13,8 @@ const Navbar = () => { () => getNavbarItems({ basePath: config.baseUrl, - activePath: "/", + activePath: basePathUrl(""), + version: "v2", }), [] ) @@ -20,8 +22,8 @@ const Navbar = () => { return ( export const sidebarConfig: SidebarConfig = { top: normalizeSidebarItems(sidebar), bottom: [], - mobile: mobileSidebarItems, + mobile: mobileSidebarItemsV2, } diff --git a/www/apps/book/next.config.mjs b/www/apps/book/next.config.mjs index a4d802f660bff..3b1df77911f34 100644 --- a/www/apps/book/next.config.mjs +++ b/www/apps/book/next.config.mjs @@ -14,7 +14,6 @@ const withMDX = mdx({ extension: /\.mdx?$/, options: { rehypePlugins: [ - // TODO add V2 to path if necessary [ crossProjectLinksPlugin, { @@ -25,13 +24,14 @@ const withMDX = mdx({ process.env.VERCEL_ENV !== "production" ? process.env.NEXT_PUBLIC_RESOURCES_URL : undefined, - path: "resources", + path: "v2/resources", }, "user-guide": { url: process.env.VERCEL_ENV !== "production" ? process.env.NEXT_PUBLIC_USER_GUIDE_URL : undefined, + path: "v2/user-guide", }, ui: { url: @@ -90,31 +90,7 @@ const nextConfig = { pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"], transpilePackages: ["docs-ui"], - // TODO uncomment if we decide on baes path - // basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2", - async rewrites() { - return { - fallback: [ - { - source: "/resources", - destination: `${process.env.NEXT_PUBLIC_RESOURCES_URL}/resources`, - }, - { - source: "/resources/:path*", - destination: `${process.env.NEXT_PUBLIC_RESOURCES_URL}/resources/:path*`, - }, - // TODO comment out once we have the user guide published - // { - // source: "/user-guide", - // destination: `${process.env.NEXT_PUBLIC_USER_GUIDE_URL}/user-guide`, - // }, - // { - // source: "/user-guide/:path*", - // destination: `${process.env.NEXT_PUBLIC_USER_GUIDE_URL}/user-guide/:path*`, - // }, - ], - } - }, + basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2", } export default withMDX(nextConfig) diff --git a/www/apps/book/providers/search.tsx b/www/apps/book/providers/search.tsx index b8f90c0323ea1..21645c25d8fbc 100644 --- a/www/apps/book/providers/search.tsx +++ b/www/apps/book/providers/search.tsx @@ -1,11 +1,6 @@ "use client" -import { - SearchProvider as UiSearchProvider, - AiAssistantCommandIcon, - AiAssistantProvider, - searchFilters, -} from "docs-ui" +import { SearchProvider as UiSearchProvider, searchFiltersV2 } from "docs-ui" import { config } from "../config" type SearchProviderProps = { @@ -32,15 +27,15 @@ const SearchProvider = ({ children }: SearchProviderProps) => { title: "Getting started? Try one of the following terms.", items: [ "Install Medusa with create-medusa-app", - "What is a Service?", "What is an API route?", + "What is a Module?", "What is a Workflow?", ], }, { title: "Developing with Medusa", items: [ - "How to create a Service", + "How to create a Module", "How to create an API route", "How to create a data model", "How to create an admin widget", @@ -48,32 +43,11 @@ const SearchProvider = ({ children }: SearchProviderProps) => { }, ], checkInternalPattern: new RegExp( - `^${config.baseUrl}/([^(api|ui|resources)]/)*` + `^${config.baseUrl}/v2/([^(resources)])*` ), - filterOptions: searchFilters, + filterOptions: searchFiltersV2, }} - initialDefaultFilters={["docs"]} - commands={[ - { - name: "ai-assistant", - icon: , - component: ( - - ), - title: "AI Assistant", - badge: { - variant: "purple", - children: "Beta", - }, - }, - ]} + initialDefaultFilters={["book"]} > {children} diff --git a/www/apps/book/utils/base-path-url.ts b/www/apps/book/utils/base-path-url.ts new file mode 100644 index 0000000000000..b8b852fedaae0 --- /dev/null +++ b/www/apps/book/utils/base-path-url.ts @@ -0,0 +1,3 @@ +export function basePathUrl(path = "") { + return `${process.env.NEXT_PUBLIC_BASE_PATH || ""}${path}` +} diff --git a/www/apps/resources/app/configurations/medusa-admin/page.mdx b/www/apps/resources/app/configurations/medusa-admin/page.mdx index e3d15e32d2ffa..d33144949711b 100644 --- a/www/apps/resources/app/configurations/medusa-admin/page.mdx +++ b/www/apps/resources/app/configurations/medusa-admin/page.mdx @@ -1,5 +1,4 @@ -import { Table } from "docs-ui" -import TypeList from "@/components/TypeList" +import { Table, TypeList } from "docs-ui" export const metadata = { title: `Medusa Admin Configurations`, diff --git a/www/apps/resources/app/js-client/page.mdx b/www/apps/resources/app/js-client/page.mdx index ce75ca7784bbf..ab270ac9bf142 100644 --- a/www/apps/resources/app/js-client/page.mdx +++ b/www/apps/resources/app/js-client/page.mdx @@ -175,7 +175,9 @@ The client accepts the following options on initialization: - A string indicating publishable API key used for storefront requests. You can create a publishable API key either using the [Medusa Admin](!user-guide!/settings/developer/api-key-management) or the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys). + {/* TODO add link [Medusa Admin](!user-guide!/settings/developer/api-key-management) */} + + A string indicating publishable API key used for storefront requests. You can create a publishable API key either using the Medusa Admin or the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys). @@ -408,7 +410,9 @@ You can learn more about publishable API keys and how to use them in [this docum ### Create a Publishable API Key -You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the [Medusa Admin](!user-guide!/settings/developer/api-key-management). +{/* TODO add link [Medusa Admin](!user-guide!/settings/developer/api-key-management) */} + +You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the Medusa Admin. ### Use a Publishable API Key diff --git a/www/apps/resources/app/layout.tsx b/www/apps/resources/app/layout.tsx index 506293f34edea..cbc36af4ae475 100644 --- a/www/apps/resources/app/layout.tsx +++ b/www/apps/resources/app/layout.tsx @@ -4,7 +4,7 @@ import { Inter, Roboto_Mono } from "next/font/google" import Navbar from "@/components/Navbar" import Providers from "@/providers" import "./globals.css" -import { TightLayout } from "docs-ui" +import { Bannerv2, Breadcrumbs, TightLayout } from "docs-ui" import { config } from "@/config" import clsx from "clsx" import { Feedback } from "@/components/Feedback" @@ -44,9 +44,11 @@ export default function RootLayout({ NavbarComponent={Navbar} sidebarProps={{ expandItems: true, + banner: , }} bodyClassName={clsx(inter.variable, robotoMono.variable)} > + {children} diff --git a/www/apps/resources/app/medusa-react/page.mdx b/www/apps/resources/app/medusa-react/page.mdx index ae6d5a86027eb..dc6a0f8a40e9c 100644 --- a/www/apps/resources/app/medusa-react/page.mdx +++ b/www/apps/resources/app/medusa-react/page.mdx @@ -327,7 +327,9 @@ You can learn more about publishable API keys and how to use them in [this docum ### Create a Publishable API Key -You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the [Medusa Admin](!user-guide!/settings/developer/api-key-management). +{/* TODO add link [Medusa Admin](!user-guide!/settings/developer/api-key-management) */} + +You can create a publishable API key either using the [Admin API Routes](https://docs.medusajs.com/api/admin#publishable-api-keys), or using the Medusa Admin. ### Use a Publishable API Key diff --git a/www/apps/resources/components/Feedback/index.tsx b/www/apps/resources/components/Feedback/index.tsx index 6a8d2731c4255..897f6c3a4bde1 100644 --- a/www/apps/resources/components/Feedback/index.tsx +++ b/www/apps/resources/components/Feedback/index.tsx @@ -4,23 +4,34 @@ import { Feedback as UiFeedback, FeedbackProps as UiFeedbackProps, formatReportLink, + useIsBrowser, } from "docs-ui" import { usePathname } from "next/navigation" import { config } from "../../config" +import { useMemo } from "react" +import { basePathUrl } from "../../utils/base-path-url" type FeedbackProps = Omit export const Feedback = (props: FeedbackProps) => { const pathname = usePathname() + const isBrowser = useIsBrowser() + + const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname]) + const reportLink = useMemo( + () => + formatReportLink( + config.titleSuffix || "", + isBrowser ? document.title : "" + ), + [isBrowser] + ) return ( diff --git a/www/apps/resources/components/Navbar/index.tsx b/www/apps/resources/components/Navbar/index.tsx index 7dd807ed53a23..8602b9707baa5 100644 --- a/www/apps/resources/components/Navbar/index.tsx +++ b/www/apps/resources/components/Navbar/index.tsx @@ -12,7 +12,8 @@ const Navbar = () => { () => getNavbarItems({ basePath: config.baseUrl, - activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/resources", + activePath: basePathUrl(""), + version: "v2", }), [] ) diff --git a/www/apps/resources/components/TypeList/index.tsx b/www/apps/resources/components/TypeList/index.tsx deleted file mode 100644 index 6768287e536bb..0000000000000 --- a/www/apps/resources/components/TypeList/index.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { TypeList as UiTypeList } from "docs-ui" -import { ComponentProps } from "react" -import { config } from "@/config" - -const TypeList = (props: ComponentProps) => { - return -} - -export default TypeList diff --git a/www/apps/resources/config/index.ts b/www/apps/resources/config/index.ts index 908c5018e0d0c..2efdd0bf7eb81 100644 --- a/www/apps/resources/config/index.ts +++ b/www/apps/resources/config/index.ts @@ -1,13 +1,14 @@ import { DocsConfig } from "types" -import { mobileSidebarItems } from "docs-ui" +import { mobileSidebarItemsV2 } from "docs-ui" import { generatedSidebar } from "../generated/sidebar.mjs" export const config: DocsConfig = { titleSuffix: "Medusa Resources", baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000", + basePath: process.env.NEXT_PUBLIC_BASE_PATH, sidebar: { top: generatedSidebar, bottom: [], - mobile: mobileSidebarItems, + mobile: mobileSidebarItemsV2, }, } diff --git a/www/apps/resources/mdx-options.mjs b/www/apps/resources/mdx-options.mjs index cd365b0e0569a..7c721b6eaa1df 100644 --- a/www/apps/resources/mdx-options.mjs +++ b/www/apps/resources/mdx-options.mjs @@ -12,7 +12,6 @@ import remarkDirective from "remark-directive" const mdxPluginOptions = { options: { rehypePlugins: [ - // TODO add V2 to path if necessary [ crossProjectLinksPlugin, { @@ -23,13 +22,14 @@ const mdxPluginOptions = { process.env.VERCEL_ENV !== "production" ? process.env.NEXT_PUBLIC_DOCS_URL : undefined, + path: "v2", }, "user-guide": { url: process.env.VERCEL_ENV !== "production" ? process.env.NEXT_PUBLIC_USER_GUIDE_URL : undefined, - path: "user-guide", + path: "v2/user-guide", }, ui: { url: diff --git a/www/apps/resources/next.config.mjs b/www/apps/resources/next.config.mjs index 764e74a8a42ae..dfbbb431df89a 100644 --- a/www/apps/resources/next.config.mjs +++ b/www/apps/resources/next.config.mjs @@ -28,9 +28,7 @@ const nextConfig = { transpilePackages: ["docs-ui"], - // TODO uncomment if we decide on baes path - // basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2/resources", - basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/resources", + basePath: process.env.NEXT_PUBLIC_BASE_PATH || "/v2/resources", async rewrites() { return { fallback: [ diff --git a/www/apps/resources/providers/search.tsx b/www/apps/resources/providers/search.tsx index 8422bf9ddaa8b..44846d5677ae9 100644 --- a/www/apps/resources/providers/search.tsx +++ b/www/apps/resources/providers/search.tsx @@ -1,11 +1,6 @@ "use client" -import { - SearchProvider as UiSearchProvider, - AiAssistantCommandIcon, - AiAssistantProvider, - searchFilters, -} from "docs-ui" +import { SearchProvider as UiSearchProvider, searchFiltersV2 } from "docs-ui" import { config } from "../config" type SearchProviderProps = { @@ -39,32 +34,10 @@ const SearchProvider = ({ children }: SearchProviderProps) => { ], }, ], - checkInternalPattern: new RegExp(`^${config.baseUrl}/resources/.*`), - filterOptions: searchFilters, + checkInternalPattern: new RegExp(`^${config.baseUrl}/v2/resources/.*`), + filterOptions: searchFiltersV2, }} - // TODO change once we have a dedicated index - initialDefaultFilters={["docs"]} - commands={[ - { - name: "ai-assistant", - icon: , - component: ( - - ), - title: "AI Assistant", - badge: { - variant: "purple", - children: "Beta", - }, - }, - ]} + initialDefaultFilters={["resources"]} > {children} diff --git a/www/apps/ui/.env.example b/www/apps/ui/.env.example index e7cbf786fc340..520fe20af538b 100644 --- a/www/apps/ui/.env.example +++ b/www/apps/ui/.env.example @@ -8,4 +8,5 @@ NEXT_PUBLIC_ALGOLIA_APP_ID= NEXT_PUBLIC_SEGMENT_API_KEY= NEXT_PUBLIC_AI_ASSISTANT_URL= NEXT_PUBLIC_AI_WEBSITE_ID= -NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY= \ No newline at end of file +NEXT_PUBLIC_AI_API_ASSISTANT_RECAPTCHA_SITE_KEY= +NEXT_PUBLIC_SHOW_V2= \ No newline at end of file diff --git a/www/apps/ui/src/config/docs.tsx b/www/apps/ui/src/config/docs.tsx index e9dd26b5ed169..dbe092aa86926 100644 --- a/www/apps/ui/src/config/docs.tsx +++ b/www/apps/ui/src/config/docs.tsx @@ -1,10 +1,15 @@ import { ArrowUpRightOnBox } from "@medusajs/icons" -import { NavbarLinkProps, getNavbarItems, mobileSidebarItems } from "docs-ui" +import { + NavbarItem, + getNavbarItems, + legacyMobileSidebarItems, + mobileSidebarItemsV1, +} from "docs-ui" import { SidebarSectionItemsType } from "types" import { siteConfig } from "./site" type DocsConfig = { - mainNav: NavbarLinkProps[] + mainNav: NavbarItem[] sidebar: SidebarSectionItemsType } @@ -12,6 +17,7 @@ export const docsConfig: DocsConfig = { mainNav: getNavbarItems({ basePath: siteConfig.baseUrl, activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/ui", + version: process.env.NEXT_PUBLIC_SHOW_V2 ? "v1" : "legacy", }), sidebar: { top: [ @@ -279,6 +285,8 @@ export const docsConfig: DocsConfig = { ], }, ], - mobile: mobileSidebarItems, + mobile: process.env.NEXT_PUBLIC_SHOW_V2 + ? mobileSidebarItemsV1 + : legacyMobileSidebarItems, }, } diff --git a/www/apps/ui/src/config/site.ts b/www/apps/ui/src/config/site.ts index 59db3a51881fe..f81e9b97761db 100644 --- a/www/apps/ui/src/config/site.ts +++ b/www/apps/ui/src/config/site.ts @@ -11,6 +11,7 @@ const baseUrl = process.env.NEXT_PUBLIC_DOCS_URL || "http://localhost:3000" export const siteConfig: SiteConfig = { name: "Medusa UI", baseUrl, + basePath: process.env.NEXT_PUBLIC_BASE_PATH, url: `${baseUrl}/${process.env.NEXT_PUBLIC_BASE_PATH}`, description: "Primitives for building Medusa applications.", // sidebar is defined in docs.tsx diff --git a/www/apps/ui/src/lib/base-path-url.ts b/www/apps/ui/src/lib/base-path-url.ts index e10c6f9cbb9ba..b8b852fedaae0 100644 --- a/www/apps/ui/src/lib/base-path-url.ts +++ b/www/apps/ui/src/lib/base-path-url.ts @@ -1,3 +1,3 @@ export function basePathUrl(path = "") { - return `${process.env.NEXT_PUBLIC_BASE_PATH}${path}` + return `${process.env.NEXT_PUBLIC_BASE_PATH || ""}${path}` } diff --git a/www/apps/ui/src/providers/search.tsx b/www/apps/ui/src/providers/search.tsx index 7538078fda7c9..95a6754f9a4ab 100644 --- a/www/apps/ui/src/providers/search.tsx +++ b/www/apps/ui/src/providers/search.tsx @@ -4,7 +4,7 @@ import { AiAssistantCommandIcon, AiAssistantProvider, SearchProvider as UiSearchProvider, - searchFilters, + searchFiltersV1, } from "docs-ui" import { absoluteUrl } from "../lib/absolute-url" @@ -34,7 +34,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => { }, ], checkInternalPattern: new RegExp(`^${absoluteUrl()}/ui`), - filterOptions: searchFilters, + filterOptions: searchFiltersV1, }} initialDefaultFilters={["ui"]} commands={[ diff --git a/www/apps/user-guide/components/Feedback/index.tsx b/www/apps/user-guide/components/Feedback/index.tsx index cdf5cfa66d8d1..2b9b6686ad6e7 100644 --- a/www/apps/user-guide/components/Feedback/index.tsx +++ b/www/apps/user-guide/components/Feedback/index.tsx @@ -4,23 +4,34 @@ import { Feedback as UiFeedback, FeedbackProps as UiFeedbackProps, formatReportLink, + useIsBrowser, } from "docs-ui" import { usePathname } from "next/navigation" import { config } from "../../config" +import { basePathUrl } from "../../utils/base-path-url" +import { useMemo } from "react" type FeedbackProps = Omit const Feedback = (props: FeedbackProps) => { const pathname = usePathname() + const isBrowser = useIsBrowser() + + const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname]) + const reportLink = useMemo( + () => + formatReportLink( + config.titleSuffix || "", + isBrowser ? document.title : "" + ), + [isBrowser] + ) return ( diff --git a/www/apps/user-guide/components/Navbar/index.tsx b/www/apps/user-guide/components/Navbar/index.tsx index be11a590fdcb6..f7618199d73b9 100644 --- a/www/apps/user-guide/components/Navbar/index.tsx +++ b/www/apps/user-guide/components/Navbar/index.tsx @@ -14,6 +14,7 @@ const Navbar = () => { getNavbarItems({ basePath: config.baseUrl, activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/user-guide", + version: "v2", }), [] ) diff --git a/www/apps/user-guide/config/index.ts b/www/apps/user-guide/config/index.ts index 05539e1b3cb7b..db049ff2676e6 100644 --- a/www/apps/user-guide/config/index.ts +++ b/www/apps/user-guide/config/index.ts @@ -1,13 +1,14 @@ import { DocsConfig } from "types" -import { mobileSidebarItems } from "docs-ui" +import { mobileSidebarItemsV2 } from "docs-ui" import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs" export const config: DocsConfig = { titleSuffix: "Medusa Admin User Guide", baseUrl: process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000", + basePath: process.env.NEXT_PUBLIC_BASE_PATH, sidebar: { top: sidebar, bottom: [], - mobile: mobileSidebarItems, + mobile: mobileSidebarItemsV2, }, } diff --git a/www/apps/user-guide/providers/search.tsx b/www/apps/user-guide/providers/search.tsx index ff50b51af3fa6..0e78a7c064b53 100644 --- a/www/apps/user-guide/providers/search.tsx +++ b/www/apps/user-guide/providers/search.tsx @@ -4,7 +4,7 @@ import { SearchProvider as UiSearchProvider, AiAssistantCommandIcon, AiAssistantProvider, - searchFilters, + searchFiltersV1, } from "docs-ui" import { config } from "../config" @@ -42,7 +42,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => { }, ], checkInternalPattern: new RegExp(`^${config.baseUrl}/user-guide`), - filterOptions: searchFilters, + filterOptions: searchFiltersV1, }} initialDefaultFilters={["user-guide"]} commands={[ diff --git a/www/packages/docs-ui/src/components/Bannerv2/index.tsx b/www/packages/docs-ui/src/components/Bannerv2/index.tsx new file mode 100644 index 0000000000000..bb8cdb35a1ab2 --- /dev/null +++ b/www/packages/docs-ui/src/components/Bannerv2/index.tsx @@ -0,0 +1,15 @@ +import React from "react" +import { Card, Link } from "../.." + +export const Bannerv2 = () => { + return ( + + This documentation is for Medusa v2, which isn't ready for + production. +
+
+ For production-use, refer to{" "} + this documentation instead. +
+ ) +} diff --git a/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx b/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx new file mode 100644 index 0000000000000..fd6bd17d74f2f --- /dev/null +++ b/www/packages/docs-ui/src/components/Breadcrumbs/index.tsx @@ -0,0 +1,76 @@ +"use client" + +import React, { useMemo } from "react" +import { CurrentItemsState, useSidebar } from "@/providers" +import { TriangleRightMini } from "@medusajs/icons" +import Link from "next/link" +import clsx from "clsx" + +type BreadcrumbItem = Map + +export const Breadcrumbs = () => { + const { currentItems } = useSidebar() + + const getBreadcrumbsOfItem = (item: CurrentItemsState): BreadcrumbItem => { + let tempBreadcrumbItems: BreadcrumbItem = new Map() + if (item.previousSidebar) { + tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar) + } + + tempBreadcrumbItems.set( + item.parentItem?.path || item.top[0].path || "/", + item.parentItem?.childSidebarTitle || item.parentItem?.title || "" + ) + + return tempBreadcrumbItems + } + + const breadcrumbItems = useMemo(() => { + const tempBreadcrumbItems: BreadcrumbItem = new Map() + if (!currentItems) { + return tempBreadcrumbItems + } + + tempBreadcrumbItems.set("/", "Home") + + getBreadcrumbsOfItem(currentItems).forEach((value, key) => + tempBreadcrumbItems.set(key, value) + ) + + return tempBreadcrumbItems + }, [currentItems]) + + const getBreadcrumbItemElms = (): React.ReactNode[] => { + const elms: React.ReactNode[] = [] + breadcrumbItems.forEach((title, path) => { + elms.push( + + {elms.length !== 0 && ( + + )} + + {title} + + + ) + }) + + return elms + } + + return ( + <> + {breadcrumbItems.size > 0 && ( +
+ {...getBreadcrumbItemElms()} +
+ )} + + ) +} diff --git a/www/packages/docs-ui/src/components/Navbar/Link/index.tsx b/www/packages/docs-ui/src/components/Navbar/Link/index.tsx index 26fc8c6048941..44efccd873adb 100644 --- a/www/packages/docs-ui/src/components/Navbar/Link/index.tsx +++ b/www/packages/docs-ui/src/components/Navbar/Link/index.tsx @@ -2,7 +2,7 @@ import React from "react" import clsx from "clsx" -import { Link, LinkProps } from "@/components" +import { Badge, BadgeProps, Link, LinkProps } from "@/components" export type NavbarLinkProps = { href: string @@ -10,6 +10,7 @@ export type NavbarLinkProps = { className?: string activeValuePattern?: RegExp isActive?: boolean + badge?: BadgeProps } & LinkProps export const NavbarLink = ({ @@ -17,6 +18,7 @@ export const NavbarLink = ({ label, className, isActive, + badge }: NavbarLinkProps) => { return ( {label} + {badge && } ) } diff --git a/www/packages/docs-ui/src/components/Navbar/Logo/index.tsx b/www/packages/docs-ui/src/components/Navbar/Logo/index.tsx index 5dfcf106f82cc..e28ef7f7175d8 100644 --- a/www/packages/docs-ui/src/components/Navbar/Logo/index.tsx +++ b/www/packages/docs-ui/src/components/Navbar/Logo/index.tsx @@ -4,6 +4,7 @@ import React from "react" import { useColorMode } from "@/providers" import Link from "next/link" import clsx from "clsx" +import Image from "next/image" export type NavbarLogoProps = { light: string @@ -22,7 +23,7 @@ export const NavbarLogo = ({ return ( - Medusa Logo { + return ( +
+ ) +} \ No newline at end of file diff --git a/www/packages/docs-ui/src/components/Navbar/index.tsx b/www/packages/docs-ui/src/components/Navbar/index.tsx index 981474cdd2499..4ea2756fc9363 100644 --- a/www/packages/docs-ui/src/components/Navbar/index.tsx +++ b/www/packages/docs-ui/src/components/Navbar/index.tsx @@ -6,10 +6,19 @@ import { NavbarLogo, NavbarLogoProps } from "./Logo" import { NavbarMobileMenu } from "./MobileMenu" import { NavbarSearchModalOpener } from "./SearchModalOpener" import { NavbarMobileMenuButtonProps } from "./MobileMenu/Button" +import { NavbarDivider } from "./NavbarDivider" + +export type NavbarItem = { + type: "link" + props: NavbarLinkProps +} | { + type: "divider" + props?: {} +} export type NavbarProps = { logo: NavbarLogoProps - items: NavbarLinkProps[] + items: NavbarItem[] showSearchOpener?: boolean showColorModeToggle?: boolean additionalActionsAfter?: React.ReactNode @@ -45,9 +54,14 @@ export const Navbar = ({ >
- {items.map((item, index) => ( - - ))} + {items.map(({type, props}, index) => { + switch(type) { + case "divider": + return + default: + return + } + })}
{additionalActionsBefore} diff --git a/www/packages/docs-ui/src/components/Pagination/index.tsx b/www/packages/docs-ui/src/components/Pagination/index.tsx index 4936e3e272809..26d99d90c9a94 100644 --- a/www/packages/docs-ui/src/components/Pagination/index.tsx +++ b/www/packages/docs-ui/src/components/Pagination/index.tsx @@ -13,6 +13,7 @@ export const Pagination = () => { {previousPage && ( } showLinkIcon={false} href={previousPage.link} @@ -22,6 +23,7 @@ export const Pagination = () => { {nextPage && ( } showLinkIcon={false} href={nextPage.link} diff --git a/www/packages/docs-ui/src/components/Search/index.tsx b/www/packages/docs-ui/src/components/Search/index.tsx index 2b631bf86432c..f56deec91f1b5 100644 --- a/www/packages/docs-ui/src/components/Search/index.tsx +++ b/www/packages/docs-ui/src/components/Search/index.tsx @@ -85,6 +85,9 @@ export const Search = ({
{ return (
export const SidebarItem = ({ @@ -24,6 +26,8 @@ export const SidebarItem = ({ expandItems = false, className, currentLevel = 1, + sidebarHasParent = false, + isMobile = false }: SidebarItemProps) => { const [showLoading, setShowLoading] = useState(false) const { @@ -34,8 +38,8 @@ export const SidebarItem = ({ sidebarRef, } = useSidebar() const active = useMemo( - () => isItemActive(item, nested), - [isItemActive, item, nested] + () => !isMobile && isItemActive(item, nested), + [isItemActive, item, nested, isMobile] ) const collapsed = !expandItems && !isItemActive(item, true) const ref = useRef(null) @@ -131,7 +135,11 @@ export const SidebarItem = ({ return (
  • { return ( { const { items, @@ -32,6 +34,11 @@ export const Sidebar = ({ [items, currentItems] ) + const sidebarHasParent = useMemo( + () => sidebarItems.parentItem !== undefined, + [sidebarItems] + ) + return ( ) } diff --git a/www/packages/docs-ui/src/components/TypeList/Items/index.tsx b/www/packages/docs-ui/src/components/TypeList/Items/index.tsx index c2cf706911c16..aa00bc68cf66f 100644 --- a/www/packages/docs-ui/src/components/TypeList/Items/index.tsx +++ b/www/packages/docs-ui/src/components/TypeList/Items/index.tsx @@ -21,7 +21,7 @@ import { } from "@medusajs/icons" import { decodeStr, isInView } from "@/utils" import { usePathname } from "next/navigation" -import { useIsBrowser } from "../../.." +import { useIsBrowser, useSiteConfig } from "../../.." type CommonProps = ParentCommonProps & { level?: number @@ -39,10 +39,11 @@ const TypeListItem = ({ expandUrl, elementKey, sectionTitle, - siteUrl = "", }: TypeListItemProps) => { const isBrowser = useIsBrowser() const pathname = usePathname() + const { config: { baseUrl, basePath } } = useSiteConfig() + const siteUrl = `${baseUrl}${basePath}` const groupName = useMemo(() => { switch (level) { diff --git a/www/packages/docs-ui/src/components/TypeList/index.tsx b/www/packages/docs-ui/src/components/TypeList/index.tsx index 1813dc2a07341..2c2e42c07e74f 100644 --- a/www/packages/docs-ui/src/components/TypeList/index.tsx +++ b/www/packages/docs-ui/src/components/TypeList/index.tsx @@ -5,7 +5,6 @@ import { Loading } from "@/components" export type CommonProps = { expandUrl?: string sectionTitle?: string - siteUrl?: string } export type Type = { @@ -30,7 +29,6 @@ const TypeListItems = lazy(async () => import("./Items")) export const TypeList = ({ types, className, - siteUrl, sectionTitle, expandUrl, ...props @@ -48,7 +46,6 @@ export const TypeList = ({ types={types} expandUrl={expandUrl} sectionTitle={sectionTitle} - siteUrl={siteUrl} />
  • diff --git a/www/packages/docs-ui/src/components/index.ts b/www/packages/docs-ui/src/components/index.ts index a30ff98410f41..24c77b213ca72 100644 --- a/www/packages/docs-ui/src/components/index.ts +++ b/www/packages/docs-ui/src/components/index.ts @@ -1,8 +1,10 @@ export * from "./AiAssistant" export * from "./AiAssistant/CommandIcon" export * from "./Badge" +export * from "./Bannerv2" export * from "./Bordered" export * from "./BorderedIcon" +export * from "./Breadcrumbs" export * from "./Button" export * from "./Card" export * from "./CardList" diff --git a/www/packages/docs-ui/src/constants.ts b/www/packages/docs-ui/src/constants.ts deleted file mode 100644 index e222d0b850dcf..0000000000000 --- a/www/packages/docs-ui/src/constants.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { NavbarLinkProps } from "@/components" -import { OptionType } from "./hooks" -import { SidebarItemType } from "types" - -export const GITHUB_ISSUES_PREFIX = `https://github.com/medusajs/medusa/issues/new?assignees=&labels=type%3A+docs&template=docs.yml` -export const GITHUB_UI_ISSUES_PREFIX = `https://github.com/medusajs/ui/issues/new?labels=documentation` - -export const navbarItems: NavbarLinkProps[] = [ - { - label: "Docs", - target: "_blank", - rel: "noreferrer", - href: `/`, - }, - { - label: "Resources", - target: "_blank", - rel: "noreferrer", - href: `/resources`, - }, - { - label: "User Guide", - target: "_blank", - rel: "noreferrer", - href: `/user-guide`, - }, - { - label: "Store API", - target: "_blank", - rel: "noreferrer", - href: `/api/store`, - }, - { - label: "Admin API", - target: "_blank", - rel: "noreferrer", - href: `/api/admin`, - }, - { - label: "UI", - target: "_blank", - rel: "noreferrer", - href: `/ui`, - }, -] - -/** - * TODO Uncomment for V2 - * - * export const navbarItems: NavbarLinkProps[] = [ - { - label: "Docs", - target: "_blank", - rel: "noreferrer", - href: `/`, - activeValuePattern: /^\/(?!api\/|ui\/|user-guide\/|resources\/)/, - }, - { - label: "User Guide", - target: "_blank", - rel: "noreferrer", - href: `/user-guide`, - }, - { - label: "Store API", - target: "_blank", - rel: "noreferrer", - href: `/api/store`, - }, - { - label: "Admin API", - target: "_blank", - rel: "noreferrer", - href: `/api/admin`, - }, - { - label: "UI", - target: "_blank", - rel: "noreferrer", - href: `/ui`, - activeValuePattern: /^\/ui\//, - }, - { - label: "V2 Docs", - target: "_blank", - rel: "noreferrer", - href: `/v2`, - }, -] - -export const navbarItemsV2: NavbarLinkProps[] = [ - { - label: "Docs", - target: "_blank", - rel: "noreferrer", - href: `/v2`, - activeValuePattern: /^\/v2\/(?!api\/|ui\/|user-guide\/|resources\/)/, - }, - { - label: "Resources", - target: "_blank", - rel: "noreferrer", - href: `/v2/resources`, - activeValuePattern: /^\/v2\/resources\//, - }, - { - label: "User Guide", - target: "_blank", - rel: "noreferrer", - href: `/v2/user-guide`, - activeValuePattern: /^\/v2\/user-guide/, - }, - { - label: "Store API", - target: "_blank", - rel: "noreferrer", - href: `/api/store`, - }, - { - label: "Admin API", - target: "_blank", - rel: "noreferrer", - href: `/api/admin`, - }, - { - label: "UI", - target: "_blank", - rel: "noreferrer", - href: `/ui`, - activeValuePattern: /^\/ui\//, - }, -] - */ - -export const mobileSidebarItems: SidebarItemType[] = [ - { - title: "Docs", - path: `/`, - loaded: true, - isPathHref: true, - }, - { - title: "User Guide", - path: `/user-guide`, - loaded: true, - isPathHref: true, - }, - { - title: "Store API", - path: `/api/store`, - loaded: true, - isPathHref: true, - }, - { - title: "Admin API", - path: `/api/admin`, - loaded: true, - isPathHref: true, - }, - { - title: "UI", - path: `/ui`, - loaded: true, - isPathHref: true, - }, -] - -// TODO add resources once we create index -export const searchFilters: OptionType[] = [ - { - value: "admin", - label: "Admin API", - }, - { - value: "store", - label: "Store API", - }, - { - value: "docs", - label: "Docs", - }, - { - value: "user-guide", - label: "User Guide", - }, - { - value: "plugins", - label: "Plugins", - }, - { - value: "reference", - label: "References", - }, - { - value: "ui", - label: "UI", - }, -] diff --git a/www/packages/docs-ui/src/constants.tsx b/www/packages/docs-ui/src/constants.tsx new file mode 100644 index 0000000000000..e162cb1628774 --- /dev/null +++ b/www/packages/docs-ui/src/constants.tsx @@ -0,0 +1,368 @@ +import React from "react" +import { Badge, NavbarItem } from "@/components" +import { OptionType } from "./hooks" +import { SidebarItemType } from "types" + +export const GITHUB_ISSUES_PREFIX = `https://github.com/medusajs/medusa/issues/new?assignees=&labels=type%3A+docs&template=docs.yml` +export const GITHUB_UI_ISSUES_PREFIX = `https://github.com/medusajs/ui/issues/new?labels=documentation` + +export const navbarItemsV1: NavbarItem[] = [ + { + type: "link", + props: { + label: "Docs", + target: "_blank", + rel: "noreferrer", + href: `/`, + }, + }, + { + type: "link", + props: { + label: "User Guide", + target: "_blank", + rel: "noreferrer", + href: `/user-guide`, + }, + }, + { + type: "link", + props: { + label: "Store API", + target: "_blank", + rel: "noreferrer", + href: `/api/store`, + }, + }, + { + type: "link", + props: { + label: "Admin API", + target: "_blank", + rel: "noreferrer", + href: `/api/admin`, + }, + }, + { + type: "link", + props: { + label: "UI", + target: "_blank", + rel: "noreferrer", + href: `/ui`, + }, + }, + { + type: "divider", + }, + { + type: "link", + props: { + label: "Learn Medusa v2", + target: "_blank", + rel: "noreferrer", + href: `/v2`, + badge: { + variant: "blue", + children: "New", + }, + }, + }, +] + +export const navbarItemsV2: NavbarItem[] = [ + { + type: "link", + props: { + label: "Docs", + target: "_blank", + rel: "noreferrer", + href: `/v2`, + }, + }, + { + type: "link", + props: { + label: "Learning Resources", + target: "_blank", + rel: "noreferrer", + href: `/v2/resources`, + }, + }, + { + type: "divider", + }, + { + type: "link", + props: { + label: "Docs", + target: "_blank", + rel: "noreferrer", + href: `/`, + badge: { + variant: "neutral", + children: "v1", + }, + }, + }, + { + type: "link", + props: { + label: "User Guide", + target: "_blank", + rel: "noreferrer", + href: `/user-guide`, + badge: { + variant: "neutral", + children: "v1", + }, + }, + }, + { + type: "link", + props: { + label: "Store API", + target: "_blank", + rel: "noreferrer", + href: `/api/store`, + }, + }, + { + type: "link", + props: { + label: "Admin API", + target: "_blank", + rel: "noreferrer", + href: `/api/admin`, + }, + }, + { + type: "link", + props: { + label: "UI", + target: "_blank", + rel: "noreferrer", + href: `/ui`, + }, + }, +] + +export const legacyNavbarItems: NavbarItem[] = [ + { + type: "link", + props: { + label: "Docs", + target: "_blank", + rel: "noreferrer", + href: `/`, + }, + }, + { + type: "link", + props: { + label: "Resources", + target: "_blank", + rel: "noreferrer", + href: `/resources`, + }, + }, + { + type: "link", + props: { + label: "User Guide", + target: "_blank", + rel: "noreferrer", + href: `/user-guide`, + }, + }, + { + type: "link", + props: { + label: "Store API", + target: "_blank", + rel: "noreferrer", + href: `/api/store`, + }, + }, + { + type: "link", + props: { + label: "Admin API", + target: "_blank", + rel: "noreferrer", + href: `/api/admin`, + }, + }, + { + type: "link", + props: { + label: "UI", + target: "_blank", + rel: "noreferrer", + href: `/ui`, + }, + }, +] + +export const mobileSidebarItemsV1: SidebarItemType[] = [ + { + title: "Docs", + path: `/`, + loaded: true, + isPathHref: true, + }, + { + title: "User Guide", + path: `/user-guide`, + loaded: true, + isPathHref: true, + }, + { + title: "Store API", + path: `/api/store`, + loaded: true, + isPathHref: true, + }, + { + title: "Admin API", + path: `/api/admin`, + loaded: true, + isPathHref: true, + }, + { + title: "UI", + path: `/ui`, + loaded: true, + isPathHref: true, + }, + { + title: "Book", + path: `/v2`, + loaded: true, + isPathHref: true, + additionalElms: v2, + }, +] + +export const mobileSidebarItemsV2: SidebarItemType[] = [ + { + title: "Book", + path: `/v2`, + loaded: true, + isPathHref: true, + }, + { + title: "Learning Resources", + path: `/v2/resources`, + loaded: true, + isPathHref: true, + }, + { + title: "Docs", + path: `/`, + loaded: true, + isPathHref: true, + additionalElms: v1, + }, + { + title: "User Guide", + path: `/user-guide`, + loaded: true, + isPathHref: true, + additionalElms: v1, + }, + { + title: "Store API", + path: `/api/store`, + loaded: true, + isPathHref: true, + }, + { + title: "Admin API", + path: `/api/admin`, + loaded: true, + isPathHref: true, + }, + { + title: "UI", + path: `/ui`, + loaded: true, + isPathHref: true, + }, +] + +export const legacyMobileSidebarItems: SidebarItemType[] = [ + { + title: "Docs", + path: `/`, + loaded: true, + isPathHref: true, + }, + { + title: "User Guide", + path: `/user-guide`, + loaded: true, + isPathHref: true, + }, + { + title: "Store API", + path: `/api/store`, + loaded: true, + isPathHref: true, + }, + { + title: "Admin API", + path: `/api/admin`, + loaded: true, + isPathHref: true, + }, + { + title: "UI", + path: `/ui`, + loaded: true, + isPathHref: true, + }, +] + +export const searchFiltersV2: OptionType[] = [ + { + value: "book", + label: "Book", + }, + { + value: "resources", + label: "Resources", + }, + // TODO add more filters once V2 become the main docs +] + +export const searchFiltersV1: OptionType[] = [ + { + value: "admin", + label: "Admin API", + }, + { + value: "store", + label: "Store API", + }, + { + value: "docs", + label: "Docs", + }, + { + value: "user-guide", + label: "User Guide", + }, + { + value: "plugins", + label: "Plugins", + }, + { + value: "reference", + label: "References", + }, + { + value: "ui", + label: "UI", + }, +] diff --git a/www/packages/docs-ui/src/providers/Pagination/index.tsx b/www/packages/docs-ui/src/providers/Pagination/index.tsx index c271adcb00613..f2569df53d919 100644 --- a/www/packages/docs-ui/src/providers/Pagination/index.tsx +++ b/www/packages/docs-ui/src/providers/Pagination/index.tsx @@ -14,6 +14,7 @@ import { SidebarItemType } from "types" export type Page = { title: string description?: string + parentTitle?: string link: string } @@ -26,10 +27,14 @@ export const PaginationContext = createContext( null ) +type SidebarItemWithParent = SidebarItemType & { + parent?: SidebarItemType +} + type SearchItemsResult = { foundActive: boolean - prevItem?: SidebarItemType - nextItem?: SidebarItemType + prevItem?: SidebarItemWithParent + nextItem?: SidebarItemWithParent } export type PaginationProviderProps = { @@ -66,14 +71,20 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => { const getPrevItem = ( items: SidebarItemType[], index: number - ): SidebarItemType | undefined => { - let foundItem: SidebarItemType | undefined + ): SidebarItemWithParent | undefined => { + let foundItem: SidebarItemWithParent | undefined items .slice(0, index) .reverse() .some((item) => { if (item.children?.length) { - foundItem = getPrevItem(item.children, item.children.length) + const childItem = getPrevItem(item.children, item.children.length) + if (childItem) { + foundItem = { + ...childItem, + parent: item, + } + } } else if (item.path) { foundItem = item } @@ -87,13 +98,19 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => { const getNextItem = ( items: SidebarItemType[], index: number - ): SidebarItemType | undefined => { - let foundItem: SidebarItemType | undefined + ): SidebarItemWithParent | undefined => { + let foundItem: SidebarItemWithParent | undefined items.slice(index + 1).some((item) => { if (item.path) { foundItem = item } else if (item.children?.length) { - foundItem = getNextItem(item.children, -1) + const childItem = getNextItem(item.children, -1) + if (childItem) { + foundItem = { + ...childItem, + parent: item, + } + } } return foundItem !== undefined @@ -157,6 +174,7 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => { ? { title: result.prevItem.title, link: result.prevItem.path || "", + parentTitle: result.prevItem.parent?.title, } : undefined ) @@ -165,6 +183,7 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => { ? { title: result.nextItem.title, link: result.nextItem.path || "", + parentTitle: result.nextItem.parent?.title, } : undefined ) diff --git a/www/packages/docs-ui/src/providers/Sidebar/index.tsx b/www/packages/docs-ui/src/providers/Sidebar/index.tsx index c6223acac153f..6253e6169ea8b 100644 --- a/www/packages/docs-ui/src/providers/Sidebar/index.tsx +++ b/www/packages/docs-ui/src/providers/Sidebar/index.tsx @@ -59,7 +59,7 @@ export type SidebarContextType = { setDesktopSidebarOpen: React.Dispatch> staticSidebarItems?: boolean shouldHandleHashChange: boolean - sidebarRef: React.RefObject + sidebarRef: React.RefObject goBack: () => void } & SidebarStyleOptions @@ -198,7 +198,7 @@ export const SidebarProvider = ({ const [activePath, setActivePath] = useState("") const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false) const [desktopSidebarOpen, setDesktopSidebarOpen] = useState(true) - const sidebarRef = useRef(null) + const sidebarRef = useRef(null) const pathname = usePathname() const router = useRouter() @@ -311,7 +311,7 @@ export const SidebarProvider = ({ } setActivePath(backItem.path!) - setCurrentItems(currentItems.previousSidebar) + setCurrentItems(previousSidebar) router.replace(backItem.path!) } @@ -405,7 +405,10 @@ export const SidebarProvider = ({ bottom: [], mobile: items.mobile, parentItem: parentItem, - previousSidebar: currentItems, + previousSidebar: + currentItems?.previousSidebar?.parentItem?.path !== parentItem.path + ? currentItems + : undefined, }) } }, [getCurrentSidebar, activePath]) diff --git a/www/packages/docs-ui/src/utils/get-navbar-items.ts b/www/packages/docs-ui/src/utils/get-navbar-items.ts index dfacdc2c1186c..ebcace177d989 100644 --- a/www/packages/docs-ui/src/utils/get-navbar-items.ts +++ b/www/packages/docs-ui/src/utils/get-navbar-items.ts @@ -1,17 +1,29 @@ -import { NavbarLinkProps, navbarItems } from ".." +import { NavbarItem, legacyNavbarItems, navbarItemsV1, navbarItemsV2 } from ".." type Options = { basePath: string activePath: string + version?: "v1" | "v2" | "legacy" } export function getNavbarItems({ basePath, activePath, -}: Options): NavbarLinkProps[] { - return navbarItems.map((item) => ({ - ...item, - isActive: activePath === item.href, - href: `${basePath}${item.href}`, - })) + version = "legacy" +}: Options): NavbarItem[] { + const navbarItems = version === "v2" ? navbarItemsV2 : version === "v1" ? navbarItemsV1 : legacyNavbarItems + return navbarItems.map((item) => { + if (item.type === "divider") { + return item + } + + return { + ...item, + props: { + ...item.props, + isActive: activePath === item.props?.href, + href: `${basePath}${item.props?.href}`, + } + } + }) } diff --git a/www/packages/types/src/config.ts b/www/packages/types/src/config.ts index 4c5bb621de2fd..e912baf9e1de5 100644 --- a/www/packages/types/src/config.ts +++ b/www/packages/types/src/config.ts @@ -3,6 +3,7 @@ import { SidebarSectionItemsType } from "./sidebar.js" export declare type DocsConfig = { titleSuffix?: string baseUrl: string + basePath?: string sidebar: SidebarSectionItemsType filesBasePath?: string useNextLinks?: boolean