diff --git a/extensions/support-page/renderer.tsx b/extensions/support-page/renderer.tsx index 0137ea7771..92d460fdfc 100644 --- a/extensions/support-page/renderer.tsx +++ b/extensions/support-page/renderer.tsx @@ -5,6 +5,8 @@ import { SupportPage } from "./src/support"; export default class SupportPageRendererExtension extends LensRendererExtension { globalPages: Interface.PageRegistration[] = [ { + id: "support", + routePath: "/support", components: { Page: SupportPage, } @@ -14,7 +16,7 @@ export default class SupportPageRendererExtension extends LensRendererExtension statusBarItems: Interface.StatusBarRegistration[] = [ { item: ( -
this.navigate()}> +
this.navigate("/support")}>
) diff --git a/src/extensions/lens-extension.ts b/src/extensions/lens-extension.ts index 164c84baa5..f1ffb9184b 100644 --- a/src/extensions/lens-extension.ts +++ b/src/extensions/lens-extension.ts @@ -14,7 +14,6 @@ export interface LensExtensionManifest { } export class LensExtension { - readonly routePrefix = "/extension/:name" readonly manifest: LensExtensionManifest; readonly manifestPath: string; readonly isBundled: boolean; diff --git a/src/extensions/lens-main-extension.ts b/src/extensions/lens-main-extension.ts index 0055344a66..de9aae40ec 100644 --- a/src/extensions/lens-main-extension.ts +++ b/src/extensions/lens-main-extension.ts @@ -2,13 +2,14 @@ import type { MenuRegistration } from "./registries/menu-registry"; import { observable } from "mobx"; import { LensExtension } from "./lens-extension" import { WindowManager } from "../main/window-manager"; +import { getPageUrl } from "./registries/page-registry" export class LensMainExtension extends LensExtension { @observable.shallow appMenus: MenuRegistration[] = [] async navigate(location?: string, frameId?: number) { const windowManager = WindowManager.getInstance(); - const url = this.getPageUrl(location); // get full path to extension's page + const url = getPageUrl(this, location); // get full path to extension's page await windowManager.navigate(url, frameId); } } diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index 87ca214805..5968124cbc 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -1,6 +1,7 @@ import type { AppPreferenceRegistration, ClusterFeatureRegistration, KubeObjectDetailRegistration, KubeObjectMenuRegistration, KubeObjectStatusRegistration, PageMenuRegistration, PageRegistration, StatusBarRegistration, } from "./registries" import { observable } from "mobx"; import { LensExtension } from "./lens-extension" +import { getPageUrl } from "./registries/page-registry" export class LensRendererExtension extends LensExtension { @observable.shallow globalPages: PageRegistration[] = [] @@ -16,6 +17,6 @@ export class LensRendererExtension extends LensExtension { async navigate(location?: string) { const { navigate } = await import("../renderer/navigation"); - navigate(this.getPageUrl(location)); + navigate(getPageUrl(this, location)); } } diff --git a/src/extensions/registries/page-menu-registry.ts b/src/extensions/registries/page-menu-registry.ts index 0748fad187..34fe50154c 100644 --- a/src/extensions/registries/page-menu-registry.ts +++ b/src/extensions/registries/page-menu-registry.ts @@ -5,13 +5,18 @@ import { action } from "mobx"; import type { IconProps } from "../../renderer/components/icon"; import { BaseRegistry } from "./base-registry"; import { LensExtension } from "../lens-extension"; -import { getPageUrl } from "./page-registry"; +import { PageRegistration } from "../interfaces"; + +export interface PageMenuTarget { + pageId: string; + extensionId: string; + params: object; +} export interface PageMenuRegistration { - url?: string; // when not provided initial extension's path used, e.g. "/extension/lens-extension-name" + target?: PageMenuTarget; title: React.ReactNode; components: PageMenuComponents; - subMenus?: PageSubMenuRegistration[]; } export interface PageSubMenuRegistration { @@ -24,18 +29,15 @@ export interface PageMenuComponents { } export class PageMenuRegistry extends BaseRegistry { + @action add(items: T[], ext?: LensExtension) { const normalizedItems = items.map((i) => { - i.url = getPageUrl(ext, i.url) + i.target.extensionId = ext.name return i }) return super.add(normalizedItems); } - - getByRoutePath(routePath: string) { - return this.getItems().find((i) => i.url === routePath) - } } export const globalPageMenuRegistry = new PageMenuRegistry>(); diff --git a/src/extensions/registries/page-registry.ts b/src/extensions/registries/page-registry.ts index 2511f28a95..f82cce2196 100644 --- a/src/extensions/registries/page-registry.ts +++ b/src/extensions/registries/page-registry.ts @@ -5,12 +5,13 @@ import { action } from "mobx"; import { compile } from "path-to-regexp"; import { BaseRegistry } from "./base-registry"; import { LensExtension } from "../lens-extension" +import { PageMenuTarget } from "./page-menu-registry"; export interface PageRegistration { + id: string; // hello-world:id routePath?: string; // additional (suffix) route path to base extension's route: "/extension/:name" exact?: boolean; // route matching flag, see: https://reactrouter.com/web/api/NavLink/exact-bool components: PageComponents; - subPages?: SubPageRegistration[]; } export interface SubPageRegistration { @@ -41,8 +42,8 @@ export class PageRegistry extends BaseRegistry { return super.add(normalizedItems); } - getByUrl(url: string) { - return this.getItems().find((i) => i.routePath === url) + getByPageMenuTarget(target: PageMenuTarget) { + return this.getItems().find((page) => page.routePath.startsWith(`/extension/${target.extensionId}/`) && page.id === target.pageId) } } diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx index 193a1a8796..cb8d02172b 100755 --- a/src/renderer/components/app.tsx +++ b/src/renderer/components/app.tsx @@ -74,27 +74,8 @@ export class App extends React.Component { } renderExtensionRoutes() { - return clusterPageRegistry.getItems().map(({ components: { Page }, exact, routePath, subPages }) => { + return clusterPageRegistry.getItems().map(({ components: { Page }, exact, routePath }) => { const Component = () => { - if (subPages) { - const tabs: TabLayoutRoute[] = subPages.map(({ exact, routePath, components: { Page } }) => { - const menuItem = clusterPageMenuRegistry.getByRoutePath(routePath); - if (!menuItem) return; - return { - routePath, exact, - component: Page, - url: menuItem.url, - title: menuItem.title, - } - }).filter(Boolean); - if (tabs.length > 0) { - return ( - - - - ) - } - } return }; return diff --git a/src/renderer/components/cluster-manager/clusters-menu.tsx b/src/renderer/components/cluster-manager/clusters-menu.tsx index 4c81e967b6..302e4e76d2 100644 --- a/src/renderer/components/cluster-manager/clusters-menu.tsx +++ b/src/renderer/components/cluster-manager/clusters-menu.tsx @@ -23,6 +23,7 @@ import { ConfirmDialog } from "../confirm-dialog"; import { clusterIpc } from "../../../common/cluster-ipc"; import { clusterViewURL } from "./cluster-view.route"; import { globalPageMenuRegistry, globalPageRegistry } from "../../../extensions/registries"; +import { compile } from "path-to-regexp"; interface Props { className?: IClassName; @@ -148,8 +149,8 @@ export class ClustersMenu extends React.Component { )}
- {globalPageMenuRegistry.getItems().map(({ title, url, components: { Icon } }) => { - const registeredPage = globalPageRegistry.getByUrl(url); + {globalPageMenuRegistry.getItems().map(({ title, target, components: { Icon } }) => { + const registeredPage = globalPageRegistry.getByPageMenuTarget(target); if (!registeredPage) return; const { routePath, exact } = registeredPage; return ( @@ -157,7 +158,7 @@ export class ClustersMenu extends React.Component { key={routePath} tooltip={title} active={isActiveRoute({ path: routePath, exact })} - onClick={() => navigate(url)} + onClick={() => navigate(compile(routePath)(target.params))} /> ) })} diff --git a/src/renderer/components/layout/sidebar.tsx b/src/renderer/components/layout/sidebar.tsx index 74fdd37b0b..8485f1e134 100644 --- a/src/renderer/components/layout/sidebar.tsx +++ b/src/renderer/components/layout/sidebar.tsx @@ -30,6 +30,7 @@ import { isActiveRoute } from "../../navigation"; import { isAllowedResource } from "../../../common/rbac" import { Spinner } from "../spinner"; import { clusterPageMenuRegistry, clusterPageRegistry } from "../../../extensions/registries"; +import { compile } from "path-to-regexp"; const SidebarContext = React.createContext({ pinned: false }); type SidebarContextValue = { @@ -191,10 +192,11 @@ export class Sidebar extends React.Component { > {this.renderCustomResources()} - {clusterPageMenuRegistry.getItems().map(({ title, url, components: { Icon } }) => { - const registeredPage = clusterPageRegistry.getByUrl(url); + {clusterPageMenuRegistry.getItems().map(({ title, target, components: { Icon } }) => { + const registeredPage = clusterPageRegistry.getByPageMenuTarget(target); if (!registeredPage) return; const { routePath, exact } = registeredPage; + const url = compile(routePath)(target.params) return (