diff --git a/src/common/app-event-bus/app-event-bus.injectable.ts b/src/common/app-event-bus/app-event-bus.injectable.ts index 31ed3dd3a1..a4c57612d1 100644 --- a/src/common/app-event-bus/app-event-bus.injectable.ts +++ b/src/common/app-event-bus/app-event-bus.injectable.ts @@ -3,12 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { appEventBus } from "./event-bus"; +import { EventEmitter } from "../event-emitter"; +import type { AppEvent } from "./event-bus"; const appEventBusInjectable = getInjectable({ id: "app-event-bus", - instantiate: () => appEventBus, - causesSideEffects: true, + instantiate: () => new EventEmitter<[AppEvent]>(), }); export default appEventBusInjectable; diff --git a/src/common/app-event-bus/event-bus.ts b/src/common/app-event-bus/event-bus.ts index 67d23587c7..e947b5a4a7 100644 --- a/src/common/app-event-bus/event-bus.ts +++ b/src/common/app-event-bus/event-bus.ts @@ -3,7 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { EventEmitter } from "../event-emitter"; +import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; +import appEventBusInjectable from "./app-event-bus.injectable"; export interface AppEvent { name: string; @@ -12,4 +13,7 @@ export interface AppEvent { params?: Record; } -export const appEventBus = new EventEmitter<[AppEvent]>(); +/** + * @deprecated Switch to using appEventBusInjectable instead + */ +export const appEventBus = asLegacyGlobalForExtensionApi(appEventBusInjectable); diff --git a/src/extensions/common-api/event-bus.ts b/src/extensions/common-api/event-bus.ts index c6d2a1a34b..97442101b6 100644 --- a/src/extensions/common-api/event-bus.ts +++ b/src/extensions/common-api/event-bus.ts @@ -3,5 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -export { appEventBus } from "../../common/app-event-bus/event-bus"; +import { appEventBus as bus } from "../../common/app-event-bus/event-bus"; export type { AppEvent } from "../../common/app-event-bus/event-bus"; + +export const appEventBus = bus; diff --git a/src/features/cluster/__snapshots__/connection-status.test.ts.snap b/src/features/cluster/__snapshots__/connection-status.test.ts.snap index b0695fc1b0..13ab89ead3 100644 --- a/src/features/cluster/__snapshots__/connection-status.test.ts.snap +++ b/src/features/cluster/__snapshots__/connection-status.test.ts.snap @@ -78,7 +78,7 @@ exports[`cluster connection status renders 1`] = ` style="width: 320px;" >

- Welcome to OpenLens 5! + Welcome to OpenLens!

To get you started we have auto-detected your clusters in your diff --git a/src/features/cluster/connection-status.test.ts b/src/features/cluster/connection-status.test.ts index 640985c9e8..fc33f73a09 100644 --- a/src/features/cluster/connection-status.test.ts +++ b/src/features/cluster/connection-status.test.ts @@ -18,6 +18,8 @@ import createKubectlInjectable from "../../main/kubectl/create-kubectl.injectabl import type { KubeconfigManager } from "../../main/kubeconfig-manager/kubeconfig-manager"; import type { Kubectl } from "../../main/kubectl/kubectl"; import type { ContextHandler } from "../../main/context-handler/context-handler"; +import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; +import { KubernetesCluster } from "../../common/catalog-entities"; describe("cluster connection status", () => { let clusterStore: ClusterStore; @@ -40,6 +42,37 @@ describe("cluster connection status", () => { const createCluster = applicationBuilder.dis.mainDi.inject(createClusterInjectable); + applicationBuilder.dis.rendererDi.inject(catalogEntityRegistryInjectable).updateItems([ + new KubernetesCluster({ + metadata: { + labels: {}, + name: "minikube", + uid: "some-cluster-id", + }, + spec: { + kubeconfigContext: "minikube", + kubeconfigPath: "/some/file/path", + }, + status: { + phase: "disconnected", + }, + }), + new KubernetesCluster({ + metadata: { + labels: {}, + name: "minikube-2", + uid: "some-cluster-id-2", + }, + spec: { + kubeconfigContext: "minikube-2", + kubeconfigPath: "/some/file/path", + }, + status: { + phase: "disconnected", + }, + }), + ]); + cluster = createCluster({ contextName: "minikube", id: "some-cluster-id", diff --git a/src/renderer/api/catalog-category-registry.ts b/src/renderer/api/catalog-category-registry.ts index 9023c5a755..18c8493144 100644 --- a/src/renderer/api/catalog-category-registry.ts +++ b/src/renderer/api/catalog-category-registry.ts @@ -3,9 +3,5 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import catalogCategoryRegistryInjectable from "../../common/catalog/category-registry.injectable"; -import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; export type { CategoryFilter } from "../../common/catalog"; - -export const catalogCategoryRegistry = asLegacyGlobalForExtensionApi(catalogCategoryRegistryInjectable); diff --git a/src/renderer/components/+catalog/catalog-add-button.tsx b/src/renderer/components/+catalog/catalog-add-button.tsx index 227dd811b5..b6018ec6b8 100644 --- a/src/renderer/components/+catalog/catalog-add-button.tsx +++ b/src/renderer/components/+catalog/catalog-add-button.tsx @@ -13,7 +13,9 @@ import { autoBind } from "../../../common/utils"; import type { CatalogCategory, CatalogEntityAddMenuContext, CatalogEntityAddMenu } from "../../api/catalog-entity"; import { EventEmitter } from "events"; import { navigate } from "../../navigation"; -import { catalogCategoryRegistry } from "../../api/catalog-category-registry"; +import type { CatalogCategoryRegistry } from "../../../common/catalog"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import catalogCategoryRegistryInjectable from "../../../common/catalog/category-registry.injectable"; export interface CatalogAddButtonProps { category: CatalogCategory; @@ -21,12 +23,16 @@ export interface CatalogAddButtonProps { type CategoryId = string; +interface Dependencies { + catalogCategoryRegistry: CatalogCategoryRegistry; +} + @observer -export class CatalogAddButton extends React.Component { +class NonInjectedCatalogAddButton extends React.Component { @observable protected isOpen = false; @observable menuItems = new Map(); - constructor(props: CatalogAddButtonProps) { + constructor(props: CatalogAddButtonProps & Dependencies) { super(props); makeObservable(this); autoBind(this); @@ -43,7 +49,7 @@ export class CatalogAddButton extends React.Component { } get categories() { - return catalogCategoryRegistry.filteredItems; + return this.props.catalogCategoryRegistry.filteredItems; } @action @@ -133,3 +139,10 @@ export class CatalogAddButton extends React.Component { ); } } + +export const CatalogAddButton = withInjectables(NonInjectedCatalogAddButton, { + getProps: (di, props) => ({ + ...props, + catalogCategoryRegistry: di.inject(catalogCategoryRegistryInjectable), + }), +}); diff --git a/src/renderer/components/+catalog/catalog-menu.tsx b/src/renderer/components/+catalog/catalog-menu.tsx index 8a672ddb44..bf2678448b 100644 --- a/src/renderer/components/+catalog/catalog-menu.tsx +++ b/src/renderer/components/+catalog/catalog-menu.tsx @@ -9,23 +9,21 @@ import styles from "./catalog-menu.module.scss"; import React from "react"; import type { TreeItemProps } from "@material-ui/lab"; import { TreeItem, TreeView } from "@material-ui/lab"; -import { catalogCategoryRegistry } from "../../api/catalog-category-registry"; import { Icon } from "../icon"; import { StylesProvider } from "@material-ui/core"; import { cssNames } from "../../utils"; import type { CatalogCategory } from "../../api/catalog-entity"; import { observer } from "mobx-react"; import { CatalogCategoryLabel } from "./catalog-category-label"; +import type { CatalogCategoryRegistry } from "../../../common/catalog"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import catalogCategoryRegistryInjectable from "../../../common/catalog/category-registry.injectable"; export interface CatalogMenuProps { activeTab: string | undefined; onItemClick: (id: string) => void; } -function getCategories() { - return catalogCategoryRegistry.filteredItems; -} - function getCategoryIcon(category: CatalogCategory) { const { icon } = category.metadata ?? {}; @@ -44,7 +42,15 @@ function Item(props: TreeItemProps) { ); } -export const CatalogMenu = observer((props: CatalogMenuProps) => { +interface Dependencies { + catalogCategoryRegistry: CatalogCategoryRegistry; +} + +const NonInjectedCatalogMenu = observer(({ + activeTab = "browse", + onItemClick, + catalogCategoryRegistry, +}: CatalogMenuProps & Dependencies) => { return ( // Overwrite Material UI styles with injectFirst https://material-ui.com/guides/interoperability/#controlling-priority-4 @@ -54,13 +60,13 @@ export const CatalogMenu = observer((props: CatalogMenuProps) => { defaultExpanded={["catalog"]} defaultCollapseIcon={} defaultExpandIcon={} - selected={props.activeTab || "browse"} + selected={activeTab} > props.onItemClick("*")} + onClick={() => onItemClick("*")} /> { className={cssNames(styles.bordered)} > { - getCategories().map(category => ( + catalogCategoryRegistry.filteredItems.map(category => ( } data-testid={`${category.getId()}-tab`} - onClick={() => props.onItemClick(category.getId())} + onClick={() => onItemClick(category.getId())} /> )) } @@ -85,3 +91,10 @@ export const CatalogMenu = observer((props: CatalogMenuProps) => { ); }); + +export const CatalogMenu = withInjectables(NonInjectedCatalogMenu, { + getProps: (di, props) => ({ + ...props, + catalogCategoryRegistry: di.inject(catalogCategoryRegistryInjectable), + }), +}); diff --git a/src/renderer/initializers/catalog.tsx b/src/renderer/initializers/catalog.tsx index 2597eb0f3e..1cb9f46573 100644 --- a/src/renderer/initializers/catalog.tsx +++ b/src/renderer/initializers/catalog.tsx @@ -5,12 +5,11 @@ import React from "react"; import fs from "fs"; -import "../../common/catalog-entities/kubernetes-cluster"; import { ClusterStore } from "../../common/cluster-store/cluster-store"; -import { catalogCategoryRegistry } from "../api/catalog-category-registry"; import { WeblinkAddCommand } from "../components/catalog-entities/weblink-add-command"; import { loadConfigFromString } from "../../common/kube-helpers"; import type { OpenDeleteClusterDialog } from "../components/delete-cluster-dialog/open.injectable"; +import type { CatalogCategoryRegistry } from "../../common/catalog"; async function onClusterDelete(clusterId: string, openDeleteClusterDialog: OpenDeleteClusterDialog) { const cluster = ClusterStore.getInstance().getById(clusterId); @@ -31,9 +30,14 @@ async function onClusterDelete(clusterId: string, openDeleteClusterDialog: OpenD interface Dependencies { openCommandDialog: (component: React.ReactElement) => void; openDeleteClusterDialog: OpenDeleteClusterDialog; + catalogCategoryRegistry: CatalogCategoryRegistry; } -export function initCatalog({ openCommandDialog, openDeleteClusterDialog }: Dependencies) { +export function initCatalog({ + openCommandDialog, + openDeleteClusterDialog, + catalogCategoryRegistry, +}: Dependencies) { catalogCategoryRegistry .getForGroupKind("entity.k8slens.dev", "WebLink") ?.on("catalogAddMenu", ctx => {