1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Allow register actions to "add to catalog" button (#2497)

* registrable add-to-catalog button

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* cleanup

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix integration tests

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix integration tests

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen 2021-04-13 14:51:43 +03:00 committed by GitHub
parent b852384e85
commit e948fc047c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 12 deletions

View File

@ -387,10 +387,11 @@ describe("Lens cluster pages", () => {
await new Promise(r => setTimeout(r, 1000)); 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 // Open logs tab in dock
await app.client.click(".list .TableRow:first-child"); await app.client.click(".list .TableRow:first-child");
await app.client.waitForVisible(".Drawer"); 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)"); await app.client.click(".drawer-title .Menu li:nth-child(2)");
// Check if controls are available // Check if controls are available
await app.client.waitForVisible(".LogList .VirtualList"); await app.client.waitForVisible(".LogList .VirtualList");

View File

@ -39,7 +39,10 @@ export function minikubeReady(testNamespace: string): boolean {
} }
export async function addMinikubeCluster(app: Application) { 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.waitUntilTextExists("div", "Select kubeconfig file");
await app.client.click("div.Select__control"); // show the context drop-down list await app.client.click("div.Select__control"); // show the context drop-down list
await app.client.waitUntilTextExists("div", "minikube"); await app.client.waitUntilTextExists("div", "minikube");

View File

@ -1,7 +1,7 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { observable } from "mobx"; import { observable } from "mobx";
import { catalogCategoryRegistry } from "../catalog-category-registry"; 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 { clusterDisconnectHandler } from "../cluster-ipc";
import { clusterStore } from "../cluster-store"; import { clusterStore } from "../cluster-store";
import { requestMain } from "../ipc"; 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() { getId() {
return `${this.spec.group}/${this.spec.names.kind}`; return `${this.spec.group}/${this.spec.names.kind}`;
} }

View File

@ -56,6 +56,11 @@ export interface CatalogEntityContextMenuContext {
menuItems: CatalogEntityContextMenu[]; menuItems: CatalogEntityContextMenu[];
} }
export interface CatalogEntityAddMenuContext {
navigate: (url: string) => void;
menuItems: CatalogEntityContextMenu[];
}
export type CatalogEntityData = { export type CatalogEntityData = {
apiVersion: string; apiVersion: string;
kind: string; kind: string;

View File

@ -2,7 +2,15 @@ import { navigate } from "../navigation";
import { commandRegistry } from "../../extensions/registries"; import { commandRegistry } from "../../extensions/registries";
import { CatalogEntity } from "../../common/catalog-entity"; 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 = { export const catalogEntityRunContext = {
navigate: (url: string) => navigate(url), navigate: (url: string) => navigate(url),

View File

@ -0,0 +1,9 @@
.CatalogAddButton {
position: absolute;
right: 40px;
bottom: 30px;
.MuiFab-primary {
background-color: var(--blue);
}
}

View File

@ -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<CatalogAddButtonProps> {
@observable protected isOpen = false;
protected menuItems = observable.array<CatalogEntityContextMenu>([]);
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 (
<SpeedDial
className="CatalogAddButton"
ariaLabel="SpeedDial CatalogAddButton"
open={this.isOpen}
onOpen={this.onOpen}
onClose={this.onClose}
icon={<Icon material="add" />}
direction="up"
>
{ this.menuItems.map((menuItem, index) => {
return <SpeedDialAction
key={index}
icon={<Icon material={menuItem.icon} />}
tooltipTitle={menuItem.title}
onClick={() => menuItem.onClick()}
/>;
})}
</SpeedDial>
);
}
}

View File

@ -61,8 +61,6 @@ export class CatalogEntityStore extends ItemStore<CatalogEntityItem> {
@computed get entities() { @computed get entities() {
if (!this.activeCategory) return []; if (!this.activeCategory) return [];
console.log("computing entities", this.activeCategory);
return catalogEntityRegistry.getItemsForCategory(this.activeCategory).map(entity => new CatalogEntityItem(entity)); return catalogEntityRegistry.getItemsForCategory(this.activeCategory).map(entity => new CatalogEntityItem(entity));
} }

View File

@ -2,7 +2,7 @@ import "./catalog.scss";
import React from "react"; import React from "react";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import { ItemListLayout } from "../item-object-list"; 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 { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store";
import { navigate } from "../../navigation"; import { navigate } from "../../navigation";
import { kebabCase } from "lodash"; import { kebabCase } from "lodash";
@ -12,12 +12,12 @@ import { Icon } from "../icon";
import { CatalogEntityContextMenu, CatalogEntityContextMenuContext, catalogEntityRunContext } from "../../api/catalog-entity"; import { CatalogEntityContextMenu, CatalogEntityContextMenuContext, catalogEntityRunContext } from "../../api/catalog-entity";
import { Badge } from "../badge"; import { Badge } from "../badge";
import { hotbarStore } from "../../../common/hotbar-store"; import { hotbarStore } from "../../../common/hotbar-store";
import { addClusterURL } from "../+add-cluster";
import { autobind } from "../../utils"; import { autobind } from "../../utils";
import { Notifications } from "../notifications"; import { Notifications } from "../notifications";
import { ConfirmDialog } from "../confirm-dialog"; import { ConfirmDialog } from "../confirm-dialog";
import { Tab, Tabs } from "../tabs"; import { Tab, Tabs } from "../tabs";
import { catalogCategoryRegistry } from "../../../common/catalog-category-registry"; import { catalogCategoryRegistry } from "../../../common/catalog-category-registry";
import { CatalogAddButton } from "./catalog-add-button";
enum sortBy { enum sortBy {
name = "name", name = "name",
@ -101,6 +101,7 @@ export class Catalog extends React.Component {
return catalogCategoryRegistry.items; return catalogCategoryRegistry.items;
} }
@action
onTabChange = (tabId: string) => { onTabChange = (tabId: string) => {
this.activeTab = tabId; this.activeTab = tabId;
@ -149,6 +150,7 @@ export class Catalog extends React.Component {
); );
} }
render() { render() {
if (!this.catalogEntityStore) { if (!this.catalogEntityStore) {
return null; return null;
@ -161,6 +163,7 @@ export class Catalog extends React.Component {
provideBackButtonNavigation={false} provideBackButtonNavigation={false}
contentGaps={false}> contentGaps={false}>
<ItemListLayout <ItemListLayout
renderHeaderTitle={this.catalogEntityStore.activeCategory?.metadata.name}
isClusterScoped isClusterScoped
isSearchable={true} isSearchable={true}
isSelectable={false} isSelectable={false}
@ -186,11 +189,8 @@ export class Catalog extends React.Component {
]} ]}
onDetails={(item: CatalogEntityItem) => this.onDetails(item) } onDetails={(item: CatalogEntityItem) => this.onDetails(item) }
renderItemMenu={this.renderItemMenu} renderItemMenu={this.renderItemMenu}
addRemoveButtons={{
addTooltip: "Add Kubernetes Cluster",
onAdd: () => navigate(addClusterURL()),
}}
/> />
<CatalogAddButton category={this.catalogEntityStore.activeCategory} />
</PageLayout> </PageLayout>
); );
} }