mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add onRunHook extension api
Signed-off-by: Hung-Han (Henry) Chen <chenhungh@gmail.com>
This commit is contained in:
parent
0f63ccbb82
commit
cfdb4c93c1
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
import type { CatalogCategory, CatalogEntity } from "../../common/catalog";
|
import type { CatalogCategory, CatalogEntity } from "../../common/catalog";
|
||||||
import { catalogEntityRegistry as registry } from "../../renderer/api/catalog-entity-registry";
|
import { catalogEntityRegistry as registry } from "../../renderer/api/catalog-entity-registry";
|
||||||
|
import type { CatelogEntityOnRunHook } from "../../renderer/api/catalog-entity-registry";
|
||||||
export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog/catalog-category-registry";
|
export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog/catalog-category-registry";
|
||||||
|
|
||||||
export class CatalogEntityRegistry {
|
export class CatalogEntityRegistry {
|
||||||
@ -48,6 +48,33 @@ export class CatalogEntityRegistry {
|
|||||||
getItemsForCategory<T extends CatalogEntity>(category: CatalogCategory): T[] {
|
getItemsForCategory<T extends CatalogEntity>(category: CatalogCategory): T[] {
|
||||||
return registry.getItemsForCategory(category);
|
return registry.getItemsForCategory(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a onRun hook to a catalog entity.
|
||||||
|
* @param catalogEntityUid The uid of the catalog entity
|
||||||
|
* @param onRunHook The function that should return a boolean if the onRun of catalog entity should be triggered.
|
||||||
|
* @returns A function to remove that hook
|
||||||
|
*/
|
||||||
|
addOnRunHook(catalogEntityUid: CatalogEntity["metadata"]["uid"], onRunHook: CatelogEntityOnRunHook) {
|
||||||
|
return registry.addOnRunHook(catalogEntityUid, onRunHook);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns one catalog entity onRun hook by catalog entity uid
|
||||||
|
*/
|
||||||
|
getOnRunHook(catalogEntityUid: CatalogEntity["metadata"]["uid"]): CatelogEntityOnRunHook | undefined {
|
||||||
|
return registry.getOnRunHook(catalogEntityUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all catalog entities' onRun hooks
|
||||||
|
*/
|
||||||
|
getAllOnRunHooks(): Array<{
|
||||||
|
catalogEntityUid: CatalogEntity["metadata"]["uid"];
|
||||||
|
onRunHook: CatelogEntityOnRunHook;
|
||||||
|
}> {
|
||||||
|
return registry.getAllOnRunHooks();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const catalogEntities = new CatalogEntityRegistry();
|
export const catalogEntities = new CatalogEntityRegistry();
|
||||||
|
|||||||
@ -27,8 +27,12 @@ import type { Cluster } from "../../main/cluster";
|
|||||||
import { ClusterStore } from "../../common/cluster-store";
|
import { ClusterStore } from "../../common/cluster-store";
|
||||||
import { Disposer, iter } from "../utils";
|
import { Disposer, iter } from "../utils";
|
||||||
import { once } from "lodash";
|
import { once } from "lodash";
|
||||||
|
import type { CatalogEntityItem } from "../../renderer/components/+catalog/catalog-entity-item"
|
||||||
|
|
||||||
export type EntityFilter = (entity: CatalogEntity) => any;
|
export type EntityFilter = (entity: CatalogEntity) => any;
|
||||||
|
export type CatelogEntityOnRunHook = (entity: CatalogEntity | CatalogEntityItem<CatalogEntity>) => boolean | Promise<boolean>;
|
||||||
|
|
||||||
|
type CatalogEntityUid = CatalogEntity["metadata"]["uid"];
|
||||||
|
|
||||||
export class CatalogEntityRegistry {
|
export class CatalogEntityRegistry {
|
||||||
@observable protected activeEntityId: string | undefined = undefined;
|
@observable protected activeEntityId: string | undefined = undefined;
|
||||||
@ -36,6 +40,12 @@ export class CatalogEntityRegistry {
|
|||||||
protected filters = observable.set<EntityFilter>([], {
|
protected filters = observable.set<EntityFilter>([], {
|
||||||
deep: false,
|
deep: false,
|
||||||
});
|
});
|
||||||
|
protected entityOnRunHooks = observable.set<{
|
||||||
|
catalogEntityUid: CatalogEntityUid;
|
||||||
|
onRunHook: CatelogEntityOnRunHook
|
||||||
|
}>([], {
|
||||||
|
deep: false,
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer for keeping entities that don't yet have CatalogCategory synced
|
* Buffer for keeping entities that don't yet have CatalogCategory synced
|
||||||
@ -169,6 +179,41 @@ export class CatalogEntityRegistry {
|
|||||||
|
|
||||||
return once(() => void this.filters.delete(fn));
|
return once(() => void this.filters.delete(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a onRun hook to a catalog entity.
|
||||||
|
* @param uid The uid of the catalog entity
|
||||||
|
* @param onRunHook The function that should return a boolean if the onRun of catalog entity should be triggered.
|
||||||
|
* @returns A function to remove that hook
|
||||||
|
*/
|
||||||
|
addOnRunHook(catalogEntityUid: CatalogEntityUid, onRunHook: CatelogEntityOnRunHook): Disposer {
|
||||||
|
this.entityOnRunHooks.add({
|
||||||
|
catalogEntityUid,
|
||||||
|
onRunHook,
|
||||||
|
});
|
||||||
|
|
||||||
|
return once(() => void this.entityOnRunHooks.delete({
|
||||||
|
catalogEntityUid,
|
||||||
|
onRunHook,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns one catalog entity onRun hook by catalog entity uid
|
||||||
|
*/
|
||||||
|
getOnRunHook(_catalogEntityUid: CatalogEntityUid): CatelogEntityOnRunHook | undefined {
|
||||||
|
return Array.from(this.entityOnRunHooks).find(({ catalogEntityUid }) => catalogEntityUid === _catalogEntityUid)?.onRunHook;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all catalog entities' onRun hooks
|
||||||
|
*/
|
||||||
|
getAllOnRunHooks(): Array<{
|
||||||
|
catalogEntityUid: CatalogEntityUid;
|
||||||
|
onRunHook: CatelogEntityOnRunHook;
|
||||||
|
}> {
|
||||||
|
return Array.from(this.entityOnRunHooks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry);
|
export const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry);
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import "./catalog-entity-details.scss";
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Drawer, DrawerItem } from "../drawer";
|
import { Drawer, DrawerItem } from "../drawer";
|
||||||
import { catalogEntityRunContext } from "../../api/catalog-entity";
|
|
||||||
import type { CatalogCategory, CatalogEntity } from "../../../common/catalog";
|
import type { CatalogCategory, CatalogEntity } from "../../../common/catalog";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { CatalogEntityDrawerMenu } from "./catalog-entity-drawer-menu";
|
import { CatalogEntityDrawerMenu } from "./catalog-entity-drawer-menu";
|
||||||
@ -35,6 +34,7 @@ import { isDevelopment } from "../../../common/vars";
|
|||||||
interface Props<T extends CatalogEntity> {
|
interface Props<T extends CatalogEntity> {
|
||||||
item: CatalogEntityItem<T> | null | undefined;
|
item: CatalogEntityItem<T> | null | undefined;
|
||||||
hideDetails(): void;
|
hideDetails(): void;
|
||||||
|
onClickDetailPanelIcon: (catalogEntitiyItem: CatalogEntityItem<T>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -69,7 +69,7 @@ export class CatalogEntityDetails<T extends CatalogEntity> extends Component<Pro
|
|||||||
background={item.entity.spec.icon?.background}
|
background={item.entity.spec.icon?.background}
|
||||||
disabled={!item?.enabled}
|
disabled={!item?.enabled}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
item.onRun(catalogEntityRunContext);
|
this.props.onClickDetailPanelIcon(item);
|
||||||
}}
|
}}
|
||||||
size={128}
|
size={128}
|
||||||
data-testid="detail-panel-hot-bar-icon"
|
data-testid="detail-panel-hot-bar-icon"
|
||||||
|
|||||||
@ -22,12 +22,14 @@ import styles from "./catalog.module.css";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { action, computed } from "mobx";
|
import { action, computed } from "mobx";
|
||||||
import type { CatalogEntity, CatalogEntityActionContext } from "../../api/catalog-entity";
|
import type { CatalogEntity, CatalogEntityActionContext } from "../../api/catalog-entity";
|
||||||
|
import type { CatelogEntityOnRunHook } from "../../api/catalog-entity-registry";
|
||||||
import type { ItemObject } from "../../../common/item.store";
|
import type { ItemObject } from "../../../common/item.store";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { navigation } from "../../navigation";
|
import { navigation } from "../../navigation";
|
||||||
import { searchUrlParam } from "../input";
|
import { searchUrlParam } from "../input";
|
||||||
import { makeCss } from "../../../common/utils/makeCss";
|
import { makeCss } from "../../../common/utils/makeCss";
|
||||||
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||||
|
import { toJS } from "mobx";
|
||||||
|
|
||||||
const css = makeCss(styles);
|
const css = makeCss(styles);
|
||||||
|
|
||||||
@ -102,8 +104,20 @@ export class CatalogEntityItem<T extends CatalogEntity> implements ItemObject {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
onRun(ctx: CatalogEntityActionContext) {
|
onRun(onRunHook: CatelogEntityOnRunHook | undefined, ctx: CatalogEntityActionContext) {
|
||||||
this.entity.onRun(ctx);
|
if (!onRunHook) {
|
||||||
|
this.entity.onRun(ctx);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof onRunHook === "function") {
|
||||||
|
// if onRunHook() returns a Promise, we wait for it to resolve
|
||||||
|
// if not, just take whatever it returns
|
||||||
|
Promise.resolve(onRunHook(toJS(this.entity))).then((shouldRun) => {
|
||||||
|
if (shouldRun) this.entity.onRun(ctx);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
import { computed, IReactionDisposer, makeObservable, observable, reaction } from "mobx";
|
import { computed, IReactionDisposer, makeObservable, observable, reaction } from "mobx";
|
||||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||||
import type { CatalogEntity } from "../../api/catalog-entity";
|
import type { CatalogEntity } from "../../api/catalog-entity";
|
||||||
|
import type { CatelogEntityOnRunHook } from "../../api/catalog-entity-registry";
|
||||||
import { ItemStore } from "../../../common/item.store";
|
import { ItemStore } from "../../../common/item.store";
|
||||||
import { CatalogCategory, catalogCategoryRegistry } from "../../../common/catalog";
|
import { CatalogCategory, catalogCategoryRegistry } from "../../../common/catalog";
|
||||||
import { autoBind } from "../../../common/utils";
|
import { autoBind } from "../../../common/utils";
|
||||||
@ -49,6 +50,10 @@ export class CatalogEntityStore extends ItemStore<CatalogEntityItem<CatalogEntit
|
|||||||
return this.entities.find(e => e.getId() === this.selectedItemId);
|
return this.entities.find(e => e.getId() === this.selectedItemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCatalogEntityOnRunHook(catalogEntityUid: CatalogEntity["metadata"]["uid"]): CatelogEntityOnRunHook | undefined {
|
||||||
|
return catalogEntityRegistry.getOnRunHook(catalogEntityUid);
|
||||||
|
}
|
||||||
|
|
||||||
watch() {
|
watch() {
|
||||||
const disposers: IReactionDisposer[] = [
|
const disposers: IReactionDisposer[] = [
|
||||||
reaction(() => this.entities, () => this.loadAll()),
|
reaction(() => this.entities, () => this.loadAll()),
|
||||||
|
|||||||
160
src/renderer/components/+catalog/catalog.test.tsx
Normal file
160
src/renderer/components/+catalog/catalog.test.tsx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
import { Catalog } from "./catalog";
|
||||||
|
import { createMemoryHistory } from "history";
|
||||||
|
import { mockWindow } from "../../../../__mocks__/windowMock";
|
||||||
|
import { kubernetesClusterCategory } from "../../../common/catalog-entities/kubernetes-cluster";
|
||||||
|
import { catalogCategoryRegistry, CatalogEntity } from "../../../common/catalog";
|
||||||
|
import { catalogEntityRegistry } from "../../../renderer/api/catalog-entity-registry";
|
||||||
|
import { CatalogEntityDetailRegistry } from "../../../extensions/registries";
|
||||||
|
import { CatalogEntityItem } from "./catalog-entity-item";
|
||||||
|
import { CatalogEntityStore } from "./catalog-entity.store";
|
||||||
|
|
||||||
|
mockWindow();
|
||||||
|
|
||||||
|
const isCatalogEntityItem = (entity: any): entity is CatalogEntityItem<CatalogEntity> => typeof entity.enable === "boolean";
|
||||||
|
|
||||||
|
// avoid TypeError: Cannot read property 'getPath' of undefined
|
||||||
|
jest.mock("@electron/remote", () => {
|
||||||
|
return {
|
||||||
|
app: {
|
||||||
|
getPath: () => {
|
||||||
|
// avoid TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("<Catalog />", () => {
|
||||||
|
const history = createMemoryHistory();
|
||||||
|
const mockLocation = {
|
||||||
|
pathname: "",
|
||||||
|
search: "",
|
||||||
|
state: "",
|
||||||
|
hash: "",
|
||||||
|
};
|
||||||
|
const mockMatch = {
|
||||||
|
params: {
|
||||||
|
// will be used to match activeCategory
|
||||||
|
// need to be the same as property values in kubernetesClusterCategory
|
||||||
|
group: "entity.k8slens.dev",
|
||||||
|
kind: "KubernetesCluster",
|
||||||
|
},
|
||||||
|
isExact: true,
|
||||||
|
path: "",
|
||||||
|
url: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const catalogEntityUid = "a_catalogEntity_uid";
|
||||||
|
const catalogEntity = {
|
||||||
|
enabled: true,
|
||||||
|
apiVersion: "api",
|
||||||
|
kind: "kind",
|
||||||
|
metadata: {
|
||||||
|
uid: catalogEntityUid,
|
||||||
|
name: "a catalog entity",
|
||||||
|
labels: {
|
||||||
|
test: "label",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
phase: "",
|
||||||
|
},
|
||||||
|
spec: {},
|
||||||
|
};
|
||||||
|
const catalogEntityItemMethods = {
|
||||||
|
getId: () => "",
|
||||||
|
getName: () => "",
|
||||||
|
onContextMenuOpen: () => {},
|
||||||
|
onSettingsOpen: () => {},
|
||||||
|
onRun: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
CatalogEntityDetailRegistry.createInstance();
|
||||||
|
// mock the return of getting CatalogCategoryRegistry.filteredItems
|
||||||
|
jest
|
||||||
|
.spyOn(catalogCategoryRegistry, "filteredItems", "get")
|
||||||
|
.mockImplementation(() => {
|
||||||
|
return [kubernetesClusterCategory];
|
||||||
|
});
|
||||||
|
|
||||||
|
// we don't care what this.renderList renders in this test case.
|
||||||
|
jest.spyOn(Catalog.prototype, "renderList").mockImplementation(() => {
|
||||||
|
return <span>empty renderList</span>;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
CatalogEntityDetailRegistry.resetInstance();
|
||||||
|
jest.clearAllMocks();
|
||||||
|
jest.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can use catalogEntityRegistry.addOnRunHook to add hooks for catalog entities", (done) => {
|
||||||
|
const catalogEntityItem = new CatalogEntityItem({
|
||||||
|
...catalogEntity,
|
||||||
|
...catalogEntityItemMethods,
|
||||||
|
});
|
||||||
|
|
||||||
|
// mock as if there is a selected item > the detail panel opens
|
||||||
|
jest
|
||||||
|
.spyOn(CatalogEntityStore.prototype, "selectedItem", "get")
|
||||||
|
.mockImplementation(() => {
|
||||||
|
return catalogEntityItem;
|
||||||
|
});
|
||||||
|
|
||||||
|
let hookGetCalled = false;
|
||||||
|
|
||||||
|
catalogEntityRegistry.addOnRunHook(catalogEntityUid, (entity) => {
|
||||||
|
hookGetCalled = true;
|
||||||
|
expect(hookGetCalled).toBe(true);
|
||||||
|
|
||||||
|
expect(entity.apiVersion).toBe(catalogEntity.apiVersion);
|
||||||
|
expect(entity.kind).toBe(catalogEntity.kind);
|
||||||
|
|
||||||
|
if (isCatalogEntityItem(entity)) {
|
||||||
|
expect(entity.enabled).toBe(catalogEntity.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCatalogEntityItem(entity)) {
|
||||||
|
expect(entity.metadata).toBe(catalogEntity.metadata);
|
||||||
|
expect(entity.status).toBe(catalogEntity.status);
|
||||||
|
expect(entity.spec).toBe(catalogEntity.spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
render(
|
||||||
|
<Catalog history={history} location={mockLocation} match={mockMatch} />
|
||||||
|
);
|
||||||
|
|
||||||
|
userEvent.click(screen.getByTestId("detail-panel-hot-bar-icon"));
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -127,10 +127,18 @@ export class Catalog extends React.Component<Props> {
|
|||||||
if (this.catalogEntityStore.selectedItemId) {
|
if (this.catalogEntityStore.selectedItemId) {
|
||||||
this.catalogEntityStore.selectedItemId = null;
|
this.catalogEntityStore.selectedItemId = null;
|
||||||
} else {
|
} else {
|
||||||
item.onRun(catalogEntityRunContext);
|
const onRunHook = this.catalogEntityStore.getCatalogEntityOnRunHook(item.entity.metadata.uid);
|
||||||
|
|
||||||
|
item.onRun(onRunHook, catalogEntityRunContext);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onClickDetailPanelIcon = (item: CatalogEntityItem<CatalogEntity>) => {
|
||||||
|
const onRunHook = this.catalogEntityStore.getCatalogEntityOnRunHook(item.entity.metadata.uid);
|
||||||
|
|
||||||
|
item.onRun(onRunHook, catalogEntityRunContext);
|
||||||
|
};
|
||||||
|
|
||||||
onMenuItemClick(menuItem: CatalogEntityContextMenu) {
|
onMenuItemClick(menuItem: CatalogEntityContextMenu) {
|
||||||
if (menuItem.confirm) {
|
if (menuItem.confirm) {
|
||||||
ConfirmDialog.open({
|
ConfirmDialog.open({
|
||||||
@ -276,6 +284,7 @@ export class Catalog extends React.Component<Props> {
|
|||||||
? <CatalogEntityDetails
|
? <CatalogEntityDetails
|
||||||
item={this.catalogEntityStore.selectedItem}
|
item={this.catalogEntityStore.selectedItem}
|
||||||
hideDetails={() => this.catalogEntityStore.selectedItemId = null}
|
hideDetails={() => this.catalogEntityStore.selectedItemId = null}
|
||||||
|
onClickDetailPanelIcon={this.onClickDetailPanelIcon}
|
||||||
/>
|
/>
|
||||||
: (
|
: (
|
||||||
<RenderDelay>
|
<RenderDelay>
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import { observer } from "mobx-react";
|
|||||||
import { HotbarEntityIcon } from "./hotbar-entity-icon";
|
import { HotbarEntityIcon } from "./hotbar-entity-icon";
|
||||||
import { cssNames, IClassName } from "../../utils";
|
import { cssNames, IClassName } from "../../utils";
|
||||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||||
|
import type { CatelogEntityOnRunHook} from "../../api/catalog-entity-registry";
|
||||||
import { HotbarStore } from "../../../common/hotbar-store";
|
import { HotbarStore } from "../../../common/hotbar-store";
|
||||||
import { CatalogEntity, catalogEntityRunContext } from "../../api/catalog-entity";
|
import { CatalogEntity, catalogEntityRunContext } from "../../api/catalog-entity";
|
||||||
import { DragDropContext, Draggable, Droppable, DropResult } from "react-beautiful-dnd";
|
import { DragDropContext, Draggable, Droppable, DropResult } from "react-beautiful-dnd";
|
||||||
@ -33,6 +34,7 @@ import { HotbarSelector } from "./hotbar-selector";
|
|||||||
import { HotbarCell } from "./hotbar-cell";
|
import { HotbarCell } from "./hotbar-cell";
|
||||||
import { HotbarIcon } from "./hotbar-icon";
|
import { HotbarIcon } from "./hotbar-icon";
|
||||||
import { defaultHotbarCells, HotbarItem } from "../../../common/hotbar-types";
|
import { defaultHotbarCells, HotbarItem } from "../../../common/hotbar-types";
|
||||||
|
import { toJS } from "mobx";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: IClassName;
|
className?: IClassName;
|
||||||
@ -54,6 +56,10 @@ export class HotbarMenu extends React.Component<Props> {
|
|||||||
return catalogEntityRegistry.getById(item?.entity.uid) ?? null;
|
return catalogEntityRegistry.getById(item?.entity.uid) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEntityOnRunHook(uid: string): CatelogEntityOnRunHook | undefined {
|
||||||
|
return catalogEntityRegistry.getOnRunHook(uid);
|
||||||
|
}
|
||||||
|
|
||||||
onDragEnd(result: DropResult) {
|
onDragEnd(result: DropResult) {
|
||||||
const { source, destination } = result;
|
const { source, destination } = result;
|
||||||
|
|
||||||
@ -124,7 +130,23 @@ export class HotbarMenu extends React.Component<Props> {
|
|||||||
key={index}
|
key={index}
|
||||||
index={index}
|
index={index}
|
||||||
entity={entity}
|
entity={entity}
|
||||||
onClick={() => entity.onRun(catalogEntityRunContext)}
|
onClick={() => {
|
||||||
|
const onRunHook = this.getEntityOnRunHook(entity.metadata.uid);
|
||||||
|
|
||||||
|
if (!onRunHook) {
|
||||||
|
entity.onRun(catalogEntityRunContext);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof onRunHook === "function") {
|
||||||
|
// if onRunHook() returns a Promise, we wait for it to resolve
|
||||||
|
// if not, just take whatever it returns
|
||||||
|
Promise.resolve(onRunHook(toJS(entity))).then((shouldRun) => {
|
||||||
|
if (shouldRun) entity.onRun(catalogEntityRunContext);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
className={cssNames({ isDragging: snapshot.isDragging })}
|
className={cssNames({ isDragging: snapshot.isDragging })}
|
||||||
remove={this.removeItem}
|
remove={this.removeItem}
|
||||||
add={this.addItem}
|
add={this.addItem}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user