mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add context menu into sidebar (#4044)
This commit is contained in:
parent
e21888c62c
commit
125a073007
@ -36,7 +36,7 @@ function getSidebarSelectors(itemId: string) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
expandSubMenu: `${root} .nav-item`,
|
expandSubMenu: `${root} .nav-item`,
|
||||||
subMenuLink: (href: string) => `[data-testid=cluster-sidebar] .sub-menu a[href^="/${href}"]`,
|
subMenuLink: (href: string) => `[data-testid=cluster-sidebar] .sub-menu a[href^="${href}"]`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ function isTopPageTest(test: CommonPageTest): test is TopPageTest {
|
|||||||
const commonPageTests: CommonPageTest[] = [{
|
const commonPageTests: CommonPageTest[] = [{
|
||||||
page: {
|
page: {
|
||||||
name: "Cluster",
|
name: "Cluster",
|
||||||
href: "cluster",
|
href: "/overview",
|
||||||
expectedSelector: "div.ClusterOverview div.label",
|
expectedSelector: "div.ClusterOverview div.label",
|
||||||
expectedText: "CPU"
|
expectedText: "CPU"
|
||||||
}
|
}
|
||||||
@ -81,153 +81,161 @@ const commonPageTests: CommonPageTest[] = [{
|
|||||||
{
|
{
|
||||||
page: {
|
page: {
|
||||||
name: "Nodes",
|
name: "Nodes",
|
||||||
href: "nodes",
|
href: "/nodes",
|
||||||
expectedSelector: "h5.title",
|
expectedSelector: "h5.title",
|
||||||
expectedText: "Nodes"
|
expectedText: "Nodes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "workloads",
|
drawerId: "workloads",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "Overview",
|
{
|
||||||
href: "workloads",
|
name: "Overview",
|
||||||
expectedSelector: "h5.box",
|
href: "/workloads",
|
||||||
expectedText: "Overview"
|
expectedSelector: "h5.box",
|
||||||
},
|
expectedText: "Overview"
|
||||||
{
|
},
|
||||||
name: "Pods",
|
{
|
||||||
href: "pods",
|
name: "Pods",
|
||||||
expectedSelector: "h5.title",
|
href: "/pods",
|
||||||
expectedText: "Pods"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Pods"
|
||||||
{
|
},
|
||||||
name: "Deployments",
|
{
|
||||||
href: "deployments",
|
name: "Deployments",
|
||||||
expectedSelector: "h5.title",
|
href: "/deployments",
|
||||||
expectedText: "Deployments"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Deployments"
|
||||||
{
|
},
|
||||||
name: "DaemonSets",
|
{
|
||||||
href: "daemonsets",
|
name: "DaemonSets",
|
||||||
expectedSelector: "h5.title",
|
href: "/daemonsets",
|
||||||
expectedText: "Daemon Sets"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Daemon Sets"
|
||||||
{
|
},
|
||||||
name: "StatefulSets",
|
{
|
||||||
href: "statefulsets",
|
name: "StatefulSets",
|
||||||
expectedSelector: "h5.title",
|
href: "/statefulsets",
|
||||||
expectedText: "Stateful Sets"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Stateful Sets"
|
||||||
{
|
},
|
||||||
name: "ReplicaSets",
|
{
|
||||||
href: "replicasets",
|
name: "ReplicaSets",
|
||||||
expectedSelector: "h5.title",
|
href: "/replicasets",
|
||||||
expectedText: "Replica Sets"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Replica Sets"
|
||||||
{
|
},
|
||||||
name: "Jobs",
|
{
|
||||||
href: "jobs",
|
name: "Jobs",
|
||||||
expectedSelector: "h5.title",
|
href: "/jobs",
|
||||||
expectedText: "Jobs"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Jobs"
|
||||||
{
|
},
|
||||||
name: "CronJobs",
|
{
|
||||||
href: "cronjobs",
|
name: "CronJobs",
|
||||||
expectedSelector: "h5.title",
|
href: "/cronjobs",
|
||||||
expectedText: "Cron Jobs"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Cron Jobs"
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "config",
|
drawerId: "config",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "ConfigMaps",
|
{
|
||||||
href: "configmaps",
|
name: "ConfigMaps",
|
||||||
expectedSelector: "h5.title",
|
href: "/configmaps",
|
||||||
expectedText: "Config Maps"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Config Maps"
|
||||||
{
|
},
|
||||||
name: "Secrets",
|
{
|
||||||
href: "secrets",
|
name: "Secrets",
|
||||||
expectedSelector: "h5.title",
|
href: "/secrets",
|
||||||
expectedText: "Secrets"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Secrets"
|
||||||
{
|
},
|
||||||
name: "Resource Quotas",
|
{
|
||||||
href: "resourcequotas",
|
name: "Resource Quotas",
|
||||||
expectedSelector: "h5.title",
|
href: "/resourcequotas",
|
||||||
expectedText: "Resource Quotas"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Resource Quotas"
|
||||||
{
|
},
|
||||||
name: "Limit Ranges",
|
{
|
||||||
href: "limitranges",
|
name: "Limit Ranges",
|
||||||
expectedSelector: "h5.title",
|
href: "/limitranges",
|
||||||
expectedText: "Limit Ranges"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Limit Ranges"
|
||||||
{
|
},
|
||||||
name: "HPA",
|
{
|
||||||
href: "hpa",
|
name: "HPA",
|
||||||
expectedSelector: "h5.title",
|
href: "/hpa",
|
||||||
expectedText: "Horizontal Pod Autoscalers"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Horizontal Pod Autoscalers"
|
||||||
{
|
},
|
||||||
name: "Pod Disruption Budgets",
|
{
|
||||||
href: "poddisruptionbudgets",
|
name: "Pod Disruption Budgets",
|
||||||
expectedSelector: "h5.title",
|
href: "/poddisruptionbudgets",
|
||||||
expectedText: "Pod Disruption Budgets"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Pod Disruption Budgets"
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "networks",
|
drawerId: "networks",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "Services",
|
{
|
||||||
href: "services",
|
name: "Services",
|
||||||
expectedSelector: "h5.title",
|
href: "/services",
|
||||||
expectedText: "Services"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Services"
|
||||||
{
|
},
|
||||||
name: "Endpoints",
|
{
|
||||||
href: "endpoints",
|
name: "Endpoints",
|
||||||
expectedSelector: "h5.title",
|
href: "/endpoints",
|
||||||
expectedText: "Endpoints"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Endpoints"
|
||||||
{
|
},
|
||||||
name: "Ingresses",
|
{
|
||||||
href: "ingresses",
|
name: "Ingresses",
|
||||||
expectedSelector: "h5.title",
|
href: "/ingresses",
|
||||||
expectedText: "Ingresses"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Ingresses"
|
||||||
{
|
},
|
||||||
name: "Network Policies",
|
{
|
||||||
href: "network-policies",
|
name: "Network Policies",
|
||||||
expectedSelector: "h5.title",
|
href: "/network-policies",
|
||||||
expectedText: "Network Policies"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Network Policies"
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "storage",
|
drawerId: "storage",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "Persistent Volume Claims",
|
{
|
||||||
href: "persistent-volume-claims",
|
name: "Persistent Volume Claims",
|
||||||
expectedSelector: "h5.title",
|
href: "/persistent-volume-claims",
|
||||||
expectedText: "Persistent Volume Claims"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Persistent Volume Claims"
|
||||||
{
|
},
|
||||||
name: "Persistent Volumes",
|
{
|
||||||
href: "persistent-volumes",
|
name: "Persistent Volumes",
|
||||||
expectedSelector: "h5.title",
|
href: "/persistent-volumes",
|
||||||
expectedText: "Persistent Volumes"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Persistent Volumes"
|
||||||
{
|
},
|
||||||
name: "Storage Classes",
|
{
|
||||||
href: "storage-classes",
|
name: "Storage Classes",
|
||||||
expectedSelector: "h5.title",
|
href: "/storage-classes",
|
||||||
expectedText: "Storage Classes"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Storage Classes"
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
page: {
|
page: {
|
||||||
name: "Namespaces",
|
name: "Namespaces",
|
||||||
href: "namespaces",
|
href: "/namespaces",
|
||||||
expectedSelector: "h5.title",
|
expectedSelector: "h5.title",
|
||||||
expectedText: "Namespaces"
|
expectedText: "Namespaces"
|
||||||
}
|
}
|
||||||
@ -235,72 +243,78 @@ const commonPageTests: CommonPageTest[] = [{
|
|||||||
{
|
{
|
||||||
page: {
|
page: {
|
||||||
name: "Events",
|
name: "Events",
|
||||||
href: "events",
|
href: "/events",
|
||||||
expectedSelector: "h5.title",
|
expectedSelector: "h5.title",
|
||||||
expectedText: "Events"
|
expectedText: "Events"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "apps",
|
drawerId: "apps",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "Charts",
|
{
|
||||||
href: "apps/charts",
|
name: "Charts",
|
||||||
expectedSelector: "div.HelmCharts input",
|
href: "/apps/charts",
|
||||||
},
|
expectedSelector: "div.HelmCharts input",
|
||||||
{
|
},
|
||||||
name: "Releases",
|
{
|
||||||
href: "apps/releases",
|
name: "Releases",
|
||||||
expectedSelector: "h5.title",
|
href: "/apps/releases",
|
||||||
expectedText: "Releases"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Releases"
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "users",
|
drawerId: "users",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "Service Accounts",
|
{
|
||||||
href: "service-accounts",
|
name: "Service Accounts",
|
||||||
expectedSelector: "h5.title",
|
href: "/service-accounts",
|
||||||
expectedText: "Service Accounts"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Service Accounts"
|
||||||
{
|
},
|
||||||
name: "Roles",
|
{
|
||||||
href: "roles",
|
name: "Roles",
|
||||||
expectedSelector: "h5.title",
|
href: "/roles",
|
||||||
expectedText: "Roles"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Roles"
|
||||||
{
|
},
|
||||||
name: "Cluster Roles",
|
{
|
||||||
href: "cluster-roles",
|
name: "Cluster Roles",
|
||||||
expectedSelector: "h5.title",
|
href: "/cluster-roles",
|
||||||
expectedText: "Cluster Roles"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Cluster Roles"
|
||||||
{
|
},
|
||||||
name: "Role Bindings",
|
{
|
||||||
href: "role-bindings",
|
name: "Role Bindings",
|
||||||
expectedSelector: "h5.title",
|
href: "/role-bindings",
|
||||||
expectedText: "Role Bindings"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Role Bindings"
|
||||||
{
|
},
|
||||||
name: "Cluster Role Bindings",
|
{
|
||||||
href: "cluster-role-bindings",
|
name: "Cluster Role Bindings",
|
||||||
expectedSelector: "h5.title",
|
href: "/cluster-role-bindings",
|
||||||
expectedText: "Cluster Role Bindings"
|
expectedSelector: "h5.title",
|
||||||
},
|
expectedText: "Cluster Role Bindings"
|
||||||
{
|
},
|
||||||
name: "Pod Security Policies",
|
{
|
||||||
href: "pod-security-policies",
|
name: "Pod Security Policies",
|
||||||
expectedSelector: "h5.title",
|
href: "/pod-security-policies",
|
||||||
expectedText: "Pod Security Policies"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Pod Security Policies"
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
drawerId: "custom-resources",
|
drawerId: "custom-resources",
|
||||||
pages: [{
|
pages: [
|
||||||
name: "Definitions",
|
{
|
||||||
href: "crd/definitions",
|
name: "Definitions",
|
||||||
expectedSelector: "h5.title",
|
href: "/crd/definitions",
|
||||||
expectedText: "Custom Resources"
|
expectedSelector: "h5.title",
|
||||||
}]
|
expectedText: "Custom Resources"
|
||||||
|
},
|
||||||
|
]
|
||||||
}];
|
}];
|
||||||
|
|
||||||
utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
||||||
@ -321,7 +335,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
|
|||||||
for (const test of commonPageTests) {
|
for (const test of commonPageTests) {
|
||||||
if (isTopPageTest(test)) {
|
if (isTopPageTest(test)) {
|
||||||
const { href, expectedText, expectedSelector } = test.page;
|
const { href, expectedText, expectedSelector } = test.page;
|
||||||
const menuButton = await frame.waitForSelector(`a[href^="/${href}"]`);
|
const menuButton = await frame.waitForSelector(`a[href^="${href}"]`);
|
||||||
|
|
||||||
await menuButton.click();
|
await menuButton.click();
|
||||||
await frame.waitForSelector(`${expectedSelector} >> text='${expectedText}'`);
|
await frame.waitForSelector(`${expectedSelector} >> text='${expectedText}'`);
|
||||||
|
|||||||
@ -23,10 +23,11 @@ import { catalogCategoryRegistry } from "../catalog/catalog-category-registry";
|
|||||||
import { CatalogEntity, CatalogEntityActionContext, CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
|
import { CatalogEntity, CatalogEntityActionContext, CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
|
||||||
import { clusterActivateHandler, clusterDisconnectHandler } from "../cluster-ipc";
|
import { clusterActivateHandler, clusterDisconnectHandler } from "../cluster-ipc";
|
||||||
import { ClusterStore } from "../cluster-store";
|
import { ClusterStore } from "../cluster-store";
|
||||||
import { requestMain } from "../ipc";
|
import { broadcastMessage, requestMain } from "../ipc";
|
||||||
import { CatalogCategory, CatalogCategorySpec } from "../catalog";
|
import { CatalogCategory, CatalogCategorySpec } from "../catalog";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import type { CatalogEntitySpec } from "../catalog/catalog-entity";
|
import type { CatalogEntitySpec } from "../catalog/catalog-entity";
|
||||||
|
import { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||||
|
|
||||||
export interface KubernetesClusterPrometheusMetrics {
|
export interface KubernetesClusterPrometheusMetrics {
|
||||||
address?: {
|
address?: {
|
||||||
@ -114,7 +115,10 @@ export class KubernetesCluster extends CatalogEntity<KubernetesClusterMetadata,
|
|||||||
context.menuItems.push({
|
context.menuItems.push({
|
||||||
title: "Settings",
|
title: "Settings",
|
||||||
icon: "edit",
|
icon: "edit",
|
||||||
onClick: () => context.navigate(`/entity/${this.metadata.uid}/settings`)
|
onClick: () => broadcastMessage(
|
||||||
|
IpcRendererNavigationEvents.NAVIGATE_IN_APP,
|
||||||
|
`/entity/${this.metadata.uid}/settings`,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -172,7 +172,10 @@ export interface CatalogEntitySettingsMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CatalogEntityContextMenuContext {
|
export interface CatalogEntityContextMenuContext {
|
||||||
navigate: (url: string) => void;
|
/**
|
||||||
|
* Navigate to the specified pathname
|
||||||
|
*/
|
||||||
|
navigate: (pathname: string) => void;
|
||||||
menuItems: CatalogEntityContextMenu[];
|
menuItems: CatalogEntityContextMenu[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import type { RouteProps } from "react-router";
|
|||||||
import { buildURL } from "../utils/buildUrl";
|
import { buildURL } from "../utils/buildUrl";
|
||||||
|
|
||||||
export const clusterRoute: RouteProps = {
|
export const clusterRoute: RouteProps = {
|
||||||
path: "/cluster"
|
path: "/overview"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clusterURL = buildURL(clusterRoute.path);
|
export const clusterURL = buildURL(clusterRoute.path);
|
||||||
|
|||||||
@ -72,6 +72,7 @@ import type { ClusterId } from "../../common/cluster-types";
|
|||||||
import { watchHistoryState } from "../remote-helpers/history-updater";
|
import { watchHistoryState } from "../remote-helpers/history-updater";
|
||||||
import { unmountComponentAtNode } from "react-dom";
|
import { unmountComponentAtNode } from "react-dom";
|
||||||
import { PortForwardDialog } from "../port-forward";
|
import { PortForwardDialog } from "../port-forward";
|
||||||
|
import { DeleteClusterDialog } from "./delete-cluster-dialog";
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class App extends React.Component {
|
export class App extends React.Component {
|
||||||
@ -230,6 +231,7 @@ export class App extends React.Component {
|
|||||||
<ReplicaSetScaleDialog/>
|
<ReplicaSetScaleDialog/>
|
||||||
<CronJobTriggerDialog/>
|
<CronJobTriggerDialog/>
|
||||||
<PortForwardDialog/>
|
<PortForwardDialog/>
|
||||||
|
<DeleteClusterDialog/>
|
||||||
<CommandContainer clusterId={App.clusterId}/>
|
<CommandContainer clusterId={App.clusterId}/>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
@ -44,20 +44,16 @@ interface Props extends DOMAttributes<HTMLElement> {
|
|||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class HotbarEntityIcon extends React.Component<Props> {
|
export class HotbarEntityIcon extends React.Component<Props> {
|
||||||
@observable private contextMenu: CatalogEntityContextMenuContext;
|
@observable private contextMenu: CatalogEntityContextMenuContext = {
|
||||||
|
menuItems: [],
|
||||||
|
navigate: (url: string) => navigate(url),
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.contextMenu = {
|
|
||||||
menuItems: [],
|
|
||||||
navigate: (url: string) => navigate(url),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get kindIcon() {
|
get kindIcon() {
|
||||||
const className = "badge";
|
const className = "badge";
|
||||||
const category = catalogCategoryRegistry.getCategoryForEntity(this.props.entity);
|
const category = catalogCategoryRegistry.getCategoryForEntity(this.props.entity);
|
||||||
|
|||||||
@ -42,6 +42,9 @@ import * as routes from "../../../common/routes";
|
|||||||
import { Config } from "../+config";
|
import { Config } from "../+config";
|
||||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||||
import { HotbarIcon } from "../hotbar/hotbar-icon";
|
import { HotbarIcon } from "../hotbar/hotbar-icon";
|
||||||
|
import { makeObservable, observable } from "mobx";
|
||||||
|
import type { CatalogEntityContextMenuContext } from "../../../common/catalog";
|
||||||
|
import { HotbarStore } from "../../../common/hotbar-store";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -50,6 +53,15 @@ interface Props {
|
|||||||
@observer
|
@observer
|
||||||
export class Sidebar extends React.Component<Props> {
|
export class Sidebar extends React.Component<Props> {
|
||||||
static displayName = "Sidebar";
|
static displayName = "Sidebar";
|
||||||
|
@observable private contextMenu: CatalogEntityContextMenuContext = {
|
||||||
|
menuItems: [],
|
||||||
|
navigate,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
makeObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
crdStore.reloadAll();
|
crdStore.reloadAll();
|
||||||
@ -194,6 +206,20 @@ export class Sidebar extends React.Component<Props> {
|
|||||||
src={spec.icon?.src}
|
src={spec.icon?.src}
|
||||||
className="mr-5"
|
className="mr-5"
|
||||||
onClick={() => navigate("/")}
|
onClick={() => navigate("/")}
|
||||||
|
menuItems={this.contextMenu.menuItems}
|
||||||
|
onMenuOpen={() => {
|
||||||
|
const hotbarStore = HotbarStore.getInstance();
|
||||||
|
const isAddedToActive = HotbarStore.getInstance().isAddedToActive(this.clusterEntity);
|
||||||
|
const title = isAddedToActive
|
||||||
|
? "Remove from Hotbar"
|
||||||
|
: "Add to Hotbar";
|
||||||
|
const onClick = isAddedToActive
|
||||||
|
? () => hotbarStore.removeFromHotbar(metadata.uid)
|
||||||
|
: () => hotbarStore.addToHotbar(this.clusterEntity);
|
||||||
|
|
||||||
|
this.contextMenu.menuItems = [{ title, onClick }];
|
||||||
|
this.clusterEntity.onContextMenuOpen(this.contextMenu);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div className={styles.clusterName}>
|
<div className={styles.clusterName}>
|
||||||
{metadata.name}
|
{metadata.name}
|
||||||
|
|||||||
@ -63,6 +63,7 @@ function bindClusterManagerRouteEvents() {
|
|||||||
ipcRendererOn(IpcRendererNavigationEvents.NAVIGATE_IN_APP, (event, url: string) => {
|
ipcRendererOn(IpcRendererNavigationEvents.NAVIGATE_IN_APP, (event, url: string) => {
|
||||||
logger.info(`[IPC]: navigate to ${url}`, { currentLocation: location.href });
|
logger.info(`[IPC]: navigate to ${url}`, { currentLocation: location.href });
|
||||||
navigate(url);
|
navigate(url);
|
||||||
|
window.focus(); // make sure that the main frame is focused
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user