diff --git a/src/common/catalog/catalog-entity.ts b/src/common/catalog/catalog-entity.ts index d59a21686c..593a921e72 100644 --- a/src/common/catalog/catalog-entity.ts +++ b/src/common/catalog/catalog-entity.ts @@ -230,7 +230,7 @@ export abstract class CatalogEntity< return this.metadata.name; } - public abstract onRun?(context: CatalogEntityActionContext): void | Promise; + public abstract onRun(context: CatalogEntityActionContext): void | Promise; public abstract onContextMenuOpen(context: CatalogEntityContextMenuContext): void | Promise; public abstract onSettingsOpen(context: CatalogEntitySettingsContext): void | Promise; } diff --git a/src/extensions/renderer-api/catalog.ts b/src/extensions/renderer-api/catalog.ts index 675abb42e6..e80533d0c3 100644 --- a/src/extensions/renderer-api/catalog.ts +++ b/src/extensions/renderer-api/catalog.ts @@ -23,6 +23,7 @@ import type { CatalogCategory, CatalogEntity } from "../../common/catalog"; import { catalogEntityRegistry as registry } from "../../renderer/api/catalog-entity-registry"; import type { CatalogEntityOnBeforeRun } from "../../renderer/api/catalog-entity-registry"; +import type { Disposer } from "../../common/utils"; export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog/catalog-category-registry"; export class CatalogEntityRegistry { @@ -50,21 +51,14 @@ export class CatalogEntityRegistry { } /** - * Add a onBeforeRun hook to a catalog entity. + * Add a onRun hook to a catalog entity. If `onBeforeRun` was previously added then it will not be added again * @param catalogEntityUid The uid of the catalog entity - * @param onBeforeRun The function that should return a boolean if the onBeforeRun of catalog entity should be triggered. + * @param onBeforeRun The function that should return a boolean if the onRun of catalog entity should be triggered. * @returns A function to remove that hook */ - addOnBeforeRun(entity: CatalogEntity, onBeforeRun: CatalogEntityOnBeforeRun) { + addOnBeforeRun(entity: CatalogEntity, onBeforeRun: CatalogEntityOnBeforeRun): Disposer { return registry.addOnBeforeRun(entity, onBeforeRun); } - - /** - * Returns one catalog entity onBeforeRun by catalog entity uid - */ - onBeforeRun(entity: CatalogEntity): Promise { - return registry.onBeforeRun(entity); - } } export const catalogEntities = new CatalogEntityRegistry(); diff --git a/src/renderer/api/catalog-entity-registry.ts b/src/renderer/api/catalog-entity-registry.ts index f70599791d..999ee7a09e 100644 --- a/src/renderer/api/catalog-entity-registry.ts +++ b/src/renderer/api/catalog-entity-registry.ts @@ -229,6 +229,10 @@ export class CatalogEntityRegistry { return true; } + /** + * Perform the onBeforeRun check and, if successful, then proceed to call `entity`'s onRun method + * @param entity The instance to invoke the hooks and then execute the onRun + */ onRun(entity: CatalogEntity): void { this.onBeforeRun(entity) .then(doOnRun => { diff --git a/src/renderer/components/+catalog/catalog-entity-details.tsx b/src/renderer/components/+catalog/catalog-entity-details.tsx index 4e6eaae86c..bff73a3fa2 100644 --- a/src/renderer/components/+catalog/catalog-entity-details.tsx +++ b/src/renderer/components/+catalog/catalog-entity-details.tsx @@ -34,7 +34,6 @@ import { isDevelopment } from "../../../common/vars"; interface Props { item: CatalogEntityItem | null | undefined; hideDetails(): void; - onClickDetailPanelIcon: (catalogEntitiyItem: CatalogEntityItem) => void; } @observer @@ -68,9 +67,7 @@ export class CatalogEntityDetails extends Component { - this.props.onClickDetailPanelIcon(item); - }} + onClick={() => item.onRun()} size={128} data-testid="detail-panel-hot-bar-icon" /> diff --git a/src/renderer/components/+catalog/catalog-entity-item.tsx b/src/renderer/components/+catalog/catalog-entity-item.tsx index 5ed01aded6..b16406758f 100644 --- a/src/renderer/components/+catalog/catalog-entity-item.tsx +++ b/src/renderer/components/+catalog/catalog-entity-item.tsx @@ -21,18 +21,19 @@ import styles from "./catalog.module.css"; import React from "react"; import { action, computed } from "mobx"; -import type { CatalogEntity, CatalogEntityActionContext } from "../../api/catalog-entity"; +import type { CatalogEntity } from "../../api/catalog-entity"; import type { ItemObject } from "../../../common/item.store"; import { Badge } from "../badge"; import { navigation } from "../../navigation"; import { searchUrlParam } from "../input"; import { makeCss } from "../../../common/utils/makeCss"; import { KubeObject } from "../../../common/k8s-api/kube-object"; +import type { CatalogEntityRegistry } from "../../api/catalog-entity-registry"; const css = makeCss(styles); export class CatalogEntityItem implements ItemObject { - constructor(public entity: T) {} + constructor(public entity: T, private registry: CatalogEntityRegistry) {} get kind() { return this.entity.kind; @@ -102,8 +103,8 @@ export class CatalogEntityItem implements ItemObject { ]; } - onRun(ctx: CatalogEntityActionContext) { - this.entity.onRun(ctx); + onRun() { + this.registry.onRun(this.entity); } @action diff --git a/src/renderer/components/+catalog/catalog-entity.store.tsx b/src/renderer/components/+catalog/catalog-entity.store.tsx index b15e82353d..8bbc335010 100644 --- a/src/renderer/components/+catalog/catalog-entity.store.tsx +++ b/src/renderer/components/+catalog/catalog-entity.store.tsx @@ -39,20 +39,16 @@ export class CatalogEntityStore extends ItemStore new CatalogEntityItem(entity)); + return this.registry.filteredItems.map(entity => new CatalogEntityItem(entity, this.registry)); } - return this.registry.getItemsForCategory(this.activeCategory, { filtered: true }).map(entity => new CatalogEntityItem(entity)); + return this.registry.getItemsForCategory(this.activeCategory, { filtered: true }).map(entity => new CatalogEntityItem(entity, this.registry)); } @computed get selectedItem() { return this.entities.find(e => e.getId() === this.selectedItemId); } - onRun(entity: CatalogEntity): void { - this.registry.onRun(entity); - } - watch() { return disposer( reaction(() => this.entities, () => this.loadAll()), diff --git a/src/renderer/components/+catalog/catalog-menu.tsx b/src/renderer/components/+catalog/catalog-menu.tsx index 9285fe16ce..b2d013dfcd 100644 --- a/src/renderer/components/+catalog/catalog-menu.tsx +++ b/src/renderer/components/+catalog/catalog-menu.tsx @@ -41,11 +41,15 @@ function getCategories() { } function getCategoryIcon(category: CatalogCategory) { - if (!category.metadata?.icon) return null; + const { icon } = category.metadata ?? {}; - return category.metadata.icon.includes?.(" - : ; + if (typeof icon === "string") { + return icon.includes(" + : ; + } + + return null; } function Item(props: TreeItemProps) { diff --git a/src/renderer/components/+catalog/catalog.test.tsx b/src/renderer/components/+catalog/catalog.test.tsx index 763398d1eb..ac510d8fb4 100644 --- a/src/renderer/components/+catalog/catalog.test.tsx +++ b/src/renderer/components/+catalog/catalog.test.tsx @@ -113,16 +113,15 @@ describe("", () => { }); it("can use catalogEntityRegistry.addOnBeforeRun to add hooks for catalog entities", (done) => { + const catalogCategoryRegistry = new CatalogCategoryRegistry(); + const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); + const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); const onRun = jest.fn(); const catalogEntityItem = new CatalogEntityItem({ ...catalogEntity, ...catalogEntityItemMethods, onRun, - }); - - const catalogCategoryRegistry = new CatalogCategoryRegistry(); - const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); - const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + }, catalogEntityRegistry); // mock as if there is a selected item > the detail panel opens jest @@ -178,16 +177,15 @@ describe("", () => { }); it("onBeforeRun return false => onRun wont be triggered", (done) => { + const catalogCategoryRegistry = new CatalogCategoryRegistry(); + const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); + const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); const onRun = jest.fn(); const catalogEntityItem = new CatalogEntityItem({ ...catalogEntity, ...catalogEntityItemMethods, onRun, - }); - - const catalogCategoryRegistry = new CatalogCategoryRegistry(); - const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); - const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + }, catalogEntityRegistry); // mock as if there is a selected item > the detail panel opens jest @@ -219,16 +217,15 @@ describe("", () => { }); it("addOnBeforeRun throw an exception => onRun wont be triggered", (done) => { + const catalogCategoryRegistry = new CatalogCategoryRegistry(); + const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); + const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); const onRun = jest.fn(); const catalogEntityItem = new CatalogEntityItem({ ...catalogEntity, ...catalogEntityItemMethods, onRun, - }); - - const catalogCategoryRegistry = new CatalogCategoryRegistry(); - const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); - const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + }, catalogEntityRegistry); // mock as if there is a selected item > the detail panel opens jest @@ -260,21 +257,15 @@ describe("", () => { }); it("addOnRunHook return a promise and resolve true => onRun()", (done) => { - let onRunTriggered = false; - const onRun = () => { - onRunTriggered = true; - expect(onRunTriggered).toBeTruthy(); - done(); - }; + const catalogCategoryRegistry = new CatalogCategoryRegistry(); + const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); + const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + const onRun = jest.fn(() => done()); const catalogEntityItem = new CatalogEntityItem({ ...catalogEntity, ...catalogEntityItemMethods, onRun, - }); - - const catalogCategoryRegistry = new CatalogCategoryRegistry(); - const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); - const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + }, catalogEntityRegistry); // mock as if there is a selected item > the detail panel opens jest @@ -301,19 +292,15 @@ describe("", () => { }); it("addOnRunHook return a promise and resolve false => onRun() wont be triggered", (done) => { - let onRunTriggered = false; - const onRun = () => { - onRunTriggered = true; - }; + const catalogCategoryRegistry = new CatalogCategoryRegistry(); + const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); + const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + const onRun = jest.fn(); const catalogEntityItem = new CatalogEntityItem({ ...catalogEntity, ...catalogEntityItemMethods, onRun, - }); - - const catalogCategoryRegistry = new CatalogCategoryRegistry(); - const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); - const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + }, catalogEntityRegistry); // mock as if there is a selected item > the detail panel opens jest @@ -323,10 +310,10 @@ describe("", () => { catalogEntityRegistry.addOnBeforeRun( catalogEntityUid, async () => { - expect(onRunTriggered).toBeFalsy(); + expect(onRun).not.toBeCalled(); setTimeout(() => { - expect(onRunTriggered).toBeFalsy(); + expect(onRun).not.toBeCalled(); done(); }, 500); @@ -347,16 +334,15 @@ describe("", () => { }); it("addOnRunHook return a promise and reject => onRun wont be triggered", (done) => { + const catalogCategoryRegistry = new CatalogCategoryRegistry(); + const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); + const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); const onRun = jest.fn(); const catalogEntityItem = new CatalogEntityItem({ ...catalogEntity, ...catalogEntityItemMethods, onRun, - }); - - const catalogCategoryRegistry = new CatalogCategoryRegistry(); - const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); - const catalogEntityStore = new CatalogEntityStore(catalogEntityRegistry); + }, catalogEntityRegistry); // mock as if there is a selected item > the detail panel opens jest diff --git a/src/renderer/components/+catalog/catalog.tsx b/src/renderer/components/+catalog/catalog.tsx index e908931f25..5a479d437d 100644 --- a/src/renderer/components/+catalog/catalog.tsx +++ b/src/renderer/components/+catalog/catalog.tsx @@ -133,14 +133,10 @@ export class Catalog extends React.Component { if (this.catalogEntityStore.selectedItemId) { this.catalogEntityStore.selectedItemId = null; } else { - this.catalogEntityStore.onRun(item.entity); + item.onRun(); } }; - onClickDetailPanelIcon = (item: CatalogEntityItem) => { - this.catalogEntityStore.onRun(item.entity); - }; - onMenuItemClick(menuItem: CatalogEntityContextMenu) { if (menuItem.confirm) { ConfirmDialog.open({ @@ -286,7 +282,6 @@ export class Catalog extends React.Component { ? this.catalogEntityStore.selectedItemId = null} - onClickDetailPanelIcon={this.onClickDetailPanelIcon} /> : ( diff --git a/src/renderer/components/activate-entity-command/activate-entity-command.tsx b/src/renderer/components/activate-entity-command/activate-entity-command.tsx index 110afd6b3c..f0b06769d8 100644 --- a/src/renderer/components/activate-entity-command/activate-entity-command.tsx +++ b/src/renderer/components/activate-entity-command/activate-entity-command.tsx @@ -22,7 +22,7 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; import React from "react"; -import { CatalogEntity, catalogEntityRunContext } from "../../api/catalog-entity"; +import type { CatalogEntity } from "../../api/catalog-entity"; import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; import { CommandOverlay } from "../command-palette"; import { Select } from "../select"; @@ -37,7 +37,7 @@ export class ActivateEntityCommand extends React.Component { } onSelect(entity: CatalogEntity): void { - entity.onRun?.(catalogEntityRunContext); + catalogEntityRegistry.onRun(entity); CommandOverlay.close(); }