diff --git a/src/common/catalog-entities/kubernetes-cluster.ts b/src/common/catalog-entities/kubernetes-cluster.ts index 3354b9ba61..47af1967ff 100644 --- a/src/common/catalog-entities/kubernetes-cluster.ts +++ b/src/common/catalog-entities/kubernetes-cluster.ts @@ -49,7 +49,7 @@ export class KubernetesCluster implements CatalogEntity { { icon: "settings", title: "Settings", - onClick: async () => context.navigate(`/cluster/${this.metadata.uid}/settings`) + onClick: async () => context.navigate(`/entity/${this.metadata.uid}/settings`) }, { icon: "delete", diff --git a/src/common/catalog-entity-registry.ts b/src/common/catalog-entity-registry.ts index 28afa55bac..d42913c92f 100644 --- a/src/common/catalog-entity-registry.ts +++ b/src/common/catalog-entity-registry.ts @@ -16,6 +16,10 @@ export class CatalogEntityRegistry { return Array.from(this.sources.values()).flat(); } + getById(id: string) { + return this.items.find((entity) => entity.metadata.uid === id); + } + getItemsForApiKind(apiVersion: string, kind: string): T[] { const items = this.items.filter((item) => item.apiVersion === apiVersion && item.kind === kind); diff --git a/src/common/catalog-entity.ts b/src/common/catalog-entity.ts index ad3f0e591e..5446bab83b 100644 --- a/src/common/catalog-entity.ts +++ b/src/common/catalog-entity.ts @@ -51,11 +51,23 @@ export type CatalogEntityContextMenu = { } }; +export type CatalogEntitySettingsMenu = { + group?: string; + title: string; + components: { + View: React.ComponentType + }; +}; + export interface CatalogEntityContextMenuContext { navigate: (url: string) => void; menuItems: CatalogEntityContextMenu[]; } +export interface CatalogEntitySettingsContext { + menuItems: CatalogEntityContextMenu[]; +} + export interface CatalogEntityAddMenuContext { navigate: (url: string) => void; menuItems: CatalogEntityContextMenu[]; @@ -77,4 +89,5 @@ export interface CatalogEntity extends CatalogEntityData { onRun: (context: CatalogEntityActionContext) => Promise; onDetailsOpen: (context: CatalogEntityActionContext) => Promise; onContextMenuOpen: (context: CatalogEntityContextMenuContext) => Promise; + onSettingsOpen?: (context: CatalogEntitySettingsContext) => Promise; } diff --git a/src/common/cluster-store.ts b/src/common/cluster-store.ts index d1f11d8372..f1f10d29c3 100644 --- a/src/common/cluster-store.ts +++ b/src/common/cluster-store.ts @@ -11,7 +11,7 @@ import { dumpConfigYaml } from "./kube-helpers"; import { saveToAppFiles } from "./utils/saveToAppFiles"; import { KubeConfig } from "@kubernetes/client-node"; import { handleRequest, requestMain, subscribeToBroadcast, unsubscribeAllFromBroadcast } from "./ipc"; -import { ResourceType } from "../renderer/components/+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../renderer/components/cluster-settings/components/cluster-metrics-setting"; export interface ClusterIconUpload { clusterId: string; diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts index d36123b95a..5ae041067f 100644 --- a/src/extensions/extension-loader.ts +++ b/src/extensions/extension-loader.ts @@ -211,8 +211,8 @@ export class ExtensionLoader { this.autoInitExtensions(async (extension: LensRendererExtension) => { const removeItems = [ registries.globalPageRegistry.add(extension.globalPages, extension), - registries.globalPageMenuRegistry.add(extension.globalPageMenus, extension), registries.appPreferenceRegistry.add(extension.appPreferences), + registries.entitySettingRegistry.add(extension.entitySettings), registries.statusBarRegistry.add(extension.statusBarItems), registries.commandRegistry.add(extension.commands), ]; diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index bf1f8cbeb3..fabb876408 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -3,6 +3,7 @@ import type { Cluster } from "../main/cluster"; import { LensExtension } from "./lens-extension"; import { getExtensionPageUrl } from "./registries/page-registry"; import { CommandRegistration } from "./registries/command-registry"; +import { EntitySettingRegistration } from "./registries/entity-setting-registry"; export class LensRendererExtension extends LensExtension { globalPages: PageRegistration[] = []; @@ -11,6 +12,7 @@ export class LensRendererExtension extends LensExtension { clusterPageMenus: ClusterPageMenuRegistration[] = []; kubeObjectStatusTexts: KubeObjectStatusRegistration[] = []; appPreferences: AppPreferenceRegistration[] = []; + entitySettings: EntitySettingRegistration[] = []; statusBarItems: StatusBarRegistration[] = []; kubeObjectDetailItems: KubeObjectDetailRegistration[] = []; kubeObjectMenuItems: KubeObjectMenuRegistration[] = []; diff --git a/src/extensions/registries/entity-setting-registry.ts b/src/extensions/registries/entity-setting-registry.ts new file mode 100644 index 0000000000..91ab8030b1 --- /dev/null +++ b/src/extensions/registries/entity-setting-registry.ts @@ -0,0 +1,35 @@ +import type React from "react"; +import { CatalogEntity } from "../../common/catalog-entity"; +import { BaseRegistry } from "./base-registry"; + +export interface EntitySettingViewProps { + entity: CatalogEntity; +} + +export interface EntitySettingComponents { + View: React.ComponentType; +} + +export interface EntitySettingRegistration { + title: string; + kind: string; + apiVersions: string[]; + source?: string; + id?: string; + components: EntitySettingComponents; +} + +export interface RegisteredEntitySetting extends EntitySettingRegistration { + id: string; +} + +export class EntitySettingRegistry extends BaseRegistry { + getRegisteredItem(item: EntitySettingRegistration): RegisteredEntitySetting { + return { + id: item.id || item.title.toLowerCase().replace(/[^0-9a-zA-Z]+/g, "-"), + ...item, + }; + } +} + +export const entitySettingRegistry = new EntitySettingRegistry(); diff --git a/src/extensions/registries/index.ts b/src/extensions/registries/index.ts index 9f0aba5f0d..419f717477 100644 --- a/src/extensions/registries/index.ts +++ b/src/extensions/registries/index.ts @@ -9,3 +9,4 @@ export * from "./kube-object-detail-registry"; export * from "./kube-object-menu-registry"; export * from "./kube-object-status-registry"; export * from "./command-registry"; +export * from "./entity-setting-registry"; diff --git a/src/extensions/registries/page-menu-registry.ts b/src/extensions/registries/page-menu-registry.ts index 8fe5b68b3b..25796bbda5 100644 --- a/src/extensions/registries/page-menu-registry.ts +++ b/src/extensions/registries/page-menu-registry.ts @@ -57,5 +57,4 @@ export class ClusterPageMenuRegistry extends PageMenuRegistry { - item.enabled = false; - }); - } - - return menuItems; - } - async function navigate(url: string) { logger.info(`[MENU]: navigating to ${url}`); await windowManager.navigate(url); @@ -112,19 +101,6 @@ export function buildMenu(windowManager: WindowManager) { navigate(addClusterURL()); } }, - ...activeClusterOnly([ - { - label: "Cluster Settings", - accelerator: "CmdOrCtrl+Shift+S", - click() { - navigate(clusterSettingsURL({ - params: { - clusterId: windowManager.activeClusterId - } - })); - } - } - ]), ...ignoreOnMac([ { type: "separator" }, { diff --git a/src/renderer/api/catalog-entity-registry.ts b/src/renderer/api/catalog-entity-registry.ts index afed7a88cf..12450023ee 100644 --- a/src/renderer/api/catalog-entity-registry.ts +++ b/src/renderer/api/catalog-entity-registry.ts @@ -44,6 +44,10 @@ export class CatalogEntityRegistry { return this._items; } + getById(id: string) { + return this._items.find((entity) => entity.metadata.uid === id); + } + getItemsForApiKind(apiVersion: string, kind: string): T[] { const items = this._items.filter((item) => item.apiVersion === apiVersion && item.kind === kind); diff --git a/src/renderer/components/+cluster-settings/cluster-settings.route.ts b/src/renderer/components/+cluster-settings/cluster-settings.route.ts deleted file mode 100644 index 11a373dcdb..0000000000 --- a/src/renderer/components/+cluster-settings/cluster-settings.route.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { IClusterViewRouteParams } from "../cluster-manager/cluster-view.route"; -import type { RouteProps } from "react-router"; -import { buildURL } from "../../../common/utils/buildUrl"; - -export interface IClusterSettingsRouteParams extends IClusterViewRouteParams { -} - -export const clusterSettingsRoute: RouteProps = { - path: `/cluster/:clusterId/settings`, -}; - -export const clusterSettingsURL = buildURL(clusterSettingsRoute.path); diff --git a/src/renderer/components/+cluster-settings/cluster-settings.tsx b/src/renderer/components/+cluster-settings/cluster-settings.tsx deleted file mode 100644 index 619fe9396f..0000000000 --- a/src/renderer/components/+cluster-settings/cluster-settings.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import "./cluster-settings.scss"; - -import React from "react"; -import { observable, reaction } from "mobx"; -import { RouteComponentProps } from "react-router"; -import { observer, disposeOnUnmount } from "mobx-react"; -import { Cluster } from "../../../main/cluster"; -import { IClusterSettingsRouteParams } from "./cluster-settings.route"; -import { clusterStore } from "../../../common/cluster-store"; -import { PageLayout } from "../layout/page-layout"; -import { requestMain } from "../../../common/ipc"; -import { clusterActivateHandler, clusterRefreshHandler } from "../../../common/cluster-ipc"; -import { navigation } from "../../navigation"; -import { Tabs, Tab } from "../tabs"; -import { ClusterProxySetting } from "./components/cluster-proxy-setting"; -import { ClusterNameSetting } from "./components/cluster-name-setting"; -import { ClusterHomeDirSetting } from "./components/cluster-home-dir-setting"; -import { ClusterAccessibleNamespaces } from "./components/cluster-accessible-namespaces"; -import { ClusterMetricsSetting } from "./components/cluster-metrics-setting"; -import { ShowMetricsSetting } from "./components/show-metrics"; -import { ClusterPrometheusSetting } from "./components/cluster-prometheus-setting"; -import { ClusterKubeconfig } from "./components/cluster-kubeconfig"; - -interface Props extends RouteComponentProps { -} - - -const clusterPages = ["General", "Proxy", "Terminal", "Namespaces", "Metrics"]; - -@observer -export class ClusterSettings extends React.Component { - @observable activeTab = "General"; - - get clusterId() { - return this.props.match.params.clusterId; - } - - get cluster(): Cluster { - return clusterStore.getById(this.clusterId); - } - - componentDidMount() { - const { hash } = navigation.location; - - document.getElementById(hash.slice(1))?.scrollIntoView(); - - disposeOnUnmount(this, [ - reaction(() => this.cluster, this.refreshCluster, { - fireImmediately: true, - }), - reaction(() => this.clusterId, clusterId => clusterStore.setActive(clusterId), { - fireImmediately: true, - }) - ]); - } - - refreshCluster = async () => { - if (this.cluster) { - await requestMain(clusterActivateHandler, this.cluster.id); - await requestMain(clusterRefreshHandler, this.cluster.id); - } - }; - - onTabChange = (tabId: string) => { - this.activeTab = tabId; - }; - - renderNavigation() { - return ( - <> -

{this.cluster.name}

- -
Cluster Settings
- { clusterPages.map((page) => { - return ; - })} -
- - ); - } - - render() { - const cluster = this.cluster; - - if (!cluster) return null; - - return ( - - {this.activeTab == "General" && ( -
-

General

-
-
- -
-
- -
-
-
- )} - - {this.activeTab == "Proxy" && ( -
-

Proxy

-
- -
-
- )} - - {this.activeTab == "Terminal" && ( -
-

Terminal

-
- -
-
- )} - - {this.activeTab == "Namespaces" && ( -
-

Namespaces

-
- -
-
- )} - - {this.activeTab == "Metrics" && ( -
-

Metrics

-
-
- -
-
- -
-
- -
-
-
- )} - -
- ); - } -} diff --git a/src/renderer/components/+cluster-settings/general.tsx b/src/renderer/components/+cluster-settings/general.tsx deleted file mode 100644 index ecb0457f1c..0000000000 --- a/src/renderer/components/+cluster-settings/general.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; -import { Cluster } from "../../../main/cluster"; -import { ClusterNameSetting } from "./components/cluster-name-setting"; -import { ClusterProxySetting } from "./components/cluster-proxy-setting"; -import { ClusterPrometheusSetting } from "./components/cluster-prometheus-setting"; -import { ClusterHomeDirSetting } from "./components/cluster-home-dir-setting"; -import { ClusterAccessibleNamespaces } from "./components/cluster-accessible-namespaces"; -import { ClusterMetricsSetting } from "./components/cluster-metrics-setting"; -import { ShowMetricsSetting } from "./components/show-metrics"; - -interface Props { - cluster: Cluster; -} - -export class General extends React.Component { - render() { - return
-

General

- - - - - - - -
; - } -} diff --git a/src/renderer/components/+cluster/cluster-overview.tsx b/src/renderer/components/+cluster/cluster-overview.tsx index eda8ac3090..23d3214340 100644 --- a/src/renderer/components/+cluster/cluster-overview.tsx +++ b/src/renderer/components/+cluster/cluster-overview.tsx @@ -13,7 +13,7 @@ import { ClusterIssues } from "./cluster-issues"; import { ClusterMetrics } from "./cluster-metrics"; import { clusterOverviewStore } from "./cluster-overview.store"; import { ClusterPieCharts } from "./cluster-pie-charts"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; @observer export class ClusterOverview extends React.Component { diff --git a/src/renderer/components/+entity-settings/entity-settings.route.ts b/src/renderer/components/+entity-settings/entity-settings.route.ts new file mode 100644 index 0000000000..f140353070 --- /dev/null +++ b/src/renderer/components/+entity-settings/entity-settings.route.ts @@ -0,0 +1,12 @@ +import type { RouteProps } from "react-router"; +import { buildURL } from "../../../common/utils/buildUrl"; + +export interface EntitySettingsRouteParams { + entityId: string; +} + +export const entitySettingsRoute: RouteProps = { + path: `/entity/:entityId/settings`, +}; + +export const entitySettingsURL = buildURL(entitySettingsRoute.path); diff --git a/src/renderer/components/+cluster-settings/cluster-settings.scss b/src/renderer/components/+entity-settings/entity-settings.scss similarity index 94% rename from src/renderer/components/+cluster-settings/cluster-settings.scss rename to src/renderer/components/+entity-settings/entity-settings.scss index 8856581b03..6c8189cfe6 100644 --- a/src/renderer/components/+cluster-settings/cluster-settings.scss +++ b/src/renderer/components/+entity-settings/entity-settings.scss @@ -1,4 +1,4 @@ -.ClusterSettings { +.EntitySettings { $spacing: $padding * 3; diff --git a/src/renderer/components/+entity-settings/entity-settings.tsx b/src/renderer/components/+entity-settings/entity-settings.tsx new file mode 100644 index 0000000000..a04a410f89 --- /dev/null +++ b/src/renderer/components/+entity-settings/entity-settings.tsx @@ -0,0 +1,87 @@ +import "./entity-settings.scss"; + +import React from "react"; +import { observable } from "mobx"; +import { RouteComponentProps } from "react-router"; +import { observer } from "mobx-react"; +import { PageLayout } from "../layout/page-layout"; +import { navigation } from "../../navigation"; +import { Tabs, Tab } from "../tabs"; +import { CatalogEntity } from "../../api/catalog-entity"; +import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; +import { entitySettingRegistry } from "../../../extensions/registries"; +import { EntitySettingsRouteParams } from "./entity-settings.route"; + + +interface Props extends RouteComponentProps { +} + +@observer +export class EntitySettings extends React.Component { + @observable activeTab: string; + + get entityId() { + return this.props.match.params.entityId; + } + + get entity(): CatalogEntity { + return catalogEntityRegistry.getById(this.entityId); + } + + async componentDidMount() { + const { hash } = navigation.location; + + console.log(this.entityId, this.entity); + + + this.activeTab = entitySettingRegistry.getItems()[0]?.id; + + document.getElementById(hash.slice(1))?.scrollIntoView(); + } + + onTabChange = (tabId: string) => { + this.activeTab = tabId; + }; + + renderNavigation() { + const settings = entitySettingRegistry.getItems(); + + return ( + <> +

{this.entity.metadata.name}

+ +
Settings
+ { settings.map((setting) => { + return ; + })} +
+ + ); + } + + render() { + if (!this.entity) return null; + + const activeSetting = entitySettingRegistry.getItems().find((setting) => setting.id === this.activeTab); + + if (!activeSetting) { + return null; + } + + return ( + +
+

{activeSetting.title}

+
+ +
+
+
+ ); + } +} diff --git a/src/renderer/components/+entity-settings/index.ts b/src/renderer/components/+entity-settings/index.ts new file mode 100644 index 0000000000..44a76065a2 --- /dev/null +++ b/src/renderer/components/+entity-settings/index.ts @@ -0,0 +1,4 @@ +import "../cluster-settings"; + +export * from "./entity-settings.route"; +export * from "./entity-settings"; diff --git a/src/renderer/components/+network-ingresses/ingress-details.tsx b/src/renderer/components/+network-ingresses/ingress-details.tsx index bfbbfe6f5a..244738a537 100644 --- a/src/renderer/components/+network-ingresses/ingress-details.tsx +++ b/src/renderer/components/+network-ingresses/ingress-details.tsx @@ -14,7 +14,7 @@ import { IngressCharts } from "./ingress-charts"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { getBackendServiceNamePort } from "../../api/endpoints/ingress.api"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+nodes/node-details.tsx b/src/renderer/components/+nodes/node-details.tsx index a565411e7e..349bf59051 100644 --- a/src/renderer/components/+nodes/node-details.tsx +++ b/src/renderer/components/+nodes/node-details.tsx @@ -17,7 +17,7 @@ import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeEventDetails } from "../+events/kube-event-details"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx index 2aebba52b3..99642249ab 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx @@ -14,7 +14,7 @@ import { VolumeClaimDiskChart } from "./volume-claim-disk-chart"; import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object"; import { PersistentVolumeClaim } from "../../api/endpoints"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx b/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx index 9e613c3eff..be56f5f477 100644 --- a/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx +++ b/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx @@ -18,7 +18,7 @@ import { reaction } from "mobx"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+workloads-pods/pod-details-container.tsx b/src/renderer/components/+workloads-pods/pod-details-container.tsx index 99238aa5ad..d761f7fc1e 100644 --- a/src/renderer/components/+workloads-pods/pod-details-container.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-container.tsx @@ -11,7 +11,7 @@ import { PodContainerPort } from "./pod-container-port"; import { ResourceMetrics } from "../resource-metrics"; import { IMetrics } from "../../api/endpoints/metrics.api"; import { ContainerCharts } from "./container-charts"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props { diff --git a/src/renderer/components/+workloads-pods/pod-details.tsx b/src/renderer/components/+workloads-pods/pod-details.tsx index 6736e1e326..f643d599a5 100644 --- a/src/renderer/components/+workloads-pods/pod-details.tsx +++ b/src/renderer/components/+workloads-pods/pod-details.tsx @@ -22,7 +22,7 @@ import { getItemMetrics } from "../../api/endpoints/metrics.api"; import { PodCharts, podMetricTabs } from "./pod-charts"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx index 4510d0add7..b104340612 100644 --- a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx +++ b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx @@ -17,7 +17,7 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx index 97e83807f9..f21f9efc5d 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx @@ -18,7 +18,7 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import { ResourceType } from "../+cluster-settings/components/cluster-metrics-setting"; +import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { clusterStore } from "../../../common/cluster-store"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/cluster-manager/cluster-actions.tsx b/src/renderer/components/cluster-manager/cluster-actions.tsx deleted file mode 100644 index 5015abbcac..0000000000 --- a/src/renderer/components/cluster-manager/cluster-actions.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from "react"; -import uniqueId from "lodash/uniqueId"; -import { clusterSettingsURL } from "../+cluster-settings"; -import { catalogURL } from "../+catalog"; - -import { clusterStore } from "../../../common/cluster-store"; -import { broadcastMessage, requestMain } from "../../../common/ipc"; -import { clusterDisconnectHandler } from "../../../common/cluster-ipc"; -import { ConfirmDialog } from "../confirm-dialog"; -import { Cluster } from "../../../main/cluster"; -import { Tooltip } from "../../components//tooltip"; -import { IpcRendererNavigationEvents } from "../../navigation/events"; - -const navigate = (route: string) => - broadcastMessage(IpcRendererNavigationEvents.NAVIGATE_IN_APP, route); - -/** - * Creates handlers for high-level actions - * that could be performed on an individual cluster - * @param cluster Cluster - */ -export const ClusterActions = (cluster: Cluster) => ({ - showSettings: () => navigate(clusterSettingsURL({ - params: { clusterId: cluster.id } - })), - disconnect: async () => { - clusterStore.deactivate(cluster.id); - navigate(catalogURL()); - await requestMain(clusterDisconnectHandler, cluster.id); - }, - remove: () => { - const tooltipId = uniqueId("tooltip_target_"); - - return ConfirmDialog.open({ - okButtonProps: { - primary: false, - accent: true, - label: "Remove" - }, - ok: () => { - clusterStore.deactivate(cluster.id); - clusterStore.removeById(cluster.id); - navigate(catalogURL()); - }, - message:

- Are you sure want to remove cluster {cluster.name}? - {cluster.id} -

- }); - } -}); diff --git a/src/renderer/components/cluster-manager/cluster-manager.tsx b/src/renderer/components/cluster-manager/cluster-manager.tsx index 6fb6646d32..7b9a7be0ea 100644 --- a/src/renderer/components/cluster-manager/cluster-manager.tsx +++ b/src/renderer/components/cluster-manager/cluster-manager.tsx @@ -9,7 +9,6 @@ import { Catalog, catalogRoute, catalogURL } from "../+catalog"; import { Preferences, preferencesRoute } from "../+preferences"; import { AddCluster, addClusterRoute } from "../+add-cluster"; import { ClusterView } from "./cluster-view"; -import { ClusterSettings, clusterSettingsRoute } from "../+cluster-settings"; import { clusterViewRoute } from "./cluster-view.route"; import { clusterStore } from "../../../common/cluster-store"; import { hasLoadedView, initView, lensViews, refreshViews } from "./lens-views"; @@ -17,6 +16,7 @@ import { globalPageRegistry } from "../../../extensions/registries/page-registry import { Extensions, extensionsRoute } from "../+extensions"; import { getMatchedClusterId } from "../../navigation"; import { HotbarMenu } from "../hotbar/hotbar-menu"; +import { EntitySettings, entitySettingsRoute } from "../+entity-settings"; @observer export class ClusterManager extends React.Component { @@ -58,7 +58,7 @@ export class ClusterManager extends React.Component { - + {globalPageRegistry.getItems().map(({ url, components: { Page } }) => { return ; })} diff --git a/src/renderer/components/cluster-manager/index.tsx b/src/renderer/components/cluster-manager/index.tsx index 74595583aa..692f1676ef 100644 --- a/src/renderer/components/cluster-manager/index.tsx +++ b/src/renderer/components/cluster-manager/index.tsx @@ -1,2 +1 @@ export * from "./cluster-manager"; -export * from "./cluster-actions"; diff --git a/src/renderer/components/+cluster-settings/cluster-settings.command.ts b/src/renderer/components/cluster-settings/cluster-settings.command.ts similarity index 72% rename from src/renderer/components/+cluster-settings/cluster-settings.command.ts rename to src/renderer/components/cluster-settings/cluster-settings.command.ts index c2e762eca8..061d135d67 100644 --- a/src/renderer/components/+cluster-settings/cluster-settings.command.ts +++ b/src/renderer/components/cluster-settings/cluster-settings.command.ts @@ -1,15 +1,15 @@ import { navigate } from "../../navigation"; import { commandRegistry } from "../../../extensions/registries/command-registry"; -import { clusterSettingsURL } from "./cluster-settings.route"; import { clusterStore } from "../../../common/cluster-store"; +import { entitySettingsURL } from "../+entity-settings"; commandRegistry.add({ id: "cluster.viewCurrentClusterSettings", title: "Cluster: View Settings", scope: "global", - action: () => navigate(clusterSettingsURL({ + action: () => navigate(entitySettingsURL({ params: { - clusterId: clusterStore.active.id + entityId: clusterStore.active.id } })), isActive: (context) => !!context.entity diff --git a/src/renderer/components/cluster-settings/cluster-settings.tsx b/src/renderer/components/cluster-settings/cluster-settings.tsx new file mode 100644 index 0000000000..0d808c2ffa --- /dev/null +++ b/src/renderer/components/cluster-settings/cluster-settings.tsx @@ -0,0 +1,130 @@ +import React from "react"; +import { clusterStore } from "../../../common/cluster-store"; +import { ClusterProxySetting } from "./components/cluster-proxy-setting"; +import { ClusterNameSetting } from "./components/cluster-name-setting"; +import { ClusterHomeDirSetting } from "./components/cluster-home-dir-setting"; +import { ClusterAccessibleNamespaces } from "./components/cluster-accessible-namespaces"; +import { ClusterMetricsSetting } from "./components/cluster-metrics-setting"; +import { ShowMetricsSetting } from "./components/show-metrics"; +import { ClusterPrometheusSetting } from "./components/cluster-prometheus-setting"; +import { ClusterKubeconfig } from "./components/cluster-kubeconfig"; +import { entitySettingRegistry } from "../../../extensions/registries"; +import { CatalogEntity } from "../../api/catalog-entity"; + +entitySettingRegistry.add([ + { + apiVersions: ["entity.k8slens.dev/v1alpha1"], + kind: "KubernetesCluster", + source: "local", + title: "General", + components: { + View: (props: { entity: CatalogEntity }) => { + const cluster = clusterStore.enabledClustersList.find((cluster) => cluster.id === props.entity.metadata.uid); + + if (!cluster) { + return null; + } + + return ( +
+
+ +
+
+ +
+
+ ); + } + } + }, + { + apiVersions: ["entity.k8slens.dev/v1alpha1"], + kind: "KubernetesCluster", + title: "Proxy", + components: { + View: (props: { entity: CatalogEntity }) => { + const cluster = clusterStore.enabledClustersList.find((cluster) => cluster.id === props.entity.metadata.uid); + + if (!cluster) { + return null; + } + + return ( +
+ +
+ ); + } + } + }, + { + apiVersions: ["entity.k8slens.dev/v1alpha1"], + kind: "KubernetesCluster", + title: "Terminal", + components: { + View: (props: { entity: CatalogEntity }) => { + const cluster = clusterStore.enabledClustersList.find((cluster) => cluster.id === props.entity.metadata.uid); + + if (!cluster) { + return null; + } + + return ( +
+ +
+ ); + } + } + }, + { + apiVersions: ["entity.k8slens.dev/v1alpha1"], + kind: "KubernetesCluster", + title: "Namespaces", + components: { + View: (props: { entity: CatalogEntity }) => { + const cluster = clusterStore.enabledClustersList.find((cluster) => cluster.id === props.entity.metadata.uid); + + if (!cluster) { + return null; + } + + return ( +
+ +
+ ); + } + } + }, + { + apiVersions: ["entity.k8slens.dev/v1alpha1"], + kind: "KubernetesCluster", + source: "local", + title: "Metrics", + components: { + View: (props: { entity: CatalogEntity }) => { + const cluster = clusterStore.enabledClustersList.find((cluster) => cluster.id === props.entity.metadata.uid); + + if (!cluster) { + return null; + } + + return ( +
+
+ +
+
+ +
+
+ +
+
+ ); + } + } + } +]); diff --git a/src/renderer/components/+cluster-settings/components/cluster-accessible-namespaces.tsx b/src/renderer/components/cluster-settings/components/cluster-accessible-namespaces.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-accessible-namespaces.tsx rename to src/renderer/components/cluster-settings/components/cluster-accessible-namespaces.tsx diff --git a/src/renderer/components/+cluster-settings/components/cluster-home-dir-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-home-dir-setting.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-home-dir-setting.tsx rename to src/renderer/components/cluster-settings/components/cluster-home-dir-setting.tsx diff --git a/src/renderer/components/+cluster-settings/components/cluster-kubeconfig.tsx b/src/renderer/components/cluster-settings/components/cluster-kubeconfig.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-kubeconfig.tsx rename to src/renderer/components/cluster-settings/components/cluster-kubeconfig.tsx diff --git a/src/renderer/components/+cluster-settings/components/cluster-metrics-setting.scss b/src/renderer/components/cluster-settings/components/cluster-metrics-setting.scss similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-metrics-setting.scss rename to src/renderer/components/cluster-settings/components/cluster-metrics-setting.scss diff --git a/src/renderer/components/+cluster-settings/components/cluster-metrics-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-metrics-setting.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-metrics-setting.tsx rename to src/renderer/components/cluster-settings/components/cluster-metrics-setting.tsx diff --git a/src/renderer/components/+cluster-settings/components/cluster-name-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-name-setting.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-name-setting.tsx rename to src/renderer/components/cluster-settings/components/cluster-name-setting.tsx diff --git a/src/renderer/components/+cluster-settings/components/cluster-prometheus-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-prometheus-setting.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-prometheus-setting.tsx rename to src/renderer/components/cluster-settings/components/cluster-prometheus-setting.tsx diff --git a/src/renderer/components/+cluster-settings/components/cluster-proxy-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-proxy-setting.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/cluster-proxy-setting.tsx rename to src/renderer/components/cluster-settings/components/cluster-proxy-setting.tsx diff --git a/src/renderer/components/+cluster-settings/components/remove-cluster-button.tsx b/src/renderer/components/cluster-settings/components/remove-cluster-button.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/remove-cluster-button.tsx rename to src/renderer/components/cluster-settings/components/remove-cluster-button.tsx diff --git a/src/renderer/components/+cluster-settings/components/show-metrics.tsx b/src/renderer/components/cluster-settings/components/show-metrics.tsx similarity index 100% rename from src/renderer/components/+cluster-settings/components/show-metrics.tsx rename to src/renderer/components/cluster-settings/components/show-metrics.tsx diff --git a/src/renderer/components/+cluster-settings/index.ts b/src/renderer/components/cluster-settings/index.ts similarity index 65% rename from src/renderer/components/+cluster-settings/index.ts rename to src/renderer/components/cluster-settings/index.ts index b83e440d53..9bcc72f7d1 100644 --- a/src/renderer/components/+cluster-settings/index.ts +++ b/src/renderer/components/cluster-settings/index.ts @@ -1,3 +1,2 @@ -export * from "./cluster-settings.route"; export * from "./cluster-settings"; export * from "./cluster-settings.command"; diff --git a/src/renderer/ipc/index.tsx b/src/renderer/ipc/index.tsx index ccbeef4797..119f13a0dc 100644 --- a/src/renderer/ipc/index.tsx +++ b/src/renderer/ipc/index.tsx @@ -7,7 +7,7 @@ import { isMac } from "../../common/vars"; import { invalidKubeconfigHandler } from "./invalid-kubeconfig-handler"; import { clusterStore } from "../../common/cluster-store"; import { navigate } from "../navigation"; -import { clusterSettingsURL } from "../components/+cluster-settings"; +import { entitySettingsURL } from "../components/+entity-settings"; function sendToBackchannel(backchannel: string, notificationId: string, data: BackchannelArg): void { notificationsStore.remove(notificationId); @@ -79,7 +79,7 @@ function ListNamespacesForbiddenHandler(event: IpcRendererEvent, ...[clusterId]:

Cluster {clusterStore.active.name} does not have permissions to list namespaces. Please add the namespaces you have access to.

diff --git a/src/renderer/protocol-handler/app-handlers.ts b/src/renderer/protocol-handler/app-handlers.ts index b4d2232eb0..c71467fe8a 100644 --- a/src/renderer/protocol-handler/app-handlers.ts +++ b/src/renderer/protocol-handler/app-handlers.ts @@ -1,5 +1,4 @@ import { addClusterURL } from "../components/+add-cluster"; -import { clusterSettingsURL } from "../components/+cluster-settings"; import { extensionsURL } from "../components/+extensions"; import { catalogURL } from "../components/+catalog"; import { preferencesURL } from "../components/+preferences"; @@ -7,6 +6,8 @@ import { clusterViewURL } from "../components/cluster-manager/cluster-view.route import { LensProtocolRouterRenderer } from "./router"; import { navigate } from "../navigation/helpers"; import { clusterStore } from "../../common/cluster-store"; +import { entitySettingsURL } from "../components/+entity-settings"; +import { catalogEntityRegistry } from "../api/catalog-entity-registry"; export function bindProtocolAddRouteHandlers() { LensProtocolRouterRenderer @@ -23,6 +24,19 @@ export function bindProtocolAddRouteHandlers() { .addInternalHandler("/cluster", () => { navigate(addClusterURL()); }) + .addInternalHandler("/entity/:entityId/settings", ({ pathname: { entityId } }) => { + const entity = catalogEntityRegistry.getById(entityId); + + if (entity) { + navigate(entitySettingsURL({ params: { entityId } })); + } else { + console.log("[APP-HANDLER]: catalog entity with given ID does not exist", { entityId }); + } + }) + .addInternalHandler("/extensions", () => { + navigate(extensionsURL()); + }) + // Handlers below are deprecated and only kept for backward compat purposes .addInternalHandler("/cluster/:clusterId", ({ pathname: { clusterId } }) => { const cluster = clusterStore.getById(clusterId); @@ -36,12 +50,9 @@ export function bindProtocolAddRouteHandlers() { const cluster = clusterStore.getById(clusterId); if (cluster) { - navigate(clusterSettingsURL({ params: { clusterId } })); + navigate(entitySettingsURL({ params: { entityId: clusterId } })); } else { console.log("[APP-HANDLER]: cluster with given ID does not exist", { clusterId }); } - }) - .addInternalHandler("/extensions", () => { - navigate(extensionsURL()); }); }