diff --git a/extensions/example-extension/renderer.tsx b/extensions/example-extension/renderer.tsx index 4deb08558b..a1fb546df7 100644 --- a/extensions/example-extension/renderer.tsx +++ b/extensions/example-extension/renderer.tsx @@ -1,26 +1,16 @@ -import { LensRendererExtension, Registry } from "@k8slens/extensions"; -import { ExamplePage, ExampleIcon } from "./page" +import { LensRendererExtension } from "@k8slens/extensions"; +import { ExampleIcon, ExamplePage } from "./page" import React from "react" export default class ExampleExtension extends LensRendererExtension { - onActivate() { - console.log('EXAMPLE EXTENSION RENDERER: ACTIVATED', this.getMeta()); - } - - registerClusterPage(registry: Registry.ClusterPageRegistry) { - this.disposers.push( - registry.add({ - path: "/extension-example", - title: "Example Extension", - components: { - Page: () => , - MenuIcon: ExampleIcon, - } - }) - ) - } - - onDeactivate() { - console.log('EXAMPLE EXTENSION RENDERER: DEACTIVATED', this.getMeta()); - } + clusterPages = [ + { + path: "/extension-example", + title: "Example Extension", + components: { + Page: () => , + MenuIcon: ExampleIcon, + } + } + ] } diff --git a/extensions/metrics-cluster-feature/renderer.tsx b/extensions/metrics-cluster-feature/renderer.tsx index 2b4b4f07e9..58565c13f5 100644 --- a/extensions/metrics-cluster-feature/renderer.tsx +++ b/extensions/metrics-cluster-feature/renderer.tsx @@ -1,25 +1,23 @@ -import { Registry, LensRendererExtension } from "@k8slens/extensions" +import { LensRendererExtension } from "@k8slens/extensions" import { MetricsFeature } from "./src/metrics-feature" import React from "react" export default class ClusterMetricsFeatureExtension extends LensRendererExtension { - registerClusterFeatures(registry: Registry.ClusterFeatureRegistry) { - this.disposers.push( - registry.add({ - title: "Metrics Stack", - components: { - Description: () => { - return ( - + clusterFeatures = [ + { + title: "Metrics Stack", + components: { + Description: () => { + return ( + Enable timeseries data visualization (Prometheus stack) for your cluster. Install this only if you don't have existing Prometheus stack installed. You can see preview of manifests here. - ) - } - }, - feature: new MetricsFeature() - }) - ) - } + ) + } + }, + feature: new MetricsFeature() + } + ] } diff --git a/extensions/node-menu/renderer.tsx b/extensions/node-menu/renderer.tsx index b3e3ffd121..db8232a518 100644 --- a/extensions/node-menu/renderer.tsx +++ b/extensions/node-menu/renderer.tsx @@ -1,21 +1,15 @@ -import { Registry, LensRendererExtension } from "@k8slens/extensions"; +import { LensRendererExtension } from "@k8slens/extensions"; import React from "react" -import { NodeMenu } from "./src/node-menu" +import { NodeMenu, NodeMenuProps } from "./src/node-menu" export default class NodeMenuRendererExtension extends LensRendererExtension { - async onActivate() { - console.log("node-menu extension activated") - } - - registerKubeObjectMenus(registry: Registry.KubeObjectMenuRegistry) { - this.disposers.push( - registry.add({ - kind: "Node", - apiVersions: ["v1"], - components: { - MenuItem: (props) => - } - }) - ) - } + kubeObjectMenuItems = [ + { + kind: "Node", + apiVersions: ["v1"], + components: { + MenuItem: (props: NodeMenuProps) => + } + } + ] } diff --git a/extensions/node-menu/src/node-menu.tsx b/extensions/node-menu/src/node-menu.tsx index 09ef251d60..8c7466694e 100644 --- a/extensions/node-menu/src/node-menu.tsx +++ b/extensions/node-menu/src/node-menu.tsx @@ -1,7 +1,10 @@ import React from "react"; import { Component, K8sApi, Navigation} from "@k8slens/extensions" -export function NodeMenu(props: Component.KubeObjectMenuProps) { +export interface NodeMenuProps extends Component.KubeObjectMenuProps { +} + +export function NodeMenu(props: NodeMenuProps) { const { object: node, toolbar } = props; if (!node) return null; const nodeName = node.getName(); diff --git a/extensions/pod-menu/renderer.tsx b/extensions/pod-menu/renderer.tsx index 1340d835d0..30898da806 100644 --- a/extensions/pod-menu/renderer.tsx +++ b/extensions/pod-menu/renderer.tsx @@ -1,31 +1,23 @@ -import { Registry, LensRendererExtension } from "@k8slens/extensions"; -import { PodShellMenu } from "./src/shell-menu" -import { PodLogsMenu } from "./src/logs-menu" +import { LensRendererExtension } from "@k8slens/extensions"; +import { PodShellMenu, PodShellMenuProps } from "./src/shell-menu" +import { PodLogsMenu, PodLogsMenuProps } from "./src/logs-menu" import React from "react" export default class PodMenuRendererExtension extends LensRendererExtension { - async onActivate() { - console.log("pod-menu extension activated") - } - - registerKubeObjectMenus(registry: Registry.KubeObjectMenuRegistry) { - this.disposers.push( - registry.add({ - kind: "Pod", - apiVersions: ["v1"], - components: { - MenuItem: (props) => - } - }) - ) - this.disposers.push( - registry.add({ - kind: "Pod", - apiVersions: ["v1"], - components: { - MenuItem: (props) => - } - }) - ) - } + kubeObjectMenuItems = [ + { + kind: "Pod", + apiVersions: ["v1"], + components: { + MenuItem: (props: PodShellMenuProps) => + } + }, + { + kind: "Pod", + apiVersions: ["v1"], + components: { + MenuItem: (props: PodLogsMenuProps) => + } + } + ] } diff --git a/extensions/pod-menu/src/logs-menu.tsx b/extensions/pod-menu/src/logs-menu.tsx index e99e454fdf..f80c55cc01 100644 --- a/extensions/pod-menu/src/logs-menu.tsx +++ b/extensions/pod-menu/src/logs-menu.tsx @@ -1,10 +1,10 @@ import React from "react"; import { Component, K8sApi, Util, Navigation } from "@k8slens/extensions"; -interface Props extends Component.KubeObjectMenuProps { +export interface PodLogsMenuProps extends Component.KubeObjectMenuProps { } -export class PodLogsMenu extends React.Component { +export class PodLogsMenu extends React.Component { showLogs(container: K8sApi.IPodContainer) { Navigation.hideDetails(); const pod = this.props.object; diff --git a/extensions/pod-menu/src/shell-menu.tsx b/extensions/pod-menu/src/shell-menu.tsx index 5f19ceca01..772d17a894 100644 --- a/extensions/pod-menu/src/shell-menu.tsx +++ b/extensions/pod-menu/src/shell-menu.tsx @@ -3,10 +3,10 @@ import React from "react"; import { Component, K8sApi, Util, Navigation } from "@k8slens/extensions"; -interface Props extends Component.KubeObjectMenuProps { +export interface PodShellMenuProps extends Component.KubeObjectMenuProps { } -export class PodShellMenu extends React.Component { +export class PodShellMenu extends React.Component { async execShell(container?: string) { Navigation.hideDetails(); const { object: pod } = this.props diff --git a/extensions/support-page/main.ts b/extensions/support-page/main.ts index 20f17df4cf..70ec3bc026 100644 --- a/extensions/support-page/main.ts +++ b/extensions/support-page/main.ts @@ -1,20 +1,14 @@ -import { LensMainExtension, Registry, windowManager } from "@k8slens/extensions"; +import { LensMainExtension, windowManager } from "@k8slens/extensions"; import { supportPageURL } from "./src/support.route"; export default class SupportPageMainExtension extends LensMainExtension { - async onActivate() { - console.log("support page extension activated") - } - - async registerAppMenus(registry: Registry.MenuRegistry) { - this.disposers.push( - registry.add({ - parentId: "help", - label: "Support", - click() { - windowManager.navigate(supportPageURL()); - } - }) - ) - } + appMenus = [ + { + parentId: "help", + label: "Support", + click() { + windowManager.navigate(supportPageURL()); + } + } + ] } diff --git a/extensions/support-page/renderer.tsx b/extensions/support-page/renderer.tsx index 84e7f87f65..9f52a972bf 100644 --- a/extensions/support-page/renderer.tsx +++ b/extensions/support-page/renderer.tsx @@ -1,39 +1,31 @@ import React from "react"; -import { Component, LensRendererExtension, Navigation, Registry } from "@k8slens/extensions"; +import { Component, LensRendererExtension, Navigation } from "@k8slens/extensions"; import { supportPageRoute, supportPageURL } from "./src/support.route"; import { Support } from "./src/support"; export default class SupportPageRendererExtension extends LensRendererExtension { - async onActivate() { - console.log("support page extension activated") - } + globalPages = [ + { + ...supportPageRoute, + url: supportPageURL(), + hideInMenu: true, + components: { + Page: Support, + } + } + ] - registerGlobalPage(registry: Registry.GlobalPageRegistry) { - this.disposers.push( - registry.add({ - ...supportPageRoute, - url: supportPageURL(), - hideInMenu: true, - components: { - Page: Support, - } - }) - ) - } - - registerStatusBarItem(registry: Registry.StatusBarRegistry) { - this.disposers.push( - registry.add({ - item: ( -
Navigation.navigate(supportPageURL())} - > - - Support -
- ) - }) - ) - } + statusBarItems = [ + { + item: ( +
Navigation.navigate(supportPageURL())} + > + + Support +
+ ) + } + ] } diff --git a/extensions/telemetry/renderer.tsx b/extensions/telemetry/renderer.tsx index 3988e97097..04057386bf 100644 --- a/extensions/telemetry/renderer.tsx +++ b/extensions/telemetry/renderer.tsx @@ -1,29 +1,23 @@ -import { LensRendererExtension, Registry } from "@k8slens/extensions"; +import { LensRendererExtension } from "@k8slens/extensions"; import { telemetryPreferencesStore } from "./src/telemetry-preferences-store" import { TelemetryPreferenceHint, TelemetryPreferenceInput } from "./src/telemetry-preference" import { tracker } from "./src/tracker" import React from "react" export default class TelemetryRendererExtension extends LensRendererExtension { + appPreferences = [ + { + title: "Telemetry & Usage Tracking", + components: { + Hint: () => , + Input: () => + } + } + ]; + async onActivate() { console.log("telemetry extension activated") tracker.start() await telemetryPreferencesStore.loadExtension(this) } - - registerAppPreferences(registry: Registry.AppPreferenceRegistry) { - this.disposers.push( - registry.add({ - title: "Telemetry & Usage Tracking", - components: { - Hint: () => , - Input: () => - } - }) - ) - } - - onDeactivate() { - console.log("telemetry extension deactivated") - } } diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts index 0e831af9f8..c0b2d5ada6 100644 --- a/src/extensions/extension-loader.ts +++ b/src/extensions/extension-loader.ts @@ -36,26 +36,26 @@ export class ExtensionLoader { loadOnMain() { logger.info('[EXTENSIONS-LOADER]: load on main') - this.autoloadExtensions((instance: LensMainExtension) => { - instance.registerAppMenus(menuRegistry); + this.autoloadExtensions((extension: LensMainExtension) => { + extension.registerTo(menuRegistry, extension.appMenus) }) } loadOnClusterManagerRenderer() { logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)') - this.autoloadExtensions((instance: LensRendererExtension) => { - instance.registerGlobalPage(globalPageRegistry) - instance.registerAppPreferences(appPreferenceRegistry) - instance.registerClusterFeatures(clusterFeatureRegistry) - instance.registerStatusBarItem(statusBarRegistry) + this.autoloadExtensions((extension: LensRendererExtension) => { + extension.registerTo(globalPageRegistry, extension.globalPages) + extension.registerTo(appPreferenceRegistry, extension.appPreferences) + extension.registerTo(clusterFeatureRegistry, extension.clusterFeatures) + extension.registerTo(statusBarRegistry, extension.statusBarItems) }) } loadOnClusterRenderer() { logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)') - this.autoloadExtensions((instance: LensRendererExtension) => { - instance.registerClusterPage(clusterPageRegistry) - instance.registerKubeObjectMenus(kubeObjectMenuRegistry) + this.autoloadExtensions((extension: LensRendererExtension) => { + extension.registerTo(clusterPageRegistry, extension.clusterPages) + extension.registerTo(kubeObjectMenuRegistry, extension.kubeObjectMenuItems) }) } diff --git a/src/extensions/lens-extension.ts b/src/extensions/lens-extension.ts index b348cd6868..0921dc066a 100644 --- a/src/extensions/lens-extension.ts +++ b/src/extensions/lens-extension.ts @@ -1,6 +1,7 @@ import { readJsonSync } from "fs-extra"; import { action, observable, toJS } from "mobx"; import logger from "../main/logger"; +import { BaseRegistry } from "./registries/base-registry"; export type ExtensionId = string | ExtensionPackageJsonPath; export type ExtensionPackageJsonPath = string; @@ -25,7 +26,7 @@ export interface ExtensionManifest extends ExtensionModel { export class LensExtension implements ExtensionModel { public id: ExtensionId; public updateUrl: string; - protected disposers: Function[] = []; + protected disposers: (() => void)[] = []; @observable name = ""; @observable description = ""; @@ -77,6 +78,14 @@ export class LensExtension implements ExtensionModel { // mock } + registerTo(registry: BaseRegistry, items: T[] = []) { + const disposers = items.map(item => registry.add(item)); + this.disposers.push(...disposers); + return () => { + this.disposers = this.disposers.filter(disposer => !disposers.includes(disposer)) + }; + } + getMeta() { return toJS({ id: this.id, diff --git a/src/extensions/lens-main-extension.ts b/src/extensions/lens-main-extension.ts index 9ad858d0c6..8e300bda77 100644 --- a/src/extensions/lens-main-extension.ts +++ b/src/extensions/lens-main-extension.ts @@ -1,12 +1,7 @@ +import type { MenuRegistration } from "./registries/menu-registry"; +import { observable } from "mobx"; import { LensExtension } from "./lens-extension" -import type { MenuRegistry } from "./registries/menu-registry"; export class LensMainExtension extends LensExtension { - registerAppMenus(registry: MenuRegistry) { - // - } - - registerPrometheusProviders(registry: any) { - // - } + @observable.shallow appMenus: MenuRegistration[] = [] } diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index 4c2e25ebdf..829079d0f0 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -1,28 +1,12 @@ +import type { AppPreferenceRegistration, ClusterFeatureRegistration, KubeObjectMenuRegistration, PageRegistration, StatusBarRegistration } from "./registries" +import { observable } from "mobx"; import { LensExtension } from "./lens-extension" -import type { GlobalPageRegistry, ClusterPageRegistry, AppPreferenceRegistry, StatusBarRegistry, KubeObjectMenuRegistry, ClusterFeatureRegistry } from "./registries" export class LensRendererExtension extends LensExtension { - registerGlobalPage(registry: GlobalPageRegistry) { - return - } - - registerClusterPage(registry: ClusterPageRegistry) { - return - } - - registerAppPreferences(registry: AppPreferenceRegistry) { - return - } - - registerClusterFeatures(registry: ClusterFeatureRegistry) { - return - } - - registerStatusBarItem(registry: StatusBarRegistry) { - return - } - - registerKubeObjectMenus(registry: KubeObjectMenuRegistry) { - return - } + @observable.shallow globalPages: PageRegistration[] = [] + @observable.shallow clusterPages: PageRegistration[] = [] + @observable.shallow appPreferences: AppPreferenceRegistration[] = [] + @observable.shallow clusterFeatures: ClusterFeatureRegistration[] = [] + @observable.shallow statusBarItems: StatusBarRegistration[] = [] + @observable.shallow kubeObjectMenuItems: KubeObjectMenuRegistration[] = [] } diff --git a/src/extensions/registries/menu-registry.ts b/src/extensions/registries/menu-registry.ts index d31d124f30..4b98201073 100644 --- a/src/extensions/registries/menu-registry.ts +++ b/src/extensions/registries/menu-registry.ts @@ -1,11 +1,10 @@ // Extensions API -> Global menu customizations -import type { MenuTopId } from "../../main/menu"; import type { MenuItemConstructorOptions } from "electron"; import { BaseRegistry } from "./base-registry"; export interface MenuRegistration extends MenuItemConstructorOptions { - parentId?: MenuTopId; + parentId: string; } export class MenuRegistry extends BaseRegistry {