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:
parent
b852384e85
commit
e948fc047c
@ -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");
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
@ -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}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
9
src/renderer/components/+catalog/catalog-add-button.scss
Normal file
9
src/renderer/components/+catalog/catalog-add-button.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.CatalogAddButton {
|
||||||
|
position: absolute;
|
||||||
|
right: 40px;
|
||||||
|
bottom: 30px;
|
||||||
|
|
||||||
|
.MuiFab-primary {
|
||||||
|
background-color: var(--blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/renderer/components/+catalog/catalog-add-button.tsx
Normal file
74
src/renderer/components/+catalog/catalog-add-button.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user