feat(admin, admin-ui, medusa-js, medusa-react, medusa): Support Admin Extensions (#4761)

Co-authored-by: Rares Stefan <948623+StephixOne@users.noreply.github.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Kasper Fabricius Kristensen
2023-08-17 12:14:45 +00:00
committed by GitHub
co-authored by Rares Stefan Oli Juhl
parent 26c78bbc03
commit f1a05f4725
189 changed files with 14570 additions and 12773 deletions
@@ -2,21 +2,46 @@ import { PropsWithChildren } from "react"
import { HelmetProvider } from "react-helmet-async"
import { LayeredModalProvider } from "../components/molecules/modal/layered-modal"
import { SteppedProvider } from "../components/molecules/modal/stepped-modal"
import RouteRegistry from "../registries/route-registry"
import SettingRegistry from "../registries/setting-registry"
import WidgetRegistry from "../registries/widget-registry"
import { FeatureFlagProvider } from "./feature-flag-provider"
import { MedusaProvider } from "./medusa-provider"
import { PollingProvider } from "./polling-provider"
import { RouteProvider } from "./route-provider"
import { SettingProvider } from "./setting-provider"
import { WidgetProvider } from "./widget-provider"
type Props = PropsWithChildren<{
widgetRegistry: WidgetRegistry
routeRegistry: RouteRegistry
settingRegistry: SettingRegistry
}>
/**
* This component wraps all providers into a single component.
*/
export const Providers = ({ children }: PropsWithChildren) => {
export const Providers = ({
widgetRegistry,
routeRegistry,
settingRegistry,
children,
}: Props) => {
return (
<HelmetProvider>
<MedusaProvider>
<FeatureFlagProvider>
<PollingProvider>
<SteppedProvider>
<LayeredModalProvider>{children}</LayeredModalProvider>
<LayeredModalProvider>
<WidgetProvider registry={widgetRegistry}>
<RouteProvider registry={routeRegistry}>
<SettingProvider registry={settingRegistry}>
{children}
</SettingProvider>
</RouteProvider>
</WidgetProvider>
</LayeredModalProvider>
</SteppedProvider>
</PollingProvider>
</FeatureFlagProvider>
@@ -0,0 +1,55 @@
import React, { PropsWithChildren, useCallback, useMemo } from "react"
import RouteRegistry from "../registries/route-registry"
import { Link, Route, RouteSegment } from "../types/extensions"
type RouteContextType = {
getTopLevelRoutes: () => (Route | RouteSegment)[]
getNestedRoutes: (parent: string) => Route[]
getLinks: () => Link[]
}
const RouteContext = React.createContext<RouteContextType | null>(null)
export const useRoutes = () => {
const context = React.useContext(RouteContext)
if (!context) {
throw new Error("useRoutes must be used within a RouteContext")
}
return context
}
type RouteProviderProps = PropsWithChildren<{
registry: RouteRegistry
}>
export const RouteProvider = ({ registry, children }: RouteProviderProps) => {
const getTopLevelRoutes = useCallback(() => {
return registry.getTopLevelRoutes()
}, [registry])
const getNestedRoutes = useCallback(
(parent: string) => {
return registry.getNestedRoutes(parent)
},
[registry]
)
const getLinks = useCallback(() => {
return registry.getLinks()
}, [registry])
const values = useMemo(
() => ({
getTopLevelRoutes,
getNestedRoutes,
getLinks,
}),
[getTopLevelRoutes, getNestedRoutes, getLinks]
)
return (
<RouteContext.Provider value={values}>{children}</RouteContext.Provider>
)
}
@@ -0,0 +1,49 @@
import React, { PropsWithChildren, useCallback, useMemo } from "react"
import SettingRegistry from "../registries/setting-registry"
import { Card, Setting } from "../types/extensions"
type SettingContextType = {
getSettings: () => Setting[]
getCards: () => Card[]
}
const SettingContext = React.createContext<SettingContextType | null>(null)
export const useSettings = () => {
const context = React.useContext(SettingContext)
if (!context) {
throw new Error("useSettings must be used within a SettingContext")
}
return context
}
type SettingProviderProps = PropsWithChildren<{
registry: SettingRegistry
}>
export const SettingProvider = ({
registry,
children,
}: SettingProviderProps) => {
const getSettings = useCallback(() => {
return registry.getSettings()
}, [registry])
const getCards = useCallback(() => {
return registry.getCards()
}, [registry])
const values = useMemo(
() => ({
getSettings,
getCards,
}),
[getSettings, getCards]
)
return (
<SettingContext.Provider value={values}>{children}</SettingContext.Provider>
)
}
@@ -0,0 +1,38 @@
import React, { PropsWithChildren, useCallback, useMemo } from "react"
import WidgetRegistry from "../registries/widget-registry"
import { InjectionZone, Widget } from "../types/extensions"
type WidgetContextType = {
getWidgets: (injectionZone: InjectionZone) => Widget[]
}
const WidgetContext = React.createContext<WidgetContextType | null>(null)
export const useWidgets = () => {
const context = React.useContext(WidgetContext)
if (!context) {
throw new Error("useWidgets must be used within a WidgetContext")
}
return context
}
type WidgetProviderProps = PropsWithChildren<{
registry: WidgetRegistry
}>
export const WidgetProvider = ({ registry, children }: WidgetProviderProps) => {
const getWidgets = useCallback(
(injectionZone: InjectionZone) => {
return registry.getWidgets(injectionZone)
},
[registry]
)
const values = useMemo(() => ({ getWidgets }), [getWidgets])
return (
<WidgetContext.Provider value={values}>{children}</WidgetContext.Provider>
)
}