feat(dashboard,admin-sdk,admin-shared,admin-vite-plugin): Add support for UI extensions (#7383)
* intial work * update lock * add routes and fix HMR of configs * cleanup * rm imports * rm debug from plugin * address feedback * address feedback
This commit is contained in:
+67
-9
@@ -1,13 +1,17 @@
|
||||
import { ArrowUturnLeft, MinusMini } from "@medusajs/icons"
|
||||
import { IconButton, Text } from "@medusajs/ui"
|
||||
import * as Collapsible from "@radix-ui/react-collapsible"
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { Fragment, useEffect, useMemo, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Link, useLocation } from "react-router-dom"
|
||||
|
||||
import { settingsRouteRegex } from "../../../lib/extension-helpers"
|
||||
import { Divider } from "../../common/divider"
|
||||
import { NavItem, NavItemProps } from "../nav-item"
|
||||
import { Shell } from "../shell"
|
||||
|
||||
import routes from "virtual:medusa/routes/links"
|
||||
|
||||
export const SettingsLayout = () => {
|
||||
return (
|
||||
<Shell>
|
||||
@@ -80,6 +84,21 @@ const useDeveloperRoutes = (): NavItemProps[] => {
|
||||
)
|
||||
}
|
||||
|
||||
const useExtensionRoutes = (): NavItemProps[] => {
|
||||
const links = routes.links
|
||||
|
||||
return useMemo(() => {
|
||||
const settingsLinks = links.filter((link) =>
|
||||
settingsRouteRegex.test(link.path)
|
||||
)
|
||||
|
||||
return settingsLinks.map((link) => ({
|
||||
label: link.label,
|
||||
to: link.path,
|
||||
}))
|
||||
}, [links])
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the `from` prop is not another settings route, to avoid
|
||||
* the user getting stuck in a navigation loop.
|
||||
@@ -95,6 +114,8 @@ const getSafeFromValue = (from: string) => {
|
||||
const SettingsSidebar = () => {
|
||||
const routes = useSettingRoutes()
|
||||
const developerRoutes = useDeveloperRoutes()
|
||||
const extensionRoutes = useExtensionRoutes()
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const location = useLocation()
|
||||
@@ -108,20 +129,24 @@ const SettingsSidebar = () => {
|
||||
|
||||
return (
|
||||
<aside className="flex flex-1 flex-col justify-between overflow-y-auto">
|
||||
<div className="px-3 py-2">
|
||||
<div className="flex items-center gap-x-3 p-1">
|
||||
<Link to={from} replace className="flex items-center justify-center">
|
||||
<IconButton size="small" variant="transparent">
|
||||
<div className="p-3">
|
||||
<div className="flex items-center gap-x-3 px-2 py-1.5">
|
||||
<IconButton size="2xsmall" variant="transparent" asChild>
|
||||
<Link
|
||||
to={from}
|
||||
replace
|
||||
className="flex items-center justify-center"
|
||||
>
|
||||
<ArrowUturnLeft />
|
||||
</IconButton>
|
||||
</Link>
|
||||
</Link>
|
||||
</IconButton>
|
||||
<Text leading="compact" weight="plus" size="small">
|
||||
{t("nav.settings")}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-3">
|
||||
<div className="border-ui-border-strong h-px w-full border-b border-dashed" />
|
||||
<div className="flex items-center justify-center px-3">
|
||||
<Divider variant="dashed" />
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col overflow-y-auto">
|
||||
<Collapsible.Root defaultOpen className="py-3">
|
||||
@@ -147,6 +172,9 @@ const SettingsSidebar = () => {
|
||||
</div>
|
||||
</Collapsible.Content>
|
||||
</Collapsible.Root>
|
||||
<div className="flex items-center justify-center px-3">
|
||||
<Divider variant="dashed" />
|
||||
</div>
|
||||
<Collapsible.Root defaultOpen className="py-3">
|
||||
<div className="px-3">
|
||||
<div className="text-ui-fg-muted flex h-7 items-center justify-between px-2">
|
||||
@@ -170,6 +198,36 @@ const SettingsSidebar = () => {
|
||||
</div>
|
||||
</Collapsible.Content>
|
||||
</Collapsible.Root>
|
||||
{extensionRoutes.length > 0 && (
|
||||
<Fragment>
|
||||
<div className="flex items-center justify-center px-3">
|
||||
<Divider variant="dashed" />
|
||||
</div>
|
||||
<Collapsible.Root defaultOpen className="py-3">
|
||||
<div className="px-3">
|
||||
<div className="text-ui-fg-muted flex h-7 items-center justify-between px-2">
|
||||
<Text size="small" leading="compact">
|
||||
{t("nav.extensions")}
|
||||
</Text>
|
||||
<Collapsible.Trigger asChild>
|
||||
<IconButton size="2xsmall" variant="transparent">
|
||||
<MinusMini className="text-ui-fg-muted" />
|
||||
</IconButton>
|
||||
</Collapsible.Trigger>
|
||||
</div>
|
||||
</div>
|
||||
<Collapsible.Content>
|
||||
<div className="pt-0.5">
|
||||
<nav className="flex flex-col gap-y-1">
|
||||
{extensionRoutes.map((setting) => (
|
||||
<NavItem key={setting.to} {...setting} />
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</Collapsible.Content>
|
||||
</Collapsible.Root>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</aside>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user