From e948fc047c309fd40f56292efd25f190817756e9 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Tue, 13 Apr 2021 14:51:43 +0300 Subject: [PATCH] Allow register actions to "add to catalog" button (#2497) * registrable add-to-catalog button Signed-off-by: Jari Kolehmainen * cleanup Signed-off-by: Jari Kolehmainen * fix integration tests Signed-off-by: Jari Kolehmainen * fix integration tests Signed-off-by: Jari Kolehmainen --- integration/__tests__/cluster-pages.tests.ts | 3 +- integration/helpers/minikube.ts | 5 +- .../catalog-entities/kubernetes-cluster.ts | 16 +++- src/common/catalog-entity.ts | 5 ++ src/renderer/api/catalog-entity.ts | 10 ++- .../+catalog/catalog-add-button.scss | 9 +++ .../+catalog/catalog-add-button.tsx | 74 +++++++++++++++++++ .../+catalog/catalog-entity.store.ts | 2 - src/renderer/components/+catalog/catalog.tsx | 12 +-- 9 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 src/renderer/components/+catalog/catalog-add-button.scss create mode 100644 src/renderer/components/+catalog/catalog-add-button.tsx diff --git a/integration/__tests__/cluster-pages.tests.ts b/integration/__tests__/cluster-pages.tests.ts index 2d7807e22b..12d95f887c 100644 --- a/integration/__tests__/cluster-pages.tests.ts +++ b/integration/__tests__/cluster-pages.tests.ts @@ -387,10 +387,11 @@ describe("Lens cluster pages", () => { await new Promise(r => setTimeout(r, 1000)); } } - await new Promise(r => setTimeout(r, 500)); // Give some extra time to prepare extensions + // Open logs tab in dock await app.client.click(".list .TableRow:first-child"); await app.client.waitForVisible(".Drawer"); + await app.client.waitForVisible(`ul.KubeObjectMenu li.MenuItem i[title="Logs"]`); await app.client.click(".drawer-title .Menu li:nth-child(2)"); // Check if controls are available await app.client.waitForVisible(".LogList .VirtualList"); diff --git a/integration/helpers/minikube.ts b/integration/helpers/minikube.ts index 2c62279e4b..4c7120c4c5 100644 --- a/integration/helpers/minikube.ts +++ b/integration/helpers/minikube.ts @@ -39,7 +39,10 @@ export function minikubeReady(testNamespace: string): boolean { } export async function addMinikubeCluster(app: Application) { - await app.client.click("button.add-button"); + await app.client.waitForVisible("button.MuiSpeedDial-fab"); + await app.client.click("button.MuiSpeedDial-fab"); + await app.client.waitForVisible(`button[title="Add from kubeconfig"]`); + await app.client.click(`button[title="Add from kubeconfig"]`); await app.client.waitUntilTextExists("div", "Select kubeconfig file"); await app.client.click("div.Select__control"); // show the context drop-down list await app.client.waitUntilTextExists("div", "minikube"); diff --git a/src/common/catalog-entities/kubernetes-cluster.ts b/src/common/catalog-entities/kubernetes-cluster.ts index 78b99d3f5c..3354b9ba61 100644 --- a/src/common/catalog-entities/kubernetes-cluster.ts +++ b/src/common/catalog-entities/kubernetes-cluster.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "events"; import { observable } from "mobx"; import { catalogCategoryRegistry } from "../catalog-category-registry"; -import { CatalogCategory, CatalogEntity, CatalogEntityActionContext, CatalogEntityContextMenuContext, CatalogEntityData, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog-entity"; +import { CatalogCategory, CatalogEntity, CatalogEntityActionContext, CatalogEntityAddMenuContext, CatalogEntityContextMenuContext, CatalogEntityData, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog-entity"; import { clusterDisconnectHandler } from "../cluster-ipc"; import { clusterStore } from "../cluster-store"; import { requestMain } from "../ipc"; @@ -97,6 +97,20 @@ export class KubernetesClusterCategory extends EventEmitter implements CatalogCa } }; + constructor() { + super(); + + this.on("onCatalogAddMenu", (ctx: CatalogEntityAddMenuContext) => { + ctx.menuItems.push({ + icon: "text_snippet", + title: "Add from kubeconfig", + onClick: async () => { + ctx.navigate("/add-cluster"); + } + }); + }); + } + getId() { return `${this.spec.group}/${this.spec.names.kind}`; } diff --git a/src/common/catalog-entity.ts b/src/common/catalog-entity.ts index 8a00297d3c..ad3f0e591e 100644 --- a/src/common/catalog-entity.ts +++ b/src/common/catalog-entity.ts @@ -56,6 +56,11 @@ export interface CatalogEntityContextMenuContext { menuItems: CatalogEntityContextMenu[]; } +export interface CatalogEntityAddMenuContext { + navigate: (url: string) => void; + menuItems: CatalogEntityContextMenu[]; +} + export type CatalogEntityData = { apiVersion: string; kind: string; diff --git a/src/renderer/api/catalog-entity.ts b/src/renderer/api/catalog-entity.ts index a8006be0f7..ad82af10e6 100644 --- a/src/renderer/api/catalog-entity.ts +++ b/src/renderer/api/catalog-entity.ts @@ -2,7 +2,15 @@ import { navigate } from "../navigation"; import { commandRegistry } from "../../extensions/registries"; import { CatalogEntity } from "../../common/catalog-entity"; -export { CatalogEntity, CatalogEntityData, CatalogEntityActionContext, CatalogEntityContextMenu, CatalogEntityContextMenuContext } from "../../common/catalog-entity"; +export { + CatalogCategory, + CatalogEntity, + CatalogEntityData, + CatalogEntityActionContext, + CatalogEntityAddMenuContext, + CatalogEntityContextMenu, + CatalogEntityContextMenuContext +} from "../../common/catalog-entity"; export const catalogEntityRunContext = { navigate: (url: string) => navigate(url), diff --git a/src/renderer/components/+catalog/catalog-add-button.scss b/src/renderer/components/+catalog/catalog-add-button.scss new file mode 100644 index 0000000000..7377a60dfc --- /dev/null +++ b/src/renderer/components/+catalog/catalog-add-button.scss @@ -0,0 +1,9 @@ +.CatalogAddButton { + position: absolute; + right: 40px; + bottom: 30px; + + .MuiFab-primary { + background-color: var(--blue); + } +} diff --git a/src/renderer/components/+catalog/catalog-add-button.tsx b/src/renderer/components/+catalog/catalog-add-button.tsx new file mode 100644 index 0000000000..6da733af7c --- /dev/null +++ b/src/renderer/components/+catalog/catalog-add-button.tsx @@ -0,0 +1,74 @@ +import "./catalog-add-button.scss"; +import React from "react"; +import { SpeedDial, SpeedDialAction } from "@material-ui/lab"; +import { Icon } from "../icon"; +import { disposeOnUnmount, observer } from "mobx-react"; +import { observable, reaction } from "mobx"; +import { autobind } from "../../../common/utils"; +import { CatalogCategory, CatalogEntityAddMenuContext, CatalogEntityContextMenu } from "../../api/catalog-entity"; +import { EventEmitter } from "events"; +import { navigate } from "../../navigation"; + +export type CatalogAddButtonProps = { + category: CatalogCategory +}; + +@observer +export class CatalogAddButton extends React.Component { + @observable protected isOpen = false; + protected menuItems = observable.array([]); + + componentDidMount() { + disposeOnUnmount(this, [ + reaction(() => this.props.category, (category) => { + this.menuItems.clear(); + + if (category && category instanceof EventEmitter) { + const context: CatalogEntityAddMenuContext = { + navigate: (url: string) => navigate(url), + menuItems: this.menuItems + }; + + category.emit("onCatalogAddMenu", context); + } + }, { fireImmediately: true }) + ]); + } + + @autobind() + onOpen() { + this.isOpen = true; + } + + @autobind() + onClose() { + this.isOpen = false; + } + + render() { + if (this.menuItems.length === 0) { + return null; + } + + return ( + } + direction="up" + > + { this.menuItems.map((menuItem, index) => { + return } + tooltipTitle={menuItem.title} + onClick={() => menuItem.onClick()} + />; + })} + + ); + } +} diff --git a/src/renderer/components/+catalog/catalog-entity.store.ts b/src/renderer/components/+catalog/catalog-entity.store.ts index 2c867ca02b..49043fed70 100644 --- a/src/renderer/components/+catalog/catalog-entity.store.ts +++ b/src/renderer/components/+catalog/catalog-entity.store.ts @@ -61,8 +61,6 @@ export class CatalogEntityStore extends ItemStore { @computed get entities() { if (!this.activeCategory) return []; - console.log("computing entities", this.activeCategory); - return catalogEntityRegistry.getItemsForCategory(this.activeCategory).map(entity => new CatalogEntityItem(entity)); } diff --git a/src/renderer/components/+catalog/catalog.tsx b/src/renderer/components/+catalog/catalog.tsx index ebd17fd676..5cd0e918c1 100644 --- a/src/renderer/components/+catalog/catalog.tsx +++ b/src/renderer/components/+catalog/catalog.tsx @@ -2,7 +2,7 @@ import "./catalog.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { ItemListLayout } from "../item-object-list"; -import { observable, reaction } from "mobx"; +import { action, observable, reaction } from "mobx"; import { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store"; import { navigate } from "../../navigation"; import { kebabCase } from "lodash"; @@ -12,12 +12,12 @@ import { Icon } from "../icon"; import { CatalogEntityContextMenu, CatalogEntityContextMenuContext, catalogEntityRunContext } from "../../api/catalog-entity"; import { Badge } from "../badge"; import { hotbarStore } from "../../../common/hotbar-store"; -import { addClusterURL } from "../+add-cluster"; import { autobind } from "../../utils"; import { Notifications } from "../notifications"; import { ConfirmDialog } from "../confirm-dialog"; import { Tab, Tabs } from "../tabs"; import { catalogCategoryRegistry } from "../../../common/catalog-category-registry"; +import { CatalogAddButton } from "./catalog-add-button"; enum sortBy { name = "name", @@ -101,6 +101,7 @@ export class Catalog extends React.Component { return catalogCategoryRegistry.items; } + @action onTabChange = (tabId: string) => { this.activeTab = tabId; @@ -149,6 +150,7 @@ export class Catalog extends React.Component { ); } + render() { if (!this.catalogEntityStore) { return null; @@ -161,6 +163,7 @@ export class Catalog extends React.Component { provideBackButtonNavigation={false} contentGaps={false}> this.onDetails(item) } renderItemMenu={this.renderItemMenu} - addRemoveButtons={{ - addTooltip: "Add Kubernetes Cluster", - onAdd: () => navigate(addClusterURL()), - }} /> + ); }