1
0
mirror of https://github.com/lensapp/lens.git synced 2024-09-19 21:37:13 +03:00

Explicitly initialize registries

- Helps moves towards turning on banning CyclicImports

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-05-14 17:24:22 -04:00
parent c18df6bcae
commit 6d10f011e5
101 changed files with 1178 additions and 1087 deletions

View File

@ -29,7 +29,7 @@ import { RoutingError, RoutingErrorType } from "./error";
import { ExtensionsStore } from "../../extensions/extensions-store";
import { ExtensionLoader } from "../../extensions/extension-loader";
import type { LensExtension } from "../../extensions/lens-extension";
import type { RouteHandler, RouteParams } from "../../extensions/registries/protocol-handler-registry";
import type { RouteHandler, RouteParams } from "../../extensions/registries/protocol-handler";
// IPC channel for protocol actions. Main broadcasts the open-url events to this channel.
export const ProtocolHandlerIpcPrefix = "protocol-handler";

View File

@ -26,4 +26,4 @@ export type { KubeObjectStatusRegistration } from "../registries/kube-object-sta
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry";
export type { PageMenuRegistration, ClusterPageMenuRegistration, PageMenuComponents } from "../registries/page-menu-registry";
export type { StatusBarRegistration } from "../registries/status-bar-registry";
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler-registry";
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler";

View File

@ -221,11 +221,13 @@ export class ExtensionLoader extends Singleton {
}
loadOnMain() {
registries.MenuRegistry.createInstance();
logger.debug(`${logModule}: load on main`);
this.autoInitExtensions(async (extension: LensMainExtension) => {
// Each .add returns a function to remove the item
const removeItems = [
registries.menuRegistry.add(extension.appMenus)
registries.MenuRegistry.getInstance().add(extension.appMenus)
];
this.events.on("remove", (removedExtension: LensRendererExtension) => {
@ -244,13 +246,13 @@ export class ExtensionLoader extends Singleton {
logger.debug(`${logModule}: load on main renderer (cluster manager)`);
this.autoInitExtensions(async (extension: LensRendererExtension) => {
const removeItems = [
registries.globalPageRegistry.add(extension.globalPages, extension),
registries.appPreferenceRegistry.add(extension.appPreferences),
registries.entitySettingRegistry.add(extension.entitySettings),
registries.statusBarRegistry.add(extension.statusBarItems),
registries.commandRegistry.add(extension.commands),
registries.welcomeMenuRegistry.add(extension.welcomeMenus),
registries.catalogEntityDetailRegistry.add(extension.catalogEntityDetailItems),
registries.GlobalPageRegistry.getInstance().add(extension.globalPages, extension),
registries.AppPreferenceRegistry.getInstance().add(extension.appPreferences),
registries.EntitySettingRegistry.getInstance().add(extension.entitySettings),
registries.StatusBarRegistry.getInstance().add(extension.statusBarItems),
registries.CommandRegistry.getInstance().add(extension.commands),
registries.WelcomeMenuRegistry.getInstance().add(extension.welcomeMenus),
registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems),
];
this.events.on("remove", (removedExtension: LensRendererExtension) => {
@ -275,13 +277,13 @@ export class ExtensionLoader extends Singleton {
}
const removeItems = [
registries.clusterPageRegistry.add(extension.clusterPages, extension),
registries.clusterPageMenuRegistry.add(extension.clusterPageMenus, extension),
registries.kubeObjectMenuRegistry.add(extension.kubeObjectMenuItems),
registries.kubeObjectDetailRegistry.add(extension.kubeObjectDetailItems),
registries.kubeObjectStatusRegistry.add(extension.kubeObjectStatusTexts),
registries.workloadsOverviewDetailRegistry.add(extension.kubeWorkloadsOverviewItems),
registries.commandRegistry.add(extension.commands),
registries.ClusterPageRegistry.getInstance().add(extension.clusterPages, extension),
registries.ClusterPageMenuRegistry.getInstance().add(extension.clusterPageMenus, extension),
registries.KubeObjectMenuRegistry.getInstance().add(extension.kubeObjectMenuItems),
registries.KubeObjectDetailRegistry.getInstance().add(extension.kubeObjectDetailItems),
registries.KubeObjectStatusRegistry.getInstance().add(extension.kubeObjectStatusTexts),
registries.WorkloadsOverviewDetailRegistry.getInstance().add(extension.kubeWorkloadsOverviewItems),
registries.CommandRegistry.getInstance().add(extension.commands),
];
this.events.on("remove", (removedExtension: LensRendererExtension) => {

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { getExtensionPageUrl, globalPageRegistry, PageParams } from "../page-registry";
import { ClusterPageRegistry, getExtensionPageUrl, GlobalPageRegistry, PageParams } from "../page-registry";
import { LensExtension } from "../../lens-extension";
import React from "react";
import { Console } from "console";
@ -43,7 +43,8 @@ describe("getPageUrl", () => {
isEnabled: true,
isCompatible: true
});
globalPageRegistry.add({
ClusterPageRegistry.createInstance();
GlobalPageRegistry.createInstance().add({
id: "page-with-params",
components: {
Page: () => React.createElement("Page with params")
@ -55,6 +56,11 @@ describe("getPageUrl", () => {
}, ext);
});
afterEach(() => {
GlobalPageRegistry.resetInstance();
ClusterPageRegistry.resetInstance();
});
it("returns a page url for extension", () => {
expect(getExtensionPageUrl({ extensionId: ext.name })).toBe("/extension/foo-bar");
});
@ -111,7 +117,8 @@ describe("globalPageRegistry", () => {
isEnabled: true,
isCompatible: true
});
globalPageRegistry.add([
ClusterPageRegistry.createInstance();
GlobalPageRegistry.createInstance().add([
{
id: "test-page",
components: {
@ -132,9 +139,14 @@ describe("globalPageRegistry", () => {
], ext);
});
afterEach(() => {
GlobalPageRegistry.resetInstance();
ClusterPageRegistry.resetInstance();
});
describe("getByPageTarget", () => {
it("matching to first registered page without id", () => {
const page = globalPageRegistry.getByPageTarget({ extensionId: ext.name });
const page = GlobalPageRegistry.getInstance().getByPageTarget({ extensionId: ext.name });
expect(page.id).toEqual(undefined);
expect(page.extensionId).toEqual(ext.name);
@ -142,7 +154,7 @@ describe("globalPageRegistry", () => {
});
it("returns matching page", () => {
const page = globalPageRegistry.getByPageTarget({
const page = GlobalPageRegistry.getInstance().getByPageTarget({
pageId: "test-page",
extensionId: ext.name
});
@ -151,7 +163,7 @@ describe("globalPageRegistry", () => {
});
it("returns null if target not found", () => {
const page = globalPageRegistry.getByPageTarget({
const page = GlobalPageRegistry.getInstance().getByPageTarget({
pageId: "wrong-page",
extensionId: ext.name
});

View File

@ -46,5 +46,3 @@ export class AppPreferenceRegistry extends BaseRegistry<AppPreferenceRegistratio
};
}
}
export const appPreferenceRegistry = new AppPreferenceRegistry();

View File

@ -21,12 +21,14 @@
// Base class for extensions-api registries
import { action, observable, makeObservable } from "mobx";
import { Singleton } from "../../common/utils";
import { LensExtension } from "../lens-extension";
export class BaseRegistry<T, I = T> {
export class BaseRegistry<T, I = T> extends Singleton {
private items = observable.map<T, I>([], {deep: false});
constructor() {
super();
makeObservable(this);
}

View File

@ -42,5 +42,3 @@ export class CatalogEntityDetailRegistry extends BaseRegistry<CatalogEntityDetai
return items.sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
}
}
export const catalogEntityDetailRegistry = new CatalogEntityDetailRegistry();

View File

@ -50,5 +50,3 @@ export class CommandRegistry extends BaseRegistry<CommandRegistration> {
return super.add(filteredItems, extension);
}
}
export const commandRegistry = new CommandRegistry();

View File

@ -68,5 +68,3 @@ export class EntitySettingRegistry extends BaseRegistry<EntitySettingRegistratio
return items.sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
}
}
export const entitySettingRegistry = new EntitySettingRegistry();

View File

@ -32,6 +32,6 @@ export * from "./kube-object-status-registry";
export * from "./command-registry";
export * from "./entity-setting-registry";
export * from "./welcome-menu-registry";
export * from "./protocol-handler-registry";
export * from "./catalog-entity-detail-registry";
export * from "./workloads-overview-detail-registry";
export * from "./protocol-handler";

View File

@ -20,10 +20,12 @@
*/
import type React from "react";
import type { KubeObjectDetailsProps } from "../renderer-api/components";
import type { KubeObject } from "../renderer-api/k8s-api";
import { BaseRegistry } from "./base-registry";
export interface KubeObjectDetailComponents {
Details: React.ComponentType<any>;
Details: React.ComponentType<KubeObjectDetailsProps<KubeObject>>;
}
export interface KubeObjectDetailRegistration {
@ -42,5 +44,3 @@ export class KubeObjectDetailRegistry extends BaseRegistry<KubeObjectDetailRegis
return items.sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
}
}
export const kubeObjectDetailRegistry = new KubeObjectDetailRegistry();

View File

@ -39,5 +39,3 @@ export class KubeObjectMenuRegistry extends BaseRegistry<KubeObjectMenuRegistrat
});
}
}
export const kubeObjectMenuRegistry = new KubeObjectMenuRegistry();

View File

@ -43,5 +43,3 @@ export class KubeObjectStatusRegistry extends BaseRegistry<KubeObjectStatusRegis
.filter(Boolean);
}
}
export const kubeObjectStatusRegistry = new KubeObjectStatusRegistry();

View File

@ -30,5 +30,3 @@ export interface MenuRegistration extends MenuItemConstructorOptions {
export class MenuRegistry extends BaseRegistry<MenuRegistration> {
}
export const menuRegistry = new MenuRegistry();

View File

@ -75,5 +75,3 @@ export class ClusterPageMenuRegistry extends PageMenuRegistry<ClusterPageMenuReg
));
}
}
export const clusterPageMenuRegistry = new ClusterPageMenuRegistry();

View File

@ -75,7 +75,7 @@ export function getExtensionPageUrl(target: PageTarget): string {
const pageUrl = new URL(pagePath, `http://localhost`);
// stringify params to matched target page
const registeredPage = globalPageRegistry.getByPageTarget(target) || clusterPageRegistry.getByPageTarget(target);
const registeredPage = GlobalPageRegistry.getInstance().getByPageTarget(target) || ClusterPageRegistry.getInstance().getByPageTarget(target);
if (registeredPage?.params) {
Object.entries(registeredPage.params).forEach(([name, param]) => {
@ -91,7 +91,7 @@ export function getExtensionPageUrl(target: PageTarget): string {
return pageUrl.href.replace(pageUrl.origin, "");
}
export class PageRegistry extends BaseRegistry<PageRegistration, RegisteredPage> {
class PageRegistry extends BaseRegistry<PageRegistration, RegisteredPage> {
protected getRegisteredItem(page: PageRegistration, ext: LensExtension): RegisteredPage {
const { id: pageId } = page;
const extensionId = ext.name;
@ -157,5 +157,5 @@ export class PageRegistry extends BaseRegistry<PageRegistration, RegisteredPage>
}
}
export const globalPageRegistry = new PageRegistry();
export const clusterPageRegistry = new PageRegistry();
export class ClusterPageRegistry extends PageRegistry {}
export class GlobalPageRegistry extends PageRegistry {}

View File

@ -41,5 +41,3 @@ export interface StatusBarRegistration extends StatusBarRegistrationV2 {
export class StatusBarRegistry extends BaseRegistry<StatusBarRegistration> {
}
export const statusBarRegistry = new StatusBarRegistry();

View File

@ -28,5 +28,3 @@ export interface WelcomeMenuRegistration {
}
export class WelcomeMenuRegistry extends BaseRegistry<WelcomeMenuRegistration> {}
export const welcomeMenuRegistry = new WelcomeMenuRegistry();

View File

@ -38,5 +38,3 @@ export class WorkloadsOverviewDetailRegistry extends BaseRegistry<WorkloadsOverv
return items.sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
}
}
export const workloadsOverviewDetailRegistry = new WorkloadsOverviewDetailRegistry();

View File

@ -56,7 +56,8 @@ import { HelmRepoManager } from "./helm/helm-repo-manager";
import { KubeconfigSyncManager } from "./catalog-sources";
import { handleWsUpgrade } from "./proxy/ws-upgrade";
import configurePackages from "../common/configure-packages";
import { PrometheusProviderRegistry, registerDefaultPrometheusProviders } from "./prometheus";
import { PrometheusProviderRegistry } from "./prometheus";
import { initRegistries, initPrometheusProviderRegistry } from "./initializers";
const workingDir = path.join(app.getPath("appData"), appName);
const cleanup = disposer();
@ -124,7 +125,7 @@ app.on("ready", async () => {
registerFileProtocol("static", __static);
PrometheusProviderRegistry.createInstance();
registerDefaultPrometheusProviders();
initPrometheusProviderRegistry();
const userStore = UserStore.createInstance();
const clusterStore = ClusterStore.createInstance();
@ -173,6 +174,7 @@ app.on("ready", async () => {
app.exit();
}
initRegistries();
const extensionDiscovery = ExtensionDiscovery.createInstance();
ExtensionLoader.createInstance().init();

View File

@ -19,20 +19,5 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import { helmChartsURL, releaseURL } from "../../../common/routes";
commandRegistry.add({
id: "cluster.viewHelmCharts",
title: "Cluster: View Helm Charts",
scope: "entity",
action: () => navigate(helmChartsURL())
});
commandRegistry.add({
id: "cluster.viewHelmReleases",
title: "Cluster: View Helm Releases",
scope: "entity",
action: () => navigate(releaseURL())
});
export * from "./registries";
export * from "./metrics-providers";

View File

@ -19,34 +19,17 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import * as routes from "../../../common/routes";
import { PrometheusProviderRegistry } from "../prometheus";
import { PrometheusHelm } from "../prometheus/helm";
import { PrometheusLens } from "../prometheus/lens";
import { PrometheusOperator } from "../prometheus/operator";
import { PrometheusStacklight } from "../prometheus/stacklight";
commandRegistry.add({
id: "cluster.viewServices",
title: "Cluster: View Services",
scope: "entity",
action: () => navigate(routes.servicesURL())
});
commandRegistry.add({
id: "cluster.viewEndpoints",
title: "Cluster: View Endpoints",
scope: "entity",
action: () => navigate(routes.endpointURL())
});
commandRegistry.add({
id: "cluster.viewIngresses",
title: "Cluster: View Ingresses",
scope: "entity",
action: () => navigate(routes.ingressURL())
});
commandRegistry.add({
id: "cluster.viewNetworkPolicies",
title: "Cluster: View NetworkPolicies",
scope: "entity",
action: () => navigate(routes.networkPoliciesURL())
});
export function initPrometheusProviderRegistry() {
PrometheusProviderRegistry
.getInstance()
.registerProvider(new PrometheusLens())
.registerProvider(new PrometheusHelm())
.registerProvider(new PrometheusOperator())
.registerProvider(new PrometheusStacklight());
}

View File

@ -19,13 +19,8 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import { nodesURL } from "../../../common/routes";
import * as registries from "../../extensions/registries";
commandRegistry.add({
id: "cluster.viewNodes",
title: "Cluster: View Nodes",
scope: "entity",
action: () => navigate(nodesURL())
});
export function initRegistries() {
registries.MenuRegistry.createInstance();
}

View File

@ -23,7 +23,7 @@ import { app, BrowserWindow, dialog, ipcMain, IpcMainEvent, Menu, MenuItem, Menu
import { autorun } from "mobx";
import type { WindowManager } from "./window-manager";
import { appName, isMac, isWindows, isTestEnv, docsUrl, supportUrl, productName } from "../common/vars";
import { menuRegistry } from "../extensions/registries/menu-registry";
import { MenuRegistry } from "../extensions/registries/menu-registry";
import logger from "./logger";
import { exitApp } from "./exit-app";
import { broadcastMessage } from "../common/ipc";
@ -255,7 +255,7 @@ export function buildMenu(windowManager: WindowManager) {
};
// Modify menu from extensions-api
menuRegistry.getItems().forEach(({ parentId, ...menuItem }) => {
MenuRegistry.getInstance().getItems().forEach(({ parentId, ...menuItem }) => {
try {
const topMenu = appMenu[parentId as MenuTopId].submenu as MenuItemConstructorOptions[];

View File

@ -19,19 +19,4 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { PrometheusHelm } from "./helm";
import { PrometheusLens } from "./lens";
import { PrometheusOperator } from "./operator";
import { PrometheusProviderRegistry } from "./provider-registry";
import { PrometheusStacklight } from "./stacklight";
export * from "./provider-registry";
export function registerDefaultPrometheusProviders() {
PrometheusProviderRegistry
.getInstance()
.registerProvider(new PrometheusLens())
.registerProvider(new PrometheusHelm())
.registerProvider(new PrometheusOperator())
.registerProvider(new PrometheusStacklight());
}

View File

@ -19,4 +19,4 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
export { kubeObjectDetailRegistry } from "../../extensions/registries/kube-object-detail-registry";
export { KubeObjectDetailRegistry } from "../../extensions/registries/kube-object-detail-registry";

View File

@ -45,6 +45,7 @@ import { HelmRepoManager } from "../main/helm/helm-repo-manager";
import { ExtensionInstallationStateStore } from "./components/+extensions/extension-install.store";
import { DefaultProps } from "./mui-base-theme";
import configurePackages from "../common/configure-packages";
import * as initializers from "./initializers";
configurePackages();
@ -69,6 +70,14 @@ export async function bootstrap(App: AppComponent) {
await attachChromeDebugger();
rootElem.classList.toggle("is-mac", isMac);
initializers.initRegistries();
initializers.initCommandRegistry();
initializers.initEntitySettingsRegistry();
initializers.initKubeObjectMenuRegistry();
initializers.intiKubeObjectDetailRegistry();
initializers.initWelcomeMenuRegistry();
initializers.initWorkloadsOverviewDetailRegistry();
ExtensionLoader.createInstance().init();
ExtensionDiscovery.createInstance().init();

View File

@ -20,4 +20,3 @@
*/
export * from "./apps";
export * from "./apps.command";

View File

@ -28,7 +28,7 @@ import type { CatalogCategory } from "../../../common/catalog";
import { Icon } from "../icon";
import { KubeObject } from "../../api/kube-object";
import { CatalogEntityDrawerMenu } from "./catalog-entity-drawer-menu";
import { catalogEntityDetailRegistry } from "../../../extensions/registries";
import { CatalogEntityDetailRegistry } from "../../../extensions/registries";
import { HotbarIcon } from "../hotbar/hotbar-icon";
interface Props {
@ -63,7 +63,7 @@ export class CatalogEntityDetails extends Component<Props> {
renderContent() {
const { entity } = this.props;
const labels = KubeObject.stringifyLabels(entity.metadata.labels);
const detailItems = catalogEntityDetailRegistry.getItemsForKind(entity.kind, entity.apiVersion);
const detailItems = CatalogEntityDetailRegistry.getInstance().getItemsForKind(entity.kind, entity.apiVersion);
const details = detailItems.map((item, index) => {
return <item.components.Details entity={entity} key={index}/>;
});

View File

@ -29,11 +29,9 @@ import { Badge } from "../badge";
import { KubeObjectDetailsProps, getDetailsUrl } from "../kube-object";
import { cssNames } from "../../utils";
import { HorizontalPodAutoscaler, HpaMetricType, IHpaMetric } from "../../api/endpoints/hpa.api";
import { KubeEventDetails } from "../+events/kube-event-details";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { lookupApiLink } from "../../api/kube-api";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<HorizontalPodAutoscaler> {
}
@ -150,20 +148,3 @@ export class HpaDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "HorizontalPodAutoscaler",
apiVersions: ["autoscaling/v2beta1"],
components: {
Details: (props) => <HpaDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "HorizontalPodAutoscaler",
apiVersions: ["autoscaling/v2beta1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -25,7 +25,6 @@ import React from "react";
import { observer } from "mobx-react";
import type { KubeObjectDetailsProps } from "../kube-object";
import { LimitPart, LimitRange, LimitRangeItem, Resource } from "../../api/endpoints/limit-range.api";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { DrawerItem } from "../drawer/drawer-item";
import { Badge } from "../badge";
@ -108,11 +107,3 @@ export class LimitRangeDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "LimitRange",
apiVersions: ["v1"],
components: {
Details: (props) => <LimitRangeDetails {...props} />
}
});

View File

@ -28,12 +28,10 @@ import { DrawerTitle } from "../drawer";
import { Notifications } from "../notifications";
import { Input } from "../input";
import { Button } from "../button";
import { KubeEventDetails } from "../+events/kube-event-details";
import { configMapsStore } from "./config-maps.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { ConfigMap } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<ConfigMap> {
}
@ -123,20 +121,3 @@ export class ConfigMapDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "ConfigMap",
apiVersions: ["v1"],
components: {
Details: (props) => <ConfigMapDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "ConfigMap",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -28,7 +28,6 @@ import { Badge } from "../badge";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { PodDisruptionBudget } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<PodDisruptionBudget> {
}
@ -74,11 +73,3 @@ export class PodDisruptionBudgetDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "PodDisruptionBudget",
apiVersions: ["policy/v1beta1"],
components: {
Details: (props) => <PodDisruptionBudgetDetails {...props} />
}
});

View File

@ -30,7 +30,6 @@ import type { ResourceQuota } from "../../api/endpoints/resource-quota.api";
import { LineProgress } from "../line-progress";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<ResourceQuota> {
}
@ -117,11 +116,3 @@ export class ResourceQuotaDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "ResourceQuota",
apiVersions: ["v1"],
components: {
Details: (props) => <ResourceQuotaDetails {...props} />
}
});

View File

@ -35,7 +35,6 @@ import { secretsStore } from "./secrets.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { Secret } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<Secret> {
}
@ -143,11 +142,3 @@ export class SecretDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Secret",
apiVersions: ["v1"],
components: {
Details: (props) => <SecretDetails {...props} />
}
});

View File

@ -1,66 +0,0 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import * as routes from "../../../common/routes";
commandRegistry.add({
id: "cluster.viewConfigMaps",
title: "Cluster: View ConfigMaps",
scope: "entity",
action: () => navigate(routes.configMapsURL())
});
commandRegistry.add({
id: "cluster.viewSecrets",
title: "Cluster: View Secrets",
scope: "entity",
action: () => navigate(routes.secretsURL())
});
commandRegistry.add({
id: "cluster.viewResourceQuotas",
title: "Cluster: View ResourceQuotas",
scope: "entity",
action: () => navigate(routes.resourceQuotaURL())
});
commandRegistry.add({
id: "cluster.viewLimitRanges",
title: "Cluster: View LimitRanges",
scope: "entity",
action: () => navigate(routes.limitRangeURL())
});
commandRegistry.add({
id: "cluster.viewHorizontalPodAutoscalers",
title: "Cluster: View HorizontalPodAutoscalers (HPA)",
scope: "entity",
action: () => navigate(routes.hpaURL())
});
commandRegistry.add({
id: "cluster.viewPodDisruptionBudget",
title: "Cluster: View PodDisruptionBudgets",
scope: "entity",
action: () => navigate(routes.pdbURL())
});

View File

@ -20,4 +20,3 @@
*/
export * from "./config";
export * from "./config.command";

View File

@ -33,7 +33,6 @@ import type { KubeObjectDetailsProps } from "../kube-object";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { Input } from "../input";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<CustomResourceDefinition> {
}
@ -156,11 +155,3 @@ export class CRDDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "CustomResourceDefinition",
apiVersions: ["apiextensions.k8s.io/v1", "apiextensions.k8s.io/v1beta1"],
components: {
Details: (props) => <CRDDetails {...props} />
}
});

View File

@ -30,7 +30,7 @@ import { navigation } from "../../navigation";
import { Tabs, Tab } from "../tabs";
import type { CatalogEntity } from "../../api/catalog-entity";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
import { entitySettingRegistry } from "../../../extensions/registries";
import { EntitySettingRegistry } from "../../../extensions/registries";
import type { EntitySettingsRouteParams } from "../../../common/routes";
import { groupBy } from "lodash";
@ -57,7 +57,7 @@ export class EntitySettings extends React.Component<Props> {
get menuItems() {
if (!this.entity) return [];
return entitySettingRegistry.getItemsForKind(this.entity.kind, this.entity.apiVersion, this.entity.metadata.source);
return EntitySettingRegistry.getInstance().getItemsForKind(this.entity.kind, this.entity.apiVersion, this.entity.metadata.source);
}
async componentDidMount() {

View File

@ -31,7 +31,6 @@ import type { KubeEvent } from "../../api/endpoints/events.api";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { lookupApiLink } from "../../api/kube-api";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { LocaleDate } from "../locale-date";
interface Props extends KubeObjectDetailsProps<KubeEvent> {
@ -95,11 +94,3 @@ export class EventDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Event",
apiVersions: ["v1"],
components: {
Details: (props) => <EventDetails {...props}/>
}
});

View File

@ -32,7 +32,6 @@ import { Link } from "react-router-dom";
import { Spinner } from "../spinner";
import { resourceQuotaStore } from "../+config-resource-quotas/resource-quotas.store";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { limitRangeStore } from "../+config-limit-ranges/limit-ranges.store";
interface Props extends KubeObjectDetailsProps<Namespace> {
@ -100,11 +99,3 @@ export class NamespaceDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Namespace",
apiVersions: ["v1"],
components: {
Details: (props) => <NamespaceDetails {...props} />
}
});

View File

@ -24,12 +24,10 @@ import "./endpoint-details.scss";
import React from "react";
import { observer } from "mobx-react";
import { DrawerTitle } from "../drawer";
import { KubeEventDetails } from "../+events/kube-event-details";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { Endpoint } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { EndpointSubsetList } from "./endpoint-subset-list";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<Endpoint> {
}
@ -54,19 +52,3 @@ export class EndpointDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Endpoints",
apiVersions: ["v1"],
components: {
Details: (props) => <EndpointDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "Endpoints",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -27,13 +27,11 @@ import { reaction } from "mobx";
import { DrawerItem, DrawerTitle } from "../drawer";
import type { ILoadBalancerIngress, Ingress } from "../../api/endpoints";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { KubeEventDetails } from "../+events/kube-event-details";
import { ingressStore } from "./ingress.store";
import { ResourceMetrics } from "../resource-metrics";
import type { KubeObjectDetailsProps } from "../kube-object";
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 { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -167,19 +165,3 @@ export class IngressDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Ingress",
apiVersions: ["networking.k8s.io/v1", "extensions/v1beta1"],
components: {
Details: (props) => <IngressDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "Ingress",
apiVersions: ["networking.k8s.io/v1", "extensions/v1beta1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -27,11 +27,9 @@ import { DrawerItem, DrawerTitle } from "../drawer";
import type { IPolicyEgress, IPolicyIngress, IPolicyIpBlock, IPolicySelector, NetworkPolicy } from "../../api/endpoints/network-policy.api";
import { Badge } from "../badge";
import { SubTitle } from "../layout/sub-title";
import { KubeEventDetails } from "../+events/kube-event-details";
import { observer } from "mobx-react";
import type { KubeObjectDetailsProps } from "../kube-object";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<NetworkPolicy> {
}
@ -172,20 +170,3 @@ export class NetworkPolicyDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "NetworkPolicy",
apiVersions: ["networking.k8s.io/v1"],
components: {
Details: (props) => <NetworkPolicyDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "NetworkPolicy",
apiVersions: ["networking.k8s.io/v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -25,14 +25,12 @@ import React from "react";
import { disposeOnUnmount, observer } from "mobx-react";
import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import { KubeEventDetails } from "../+events/kube-event-details";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { Service } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { ServicePortComponent } from "./service-port-component";
import { endpointStore } from "../+network-endpoints/endpoints.store";
import { ServiceDetailsEndpoint } from "./service-details-endpoint";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { kubeWatchApi } from "../../api/kube-watch-api";
interface Props extends KubeObjectDetailsProps<Service> {
@ -121,20 +119,3 @@ export class ServiceDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Service",
apiVersions: ["v1"],
components: {
Details: (props) => <ServiceDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "Service",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -20,4 +20,3 @@
*/
export * from "./network";
export * from "./network.command";

View File

@ -21,4 +21,3 @@
export * from "./nodes";
export * from "./node-details";
export * from "./node.command";

View File

@ -36,8 +36,6 @@ import { NodeCharts } from "./node-charts";
import { reaction } from "mobx";
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 { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
import { NodeDetailsResources } from "./node-details-resources";
@ -173,20 +171,3 @@ export class NodeDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Node",
apiVersions: ["v1"],
components: {
Details: (props) => <NodeDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "Node",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -29,7 +29,6 @@ import type { PodSecurityPolicy } from "../../api/endpoints";
import { Badge } from "../badge";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<PodSecurityPolicy> {
}
@ -231,11 +230,3 @@ export class PodSecurityPolicyDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "PodSecurityPolicy",
apiVersions: ["policy/v1beta1"],
components: {
Details: (props) => <PodSecurityPolicyDetails {...props}/>
}
});

View File

@ -27,7 +27,7 @@ import { computed, observable, reaction, makeObservable } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import { isWindows } from "../../../common/vars";
import { appPreferenceRegistry, RegisteredAppPreference } from "../../../extensions/registries/app-preference-registry";
import { AppPreferenceRegistry, RegisteredAppPreference } from "../../../extensions/registries/app-preference-registry";
import { UserStore } from "../../../common/user-store";
import { ThemeStore } from "../../theme.store";
import { Input } from "../input";
@ -93,7 +93,7 @@ export class Preferences extends React.Component {
};
renderNavigation() {
const extensions = appPreferenceRegistry.getItems().filter(e => !e.showInPreferencesTab);
const extensions = AppPreferenceRegistry.getInstance().getItems().filter(e => !e.showInPreferencesTab);
return (
<Tabs className="flex column" scrollable={false} onChange={this.onTabChange} value={this.activeTab}>
@ -125,7 +125,7 @@ export class Preferences extends React.Component {
}
render() {
const extensions = appPreferenceRegistry.getItems();
const extensions = AppPreferenceRegistry.getInstance().getItems();
const telemetryExtensions = extensions.filter(e => e.showInPreferencesTab == Pages.Telemetry);
const defaultShell = process.env.SHELL
|| process.env.PTYSHELL

View File

@ -25,12 +25,10 @@ import React from "react";
import startCase from "lodash/startCase";
import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import { KubeEventDetails } from "../+events/kube-event-details";
import { observer } from "mobx-react";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { StorageClass } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { storageClassStore } from "./storage-class.store";
import { VolumeDetailsList } from "../+storage-volumes/volume-details-list";
import { volumesStore } from "../+storage-volumes/volumes.store";
@ -89,20 +87,3 @@ export class StorageClassDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "StorageClass",
apiVersions: ["storage.k8s.io/v1"],
components: {
Details: (props) => <StorageClassDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "StorageClass",
apiVersions: ["storage.k8s.io/v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -28,13 +28,11 @@ import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import { podsStore } from "../+workloads-pods/pods.store";
import { Link } from "react-router-dom";
import { KubeEventDetails } from "../+events/kube-event-details";
import { volumeClaimStore } from "./volume-claim.store";
import { ResourceMetrics } from "../resource-metrics";
import { VolumeClaimDiskChart } from "./volume-claim-disk-chart";
import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object";
import type { PersistentVolumeClaim } from "../../api/endpoints";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -116,20 +114,3 @@ export class PersistentVolumeClaimDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "PersistentVolumeClaim",
apiVersions: ["v1"],
components: {
Details: (props) => <PersistentVolumeClaimDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "PersistentVolumeClaim",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -27,11 +27,9 @@ import { Link } from "react-router-dom";
import { observer } from "mobx-react";
import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import { KubeEventDetails } from "../+events/kube-event-details";
import { PersistentVolume, pvcApi } from "../../api/endpoints";
import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<PersistentVolume> {
}
@ -121,20 +119,3 @@ export class PersistentVolumeDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "PersistentVolume",
apiVersions: ["v1"],
components: {
Details: (props) => <PersistentVolumeDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "PersistentVolume",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -25,9 +25,7 @@ import { reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import React from "react";
import { KubeEventDetails } from "../../+events/kube-event-details";
import type { ClusterRoleBinding, ClusterRoleBindingSubject } from "../../../api/endpoints";
import { kubeObjectDetailRegistry } from "../../../api/kube-object-detail-registry";
import { autoBind, ObservableHashSet, prevDefault } from "../../../utils";
import { AddRemoveButtons } from "../../add-remove-buttons";
import { ConfirmDialog } from "../../confirm-dialog";
@ -139,19 +137,3 @@ export class ClusterRoleBindingDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "ClusterRoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props) => <ClusterRoleBindingDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "ClusterRoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -24,8 +24,6 @@ import "./details.scss";
import { observer } from "mobx-react";
import React from "react";
import { KubeEventDetails } from "../../+events/kube-event-details";
import { kubeObjectDetailRegistry } from "../../../api/kube-object-detail-registry";
import { DrawerTitle } from "../../drawer";
import type { KubeObjectDetailsProps } from "../../kube-object";
import { KubeObjectMeta } from "../../kube-object/kube-object-meta";
@ -86,19 +84,3 @@ export class ClusterRoleDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "ClusterRole",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props) => <ClusterRoleDetails {...props}/>
}
});
kubeObjectDetailRegistry.add({
kind: "ClusterRole",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props}/>
}
});

View File

@ -24,9 +24,7 @@ import "./details.scss";
import { reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import React from "react";
import { KubeEventDetails } from "../../+events/kube-event-details";
import type { RoleBinding, RoleBindingSubject } from "../../../api/endpoints";
import { kubeObjectDetailRegistry } from "../../../api/kube-object-detail-registry";
import { prevDefault, boundMethod } from "../../../utils";
import { AddRemoveButtons } from "../../add-remove-buttons";
import { ConfirmDialog } from "../../confirm-dialog";
@ -137,19 +135,3 @@ export class RoleBindingDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "RoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props) => <RoleBindingDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "RoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -24,9 +24,7 @@ import "./details.scss";
import { observer } from "mobx-react";
import React from "react";
import { KubeEventDetails } from "../../+events/kube-event-details";
import type { Role } from "../../../api/endpoints";
import { kubeObjectDetailRegistry } from "../../../api/kube-object-detail-registry";
import { DrawerTitle } from "../../drawer";
import type { KubeObjectDetailsProps } from "../../kube-object";
import { KubeObjectMeta } from "../../kube-object/kube-object-meta";
@ -85,19 +83,3 @@ export class RoleDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Role",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props) => <RoleDetails {...props}/>
}
});
kubeObjectDetailRegistry.add({
kind: "Role",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -27,9 +27,7 @@ import React from "react";
import { Link } from "react-router-dom";
import { secretsStore } from "../../+config-secrets/secrets.store";
import { KubeEventDetails } from "../../+events/kube-event-details";
import { Secret, ServiceAccount } from "../../../api/endpoints";
import { kubeObjectDetailRegistry } from "../../../api/kube-object-detail-registry";
import { DrawerItem, DrawerTitle } from "../../drawer";
import { Icon } from "../../icon";
import { getDetailsUrl, KubeObjectDetailsProps } from "../../kube-object";
@ -164,19 +162,3 @@ export class ServiceAccountsDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "ServiceAccount",
apiVersions: ["v1"],
components: {
Details: (props) => <ServiceAccountsDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "ServiceAccount",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -24,7 +24,6 @@ import "./view.scss";
import { observer } from "mobx-react";
import React from "react";
import type { RouteComponentProps } from "react-router";
import { kubeObjectMenuRegistry } from "../../../../extensions/registries/kube-object-menu-registry";
import type { ServiceAccount } from "../../../api/endpoints/service-accounts.api";
import { Icon } from "../../icon";
import { KubeObjectListLayout } from "../../kube-object";
@ -89,21 +88,13 @@ export class ServiceAccounts extends React.Component<Props> {
}
}
function ServiceAccountMenu(props: KubeObjectMenuProps<ServiceAccount>) {
export function ServiceAccountMenu(props: KubeObjectMenuProps<ServiceAccount>) {
const { object, toolbar } = props;
return (
<MenuItem onClick={() => openServiceAccountKubeConfig(object)}>
<Icon material="insert_drive_file" title="Kubeconfig File" interactive={toolbar}/>
<Icon material="insert_drive_file" title="Kubeconfig File" interactive={toolbar} />
<span className="title">Kubeconfig</span>
</MenuItem>
);
}
kubeObjectMenuRegistry.add({
kind: "ServiceAccount",
apiVersions: ["v1"],
components: {
MenuItem: ServiceAccountMenu
}
});

View File

@ -24,33 +24,10 @@ import React from "react";
import { observer } from "mobx-react";
import { Icon } from "../icon";
import { productName, slackUrl } from "../../../common/vars";
import { welcomeMenuRegistry } from "../../../extensions/registries";
import { navigate } from "../../navigation";
import { catalogURL, preferencesURL } from "../../../common/routes";
import { WelcomeMenuRegistry } from "../../../extensions/registries";
@observer
export class Welcome extends React.Component {
componentDidMount() {
if (welcomeMenuRegistry.getItems().find((item) => item.title === "Browse Your Catalog")) {
return;
}
welcomeMenuRegistry.add({
title: "Browse Your Catalog",
icon: "view_list",
click: () => navigate(catalogURL())
});
if (welcomeMenuRegistry.getItems().length === 1) {
welcomeMenuRegistry.add({
title: "Configure Preferences",
icon: "settings",
click: () => navigate(preferencesURL())
});
}
}
render() {
return (
<div className="Welcome flex justify-center align-center">
@ -65,7 +42,7 @@ export class Welcome extends React.Component {
</p>
<ul className="box">
{ welcomeMenuRegistry.getItems().map((item, index) => (
{WelcomeMenuRegistry.getInstance().getItems().map((item, index) => (
<li key={index} className="flex grid-12" onClick={() => item.click()}>
<Icon material={item.icon} className="box col-1" /> <a className="box col-10">{typeof item.title === "string" ? item.title : item.title()}</a> <Icon material="navigate_next" className="box col-1" />
</li>

View File

@ -28,12 +28,10 @@ import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge/badge";
import { jobStore } from "../+workloads-jobs/job.store";
import { Link } from "react-router-dom";
import { KubeEventDetails } from "../+events/kube-event-details";
import { cronJobStore } from "./cronjob.store";
import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object";
import type { CronJob, Job } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<CronJob> {
}
@ -105,19 +103,3 @@ export class CronJobDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
components: {
Details: (props) => <CronJobDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
priority: 5,
components: {
Details: (props) => <KubeEventDetails {...props} />
}
});

View File

@ -33,7 +33,6 @@ import { eventStore } from "../+events/event.store";
import type { KubeObjectMenuProps } from "../kube-object/kube-object-menu";
import { KubeObjectListLayout } from "../kube-object";
import { CronJobTriggerDialog } from "./cronjob-trigger-dialog";
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
import { ConfirmDialog } from "../confirm-dialog/confirm-dialog";
import { Notifications } from "../notifications/notifications";
@ -152,11 +151,3 @@ export function CronJobMenu(props: KubeObjectMenuProps<CronJob>) {
</>
);
}
kubeObjectMenuRegistry.add({
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
components: {
MenuItem: CronJobMenu
}
});

View File

@ -28,7 +28,6 @@ import { Badge } from "../badge";
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
import { KubeEventDetails } from "../+events/kube-event-details";
import { daemonSetStore } from "./daemonsets.store";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object";
@ -38,7 +37,6 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
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 { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -118,19 +116,3 @@ export class DaemonSetDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "DaemonSet",
apiVersions: ["apps/v1"],
components: {
Details: (props: any) => <DaemonSetDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "DaemonSet",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: any) => <KubeEventDetails {...props} />
}
});

View File

@ -30,7 +30,6 @@ import type { Deployment } from "../../api/endpoints";
import { cssNames } from "../../utils";
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
import { KubeEventDetails } from "../+events/kube-event-details";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
@ -39,7 +38,6 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
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 { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
import { DeploymentReplicaSets } from "./deployment-replicasets";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
@ -141,19 +139,3 @@ export class DeploymentDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Deployment",
apiVersions: ["apps/v1"],
components: {
Details: (props: any) => <DeploymentDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "Deployment",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: any) => <KubeEventDetails {...props} />
}
});

View File

@ -39,7 +39,6 @@ import { KubeObjectListLayout } from "../kube-object";
import { cssNames } from "../../utils";
import kebabCase from "lodash/kebabCase";
import orderBy from "lodash/orderBy";
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
import { Notifications } from "../notifications";
import type { DeploymentsRouteParams } from "../../../common/routes";
@ -153,11 +152,3 @@ export function DeploymentMenu(props: KubeObjectMenuProps<Deployment>) {
</>
);
}
kubeObjectMenuRegistry.add({
kind: "Deployment",
apiVersions: ["apps/v1"],
components: {
MenuItem: DeploymentMenu
}
});

View File

@ -30,7 +30,6 @@ import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
import { Link } from "react-router-dom";
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
import { KubeEventDetails } from "../+events/kube-event-details";
import { podsStore } from "../+workloads-pods/pods.store";
import { jobStore } from "./job.store";
import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object";
@ -38,7 +37,6 @@ import type { Job } from "../../api/endpoints";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { lookupApiLink } from "../../api/kube-api";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
interface Props extends KubeObjectDetailsProps<Job> {
}
@ -125,19 +123,3 @@ export class JobDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Job",
apiVersions: ["batch/v1"],
components: {
Details: (props: any) => <JobDetails {...props}/>
}
});
kubeObjectDetailRegistry.add({
kind: "Job",
apiVersions: ["batch/v1"],
priority: 5,
components: {
Details: (props: any) => <KubeEventDetails {...props}/>
}
});

View File

@ -23,7 +23,6 @@ import "./overview.scss";
import React from "react";
import { disposeOnUnmount, observer } from "mobx-react";
import { OverviewStatuses } from "./overview-statuses";
import type { RouteComponentProps } from "react-router";
import { eventStore } from "../+events/event.store";
import { podsStore } from "../+workloads-pods/pods.store";
@ -33,11 +32,9 @@ import { statefulSetStore } from "../+workloads-statefulsets/statefulset.store";
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
import { jobStore } from "../+workloads-jobs/job.store";
import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
import { Events } from "../+events";
import { isAllowedResource } from "../../../common/rbac";
import { kubeWatchApi } from "../../api/kube-watch-api";
import { clusterContext } from "../context";
import { workloadsOverviewDetailRegistry } from "../../../extensions/registries";
import { WorkloadsOverviewDetailRegistry } from "../../../extensions/registries";
import type { WorkloadsOverviewRouteParams } from "../../../common/routes";
interface Props extends RouteComponentProps<WorkloadsOverviewRouteParams> {
@ -58,7 +55,7 @@ export class WorkloadsOverview extends React.Component<Props> {
}
render() {
const items = workloadsOverviewDetailRegistry.getItems().map((item, index) => {
const items = WorkloadsOverviewDetailRegistry.getInstance().getItems().map((item, index) => {
return (
<item.components.Details key={`workload-overview-${index}`}/>
);
@ -71,21 +68,3 @@ export class WorkloadsOverview extends React.Component<Props> {
);
}
}
workloadsOverviewDetailRegistry.add([
{
components: {
Details: (props: any) => <OverviewStatuses {...props} />,
}
},
{
priority: 5,
components: {
Details: () => {
return (
isAllowedResource("events") && <Events compact hideFilters className="box grow"/>
);
}
}
}
]);

View File

@ -34,7 +34,6 @@ import { PodDetailsContainer } from "./pod-details-container";
import { PodDetailsAffinities } from "./pod-details-affinities";
import { PodDetailsTolerations } from "./pod-details-tolerations";
import { Icon } from "../icon";
import { KubeEventDetails } from "../+events/kube-event-details";
import { PodDetailsSecrets } from "./pod-details-secrets";
import { ResourceMetrics } from "../resource-metrics";
import { podsStore } from "./pods.store";
@ -42,7 +41,6 @@ import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object";
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 { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -261,20 +259,3 @@ export class PodDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "Pod",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<Pod>) => <PodDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "Pod",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<Pod>) => <KubeEventDetails {...props} />
}
});

View File

@ -28,7 +28,6 @@ import { replicaSetStore } from "./replicasets.store";
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
import { KubeEventDetails } from "../+events/kube-event-details";
import { disposeOnUnmount, observer } from "mobx-react";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object";
@ -37,7 +36,6 @@ import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
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 { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -118,19 +116,3 @@ export class ReplicaSetDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
components: {
Details: (props: any) => <ReplicaSetDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: any) => <KubeEventDetails {...props} />
}
});

View File

@ -31,7 +31,6 @@ import type { RouteComponentProps } from "react-router";
import { KubeObjectListLayout } from "../kube-object/kube-object-list-layout";
import { MenuItem } from "../menu/menu";
import { Icon } from "../icon/icon";
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog";
import type { ReplicaSetsRouteParams } from "../../../common/routes";
@ -105,11 +104,3 @@ export function ReplicaSetMenu(props: KubeObjectMenuProps<ReplicaSet>) {
</>
);
}
kubeObjectMenuRegistry.add({
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
components: {
MenuItem: ReplicaSetMenu
}
});

View File

@ -29,7 +29,6 @@ import { DrawerItem } from "../drawer";
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
import { KubeEventDetails } from "../+events/kube-event-details";
import { podsStore } from "../+workloads-pods/pods.store";
import { statefulSetStore } from "./statefulset.store";
import type { KubeObjectDetailsProps } from "../kube-object";
@ -38,7 +37,6 @@ import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
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 { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -116,20 +114,3 @@ export class StatefulSetDetails extends React.Component<Props> {
);
}
}
kubeObjectDetailRegistry.add({
kind: "StatefulSet",
apiVersions: ["apps/v1"],
components: {
Details: (props: any) => <StatefulSetDetails {...props} />
}
});
kubeObjectDetailRegistry.add({
kind: "StatefulSet",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: any) => <KubeEventDetails {...props} />
}
});

View File

@ -35,7 +35,6 @@ import { KubeObjectStatusIcon } from "../kube-object-status-icon";
import { StatefulSetScaleDialog } from "./statefulset-scale-dialog";
import { MenuItem } from "../menu/menu";
import { Icon } from "../icon/icon";
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
import type { StatefulSetsRouteParams } from "../../../common/routes";
enum columnId {
@ -110,11 +109,3 @@ export function StatefulSetMenu(props: KubeObjectMenuProps<StatefulSet>) {
</>
);
}
kubeObjectMenuRegistry.add({
kind: "StatefulSet",
apiVersions: ["apps/v1"],
components: {
MenuItem: StatefulSetMenu
}
});

View File

@ -21,4 +21,3 @@
export * from "./workloads";
export * from "./workloads.stores";
export * from "./workloads.command";

View File

@ -1,66 +0,0 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import * as routes from "../../../common/routes";
commandRegistry.add({
id: "cluster.viewPods",
title: "Cluster: View Pods",
scope: "entity",
action: () => navigate(routes.podsURL())
});
commandRegistry.add({
id: "cluster.viewDeployments",
title: "Cluster: View Deployments",
scope: "entity",
action: () => navigate(routes.deploymentsURL())
});
commandRegistry.add({
id: "cluster.viewDaemonSets",
title: "Cluster: View DaemonSets",
scope: "entity",
action: () => navigate(routes.daemonSetsURL())
});
commandRegistry.add({
id: "cluster.viewStatefulSets",
title: "Cluster: View StatefulSets",
scope: "entity",
action: () => navigate(routes.statefulSetsURL())
});
commandRegistry.add({
id: "cluster.viewJobs",
title: "Cluster: View Jobs",
scope: "entity",
action: () => navigate(routes.jobsURL())
});
commandRegistry.add({
id: "cluster.viewCronJobs",
title: "Cluster: View CronJobs",
scope: "entity",
action: () => navigate(routes.cronJobsURL())
});

View File

@ -35,13 +35,13 @@ import { isAllowedResource } from "../../common/rbac";
import { getHostedCluster, getHostedClusterId } from "../../common/cluster-store";
import logger from "../../main/logger";
import { webFrame } from "electron";
import { clusterPageRegistry, getExtensionPageUrl } from "../../extensions/registries/page-registry";
import { ClusterPageRegistry, getExtensionPageUrl } from "../../extensions/registries/page-registry";
import { ExtensionLoader } from "../../extensions/extension-loader";
import { appEventBus } from "../../common/event-bus";
import { requestMain } from "../../common/ipc";
import whatInput from "what-input";
import { clusterSetFrameIdHandler } from "../../common/cluster-ipc";
import { ClusterPageMenuRegistration, clusterPageMenuRegistry } from "../../extensions/registries";
import { ClusterPageMenuRegistration, ClusterPageMenuRegistry } from "../../extensions/registries";
import { StatefulSetScaleDialog } from "./+workloads-statefulsets/statefulset-scale-dialog";
import { eventStore } from "./+events/event.store";
import { nodesStore } from "./+nodes/nodes.store";
@ -122,8 +122,8 @@ export class App extends React.Component {
if (!menuItem.id) {
return routes;
}
clusterPageMenuRegistry.getSubItems(menuItem).forEach((subMenu) => {
const page = clusterPageRegistry.getByPageTarget(subMenu.target);
ClusterPageMenuRegistry.getInstance().getSubItems(menuItem).forEach((subMenu) => {
const page = ClusterPageRegistry.getInstance().getByPageTarget(subMenu.target);
if (page) {
routes.push({
@ -139,7 +139,7 @@ export class App extends React.Component {
}
renderExtensionTabLayoutRoutes() {
return clusterPageMenuRegistry.getRootItems().map((menu, index) => {
return ClusterPageMenuRegistry.getInstance().getRootItems().map((menu, index) => {
const tabRoutes = this.getTabLayoutRoutes(menu);
if (tabRoutes.length > 0) {
@ -147,7 +147,7 @@ export class App extends React.Component {
return <Route key={`extension-tab-layout-route-${index}`} component={pageComponent} path={tabRoutes.map((tab) => tab.routePath)}/>;
} else {
const page = clusterPageRegistry.getByPageTarget(menu.target);
const page = ClusterPageRegistry.getInstance().getByPageTarget(menu.target);
if (page) {
return <Route key={`extension-tab-layout-route-${index}`} path={page.url} component={page.components.Page}/>;
@ -159,8 +159,8 @@ export class App extends React.Component {
}
renderExtensionRoutes() {
return clusterPageRegistry.getItems().map((page, index) => {
const menu = clusterPageMenuRegistry.getByPage(page);
return ClusterPageRegistry.getInstance().getItems().map((page, index) => {
const menu = ClusterPageMenuRegistry.getInstance().getByPage(page);
if (!menu) {
return <Route key={`extension-route-${index}`} path={page.url} component={page.components.Page}/>;

View File

@ -30,10 +30,17 @@ jest.mock("electron", () => ({
}));
import { BottomBar } from "./bottom-bar";
jest.mock("../../../extensions/registries");
import { statusBarRegistry } from "../../../extensions/registries";
import { StatusBarRegistry } from "../../../extensions/registries";
describe("<BottomBar />", () => {
beforeEach(() => {
StatusBarRegistry.createInstance();
});
afterEach(() => {
StatusBarRegistry.resetInstance();
});
it("renders w/o errors", () => {
const { container } = render(<BottomBar />);
@ -41,19 +48,19 @@ describe("<BottomBar />", () => {
});
it("renders w/o errors when .getItems() returns unexpected (not type complient) data", async () => {
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => undefined);
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => undefined);
expect(() => render(<BottomBar />)).not.toThrow();
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => "hello");
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => "hello");
expect(() => render(<BottomBar />)).not.toThrow();
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => 6);
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => 6);
expect(() => render(<BottomBar />)).not.toThrow();
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => null);
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => null);
expect(() => render(<BottomBar />)).not.toThrow();
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => []);
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => []);
expect(() => render(<BottomBar />)).not.toThrow();
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => [{}]);
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [{}]);
expect(() => render(<BottomBar />)).not.toThrow();
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => { return {};});
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => { return {};});
expect(() => render(<BottomBar />)).not.toThrow();
});
@ -61,7 +68,7 @@ describe("<BottomBar />", () => {
const testId = "testId";
const text = "heee";
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => [
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [
{ item: <span data-testid={testId} >{text}</span> }
]);
const { getByTestId } = render(<BottomBar />);
@ -73,7 +80,7 @@ describe("<BottomBar />", () => {
const testId = "testId";
const text = "heee";
statusBarRegistry.getItems = jest.fn().mockImplementationOnce(() => [
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [
{ item: () => <span data-testid={testId} >{text}</span> }
]);
const { getByTestId } = render(<BottomBar />);

View File

@ -23,7 +23,7 @@ import "./bottom-bar.scss";
import React from "react";
import { observer } from "mobx-react";
import { StatusBarRegistration, statusBarRegistry } from "../../../extensions/registries";
import { StatusBarRegistration, StatusBarRegistry } from "../../../extensions/registries";
import { navigate } from "../../navigation";
import { Icon } from "../icon";
import { catalogURL } from "../../../common/routes";
@ -41,7 +41,7 @@ export class BottomBar extends React.Component {
}
renderRegisteredItems() {
const items = statusBarRegistry.getItems();
const items = StatusBarRegistry.getInstance().getItems();
if (!Array.isArray(items)) {
return null;

View File

@ -29,7 +29,7 @@ import { Catalog } from "../+catalog";
import { Preferences } from "../+preferences";
import { AddCluster } from "../+add-cluster";
import { ClusterView } from "./cluster-view";
import { globalPageRegistry } from "../../../extensions/registries/page-registry";
import { GlobalPageRegistry } from "../../../extensions/registries/page-registry";
import { Extensions } from "../+extensions";
import { HotbarMenu } from "../hotbar/hotbar-menu";
import { EntitySettings } from "../+entity-settings";
@ -52,7 +52,7 @@ export class ClusterManager extends React.Component {
<Route component={ClusterView} {...routes.clusterViewRoute} />
<Route component={EntitySettings} {...routes.entitySettingsRoute} />
{
globalPageRegistry.getItems()
GlobalPageRegistry.getInstance().getItems()
.map(({ url, components: { Page } }) => (
<Route key={url} path={url} component={Page} />
))

View File

@ -21,140 +21,93 @@
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 type { EntitySettingViewProps } from "../../../extensions/registries";
import type { CatalogEntity } from "../../api/catalog-entity";
import * as components from "./components";
function getClusterForEntity(entity: CatalogEntity) {
return ClusterStore.getInstance().getById(entity.metadata.uid);
}
entitySettingRegistry.add([
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
source: "local",
title: "General",
group: "Settings",
components: {
View: (props: { entity: CatalogEntity }) => {
const cluster = getClusterForEntity(props.entity);
export function GeneralSettings({ entity }: EntitySettingViewProps) {
const cluster = getClusterForEntity(entity);
if (!cluster) {
return null;
}
return (
<section>
<section>
<ClusterNameSetting cluster={cluster} />
</section>
<section>
<ClusterKubeconfig cluster={cluster} />
</section>
</section>
);
}
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Proxy",
group: "Settings",
components: {
View: (props: { entity: CatalogEntity }) => {
const cluster = getClusterForEntity(props.entity);
if (!cluster) {
return null;
}
return (
<section>
<ClusterProxySetting cluster={cluster} />
</section>
);
}
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Terminal",
group: "Settings",
components: {
View: (props: { entity: CatalogEntity }) => {
const cluster = getClusterForEntity(props.entity);
if (!cluster) {
return null;
}
return (
<section>
<ClusterHomeDirSetting cluster={cluster} />
</section>
);
}
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Namespaces",
group: "Settings",
components: {
View: (props: { entity: CatalogEntity }) => {
const cluster = getClusterForEntity(props.entity);
if (!cluster) {
return null;
}
return (
<section>
<ClusterAccessibleNamespaces cluster={cluster} />
</section>
);
}
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Metrics",
group: "Settings",
components: {
View: (props: { entity: CatalogEntity }) => {
const cluster = getClusterForEntity(props.entity);
if (!cluster) {
return null;
}
return (
<section>
<section>
<ClusterPrometheusSetting cluster={cluster} />
</section>
<section>
<ClusterMetricsSetting cluster={cluster}/>
</section>
<section>
<ShowMetricsSetting cluster={cluster}/>
</section>
</section>
);
}
}
if (!cluster) {
return null;
}
]);
return (
<section>
<section>
<components.ClusterNameSetting cluster={cluster} />
</section>
<section>
<components.ClusterKubeconfig cluster={cluster} />
</section>
</section>
);
}
export function ProxySettings({ entity }: EntitySettingViewProps) {
const cluster = getClusterForEntity(entity);
if (!cluster) {
return null;
}
return (
<section>
<components.ClusterProxySetting cluster={cluster} />
</section>
);
}
export function TerminalSettings({ entity }: EntitySettingViewProps) {
const cluster = getClusterForEntity(entity);
if (!cluster) {
return null;
}
return (
<section>
<components.ClusterHomeDirSetting cluster={cluster} />
</section>
);
}
export function NamespacesSettings({ entity }: EntitySettingViewProps) {
const cluster = getClusterForEntity(entity);
if (!cluster) {
return null;
}
return (
<section>
<components.ClusterAccessibleNamespaces cluster={cluster} />
</section>
);
}
export function MetricsSettings({ entity }: EntitySettingViewProps) {
const cluster = getClusterForEntity(entity);
if (!cluster) {
return null;
}
return (
<section>
<section>
<components.ClusterPrometheusSetting cluster={cluster} />
</section>
<section>
<components.ClusterMetricsSetting cluster={cluster} />
</section>
<section>
<components.ShowMetricsSetting cluster={cluster} />
</section>
</section>
);
}

View File

@ -0,0 +1,29 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
export * from "./cluster-accessible-namespaces";
export * from "./cluster-home-dir-setting";
export * from "./cluster-kubeconfig";
export * from "./cluster-metrics-setting";
export * from "./cluster-name-setting";
export * from "./cluster-prometheus-setting";
export * from "./cluster-proxy-setting";
export * from "./cluster-show-metrics";

View File

@ -20,4 +20,3 @@
*/
export * from "./cluster-settings";
export * from "./cluster-settings.command";

View File

@ -28,9 +28,9 @@ import { Dialog } from "../dialog";
import { EventEmitter } from "../../../common/event-emitter";
import { subscribeToBroadcast } from "../../../common/ipc";
import { CommandDialog } from "./command-dialog";
import { CommandRegistration, commandRegistry } from "../../../extensions/registries/command-registry";
import type { ClusterId } from "../../../common/cluster-store";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
import { CommandRegistration, CommandRegistry } from "../../../extensions/registries/command-registry";
export type CommandDialogEvent = {
component: React.ReactElement
@ -74,7 +74,7 @@ export class CommandContainer extends React.Component<CommandContainerProps> {
}
private findCommandById(commandId: string) {
return commandRegistry.getItems().find((command) => command.id === commandId);
return CommandRegistry.getInstance().getItems().find((command) => command.id === commandId);
}
private runCommand(command: CommandRegistration) {

View File

@ -24,7 +24,7 @@ import { Select } from "../select";
import { computed, makeObservable, observable } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import { CommandRegistry } from "../../../extensions/registries/command-registry";
import { CommandOverlay } from "./command-container";
import { broadcastMessage } from "../../../common/ipc";
import { navigate } from "../../navigation";
@ -46,33 +46,35 @@ export class CommandDialog extends React.Component {
}
@computed get options() {
const registry = CommandRegistry.getInstance();
const context = {
entity: this.activeEntity
};
return commandRegistry.getItems().filter((command) => {
return registry.getItems().filter((command) => {
if (command.scope === "entity" && !this.activeEntity) {
return false;
}
if (!command.isActive) {
return true;
}
try {
return command.isActive(context);
return command.isActive?.(context) ?? true;
} catch(e) {
console.error(e);
return false;
}
}).map((command) => {
return { value: command.id, label: command.title };
}).sort((a, b) => a.label > b.label ? 1 : -1);
return false;
})
.map((command) => ({
value: command.id,
label: command.title,
}))
.sort((a, b) => a.label > b.label ? 1 : -1);
}
private onChange(value: string) {
const command = commandRegistry.getItems().find((cmd) => cmd.id === value);
const registry = CommandRegistry.getInstance();
const command = registry.getItems().find((cmd) => cmd.id === value);
if (!command) {
return;

View File

@ -39,7 +39,6 @@ import { Logs } from "./logs";
import { TerminalWindow } from "./terminal-window";
import { createTerminalTab } from "./terminal.store";
import { UpgradeChart } from "./upgrade-chart";
import { commandRegistry } from "../../../extensions/registries/command-registry";
interface Props {
className?: string;
@ -161,11 +160,3 @@ export class Dock extends React.Component<Props> {
);
}
}
commandRegistry.add({
id: "cluster.openTerminal",
title: "Cluster: Open terminal",
scope: "entity",
action: () => createTerminalTab(),
isActive: (context) => !!context.entity
});

View File

@ -19,7 +19,6 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import "./hotbar-menu.scss";
import "./hotbar.commands";
import React, { HTMLAttributes, ReactNode, useState } from "react";

View File

@ -20,7 +20,6 @@
*/
import "./hotbar-menu.scss";
import "./hotbar.commands";
import React from "react";
import { observer } from "mobx-react";

View File

@ -25,7 +25,7 @@ import React from "react";
import { Icon } from "../icon";
import { cssNames, formatDuration } from "../../utils";
import { KubeObject, KubeObjectStatus, KubeObjectStatusLevel } from "../../..//extensions/renderer-api/k8s-api";
import { kubeObjectStatusRegistry } from "../../../extensions/registries";
import { KubeObjectStatusRegistry } from "../../../extensions/registries";
function statusClassName(level: KubeObjectStatusLevel): string {
switch (level) {
@ -105,7 +105,7 @@ export class KubeObjectStatusIcon extends React.Component<Props> {
}
render() {
const statuses = kubeObjectStatusRegistry.getItemsForObject(this.props.object);
const statuses = KubeObjectStatusRegistry.getInstance().getItemsForObject(this.props.object);
if (statuses.length === 0) {
return null;

View File

@ -32,7 +32,8 @@ import { apiManager } from "../../api/api-manager";
import { crdStore } from "../+custom-resources/crd.store";
import { CrdResourceDetails } from "../+custom-resources";
import { KubeObjectMenu } from "./kube-object-menu";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import type { CustomResourceDefinition } from "../../api/endpoints";
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
/**
* Used to store `object.selfLink` to show more info about resource in the details panel.
@ -139,20 +140,33 @@ export class KubeObjectDetails extends React.Component {
render() {
const { object, isLoading, loadingError, isCrdInstance } = this;
const isOpen = !!(object || isLoading || loadingError);
let title = "";
let details: React.ReactNode[];
if (object) {
const { kind, getName } = object;
if (!object) {
return (
<Drawer
className="KubeObjectDetails flex column"
open={isOpen}
title=""
toolbar={<KubeObjectMenu object={object} toolbar={true} />}
onClose={hideDetails}
>
{isLoading && <Spinner center />}
{loadingError && <div className="box center">{loadingError}</div>}
</Drawer>
);
}
title = `${kind}: ${getName()}`;
details = kubeObjectDetailRegistry.getItemsForKind(object.kind, object.apiVersion).map((item, index) => {
return <item.components.Details object={object} key={`object-details-${index}`}/>;
});
const { kind, getName } = object;
const title = `${kind}: ${getName()}`;
const details = KubeObjectDetailRegistry
.getInstance()
.getItemsForKind(object.kind, object.apiVersion)
.map((item, index) => (
<item.components.Details object={object} key={`object-details-${index}`} />
));
if (isCrdInstance && details.length === 0) {
details.push(<CrdResourceDetails object={object}/>);
}
if (isCrdInstance && details.length === 0) {
details.push(<CrdResourceDetails object={object as CustomResourceDefinition}/>);
}
return (

View File

@ -26,7 +26,7 @@ import { editResourceTab } from "../dock/edit-resource.store";
import { MenuActions, MenuActionsProps } from "../menu/menu-actions";
import { hideDetails } from "./kube-object-details";
import { apiManager } from "../../api/api-manager";
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
import { KubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
export interface KubeObjectMenuProps<T> extends MenuActionsProps {
object: T | null | undefined;
@ -88,7 +88,8 @@ export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeOb
return [];
}
return kubeObjectMenuRegistry
return KubeObjectMenuRegistry
.getInstance()
.getItemsForKind(object.kind, object.apiVersion)
.map(({components: { MenuItem }}, index) => (
<MenuItem

View File

@ -35,7 +35,7 @@ import { CustomResources } from "../+custom-resources/custom-resources";
import { isActiveRoute } from "../../navigation";
import { isAllowedResource } from "../../../common/rbac";
import { Spinner } from "../spinner";
import { ClusterPageMenuRegistration, clusterPageMenuRegistry, clusterPageRegistry, getExtensionPageUrl } from "../../../extensions/registries";
import { ClusterPageMenuRegistration, ClusterPageMenuRegistry, ClusterPageRegistry, getExtensionPageUrl } from "../../../extensions/registries";
import { SidebarItem } from "./sidebar-item";
import { Apps } from "../+apps";
import * as routes from "../../../common/routes";
@ -108,8 +108,8 @@ export class Sidebar extends React.Component<Props> {
return routes;
}
clusterPageMenuRegistry.getSubItems(menu).forEach((subMenu) => {
const subPage = clusterPageRegistry.getByPageTarget(subMenu.target);
ClusterPageMenuRegistry.getInstance().getSubItems(menu).forEach((subMenu) => {
const subPage = ClusterPageRegistry.getInstance().getByPageTarget(subMenu.target);
if (subPage) {
const { extensionId, id: pageId } = subPage;
@ -127,8 +127,8 @@ export class Sidebar extends React.Component<Props> {
}
renderRegisteredMenus() {
return clusterPageMenuRegistry.getRootItems().map((menuItem, index) => {
const registeredPage = clusterPageRegistry.getByPageTarget(menuItem.target);
return ClusterPageMenuRegistry.getInstance().getRootItems().map((menuItem, index) => {
const registeredPage = ClusterPageRegistry.getInstance().getByPageTarget(menuItem.target);
const tabRoutes = this.getTabLayoutRoutes(menuItem);
const id = `registered-item-${index}`;
let pageUrl: string;

View File

@ -0,0 +1,193 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import React from "react";
import * as routes from "../../common/routes";
import { CommandRegistry } from "../../extensions/registries";
import { getActiveClusterEntity } from "../api/catalog-entity-registry";
import { CommandOverlay } from "../components/command-palette";
import { createTerminalTab } from "../components/dock/terminal.store";
import { HotbarAddCommand } from "../components/hotbar/hotbar-add-command";
import { HotbarRemoveCommand } from "../components/hotbar/hotbar-remove-command";
import { HotbarSwitchCommand } from "../components/hotbar/hotbar-switch-command";
import { navigate } from "../navigation";
export function initCommandRegistry() {
CommandRegistry.getInstance()
.add([
{
id: "app.showPreferences",
title: "Preferences: Open",
scope: "global",
action: () => navigate(routes.preferencesURL())
},
{
id: "cluster.viewHelmCharts",
title: "Cluster: View Helm Charts",
scope: "entity",
action: () => navigate(routes.helmChartsURL())
},
{
id: "cluster.viewHelmReleases",
title: "Cluster: View Helm Releases",
scope: "entity",
action: () => navigate(routes.releaseURL())
},
{
id: "cluster.viewConfigMaps",
title: "Cluster: View ConfigMaps",
scope: "entity",
action: () => navigate(routes.configMapsURL())
},
{
id: "cluster.viewSecrets",
title: "Cluster: View Secrets",
scope: "entity",
action: () => navigate(routes.secretsURL())
},
{
id: "cluster.viewResourceQuotas",
title: "Cluster: View ResourceQuotas",
scope: "entity",
action: () => navigate(routes.resourceQuotaURL())
},
{
id: "cluster.viewLimitRanges",
title: "Cluster: View LimitRanges",
scope: "entity",
action: () => navigate(routes.limitRangeURL())
},
{
id: "cluster.viewHorizontalPodAutoscalers",
title: "Cluster: View HorizontalPodAutoscalers (HPA)",
scope: "entity",
action: () => navigate(routes.hpaURL())
},
{
id: "cluster.viewPodDisruptionBudget",
title: "Cluster: View PodDisruptionBudgets",
scope: "entity",
action: () => navigate(routes.pdbURL())
},
{
id: "cluster.viewServices",
title: "Cluster: View Services",
scope: "entity",
action: () => navigate(routes.servicesURL())
},
{
id: "cluster.viewEndpoints",
title: "Cluster: View Endpoints",
scope: "entity",
action: () => navigate(routes.endpointURL())
},
{
id: "cluster.viewIngresses",
title: "Cluster: View Ingresses",
scope: "entity",
action: () => navigate(routes.ingressURL())
},
{
id: "cluster.viewNetworkPolicies",
title: "Cluster: View NetworkPolicies",
scope: "entity",
action: () => navigate(routes.networkPoliciesURL())
},
{
id: "cluster.viewNodes",
title: "Cluster: View Nodes",
scope: "entity",
action: () => navigate(routes.nodesURL())
},
{
id: "cluster.viewPods",
title: "Cluster: View Pods",
scope: "entity",
action: () => navigate(routes.podsURL())
},
{
id: "cluster.viewDeployments",
title: "Cluster: View Deployments",
scope: "entity",
action: () => navigate(routes.deploymentsURL())
},
{
id: "cluster.viewDaemonSets",
title: "Cluster: View DaemonSets",
scope: "entity",
action: () => navigate(routes.daemonSetsURL())
},
{
id: "cluster.viewStatefulSets",
title: "Cluster: View StatefulSets",
scope: "entity",
action: () => navigate(routes.statefulSetsURL())
},
{
id: "cluster.viewJobs",
title: "Cluster: View Jobs",
scope: "entity",
action: () => navigate(routes.jobsURL())
},
{
id: "cluster.viewCronJobs",
title: "Cluster: View CronJobs",
scope: "entity",
action: () => navigate(routes.cronJobsURL())
},
{
id: "cluster.viewCurrentClusterSettings",
title: "Cluster: View Settings",
scope: "global",
action: () => navigate(routes.entitySettingsURL({
params: {
entityId: getActiveClusterEntity()?.id,
}
})),
isActive: (context) => !!context.entity
},
{
id: "cluster.openTerminal",
title: "Cluster: Open terminal",
scope: "entity",
action: () => createTerminalTab(),
isActive: (context) => !!context.entity
},
{
id: "hotbar.switchHotbar",
title: "Hotbar: Switch ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarSwitchCommand />)
},
{
id: "hotbar.addHotbar",
title: "Hotbar: Add Hotbar ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarAddCommand />)
},
{
id: "hotbar.removeHotbar",
title: "Hotbar: Remove Hotbar ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarRemoveCommand />)
},
]);
}

View File

@ -0,0 +1,70 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { EntitySettingRegistry } from "../../extensions/registries";
import * as clusterSettings from "../components/cluster-settings";
export function initEntitySettingsRegistry() {
EntitySettingRegistry.getInstance()
.add([
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
source: "local",
title: "General",
components: {
View: clusterSettings.GeneralSettings,
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Proxy",
components: {
View: clusterSettings.ProxySettings,
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Terminal",
components: {
View: clusterSettings.TerminalSettings,
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Namespaces",
components: {
View: clusterSettings.NamespacesSettings,
}
},
{
apiVersions: ["entity.k8slens.dev/v1alpha1"],
kind: "KubernetesCluster",
title: "Metrics",
components: {
View: clusterSettings.MetricsSettings,
}
}
]);
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
export * from "./command-registry";
export * from "./entity-settings-registry";
export * from "./kube-object-detail-registry";
export * from "./kube-object-menu-registry";
export * from "./registries";
export * from "./welcome-menu-registry";
export * from "./workloads-overview-detail-registry";

View File

@ -0,0 +1,449 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import React from "react";
import type * as endpoints from "../api/endpoints";
import type { KubeObject } from "../api/kube-object";
import { KubeObjectDetailRegistry } from "../api/kube-object-detail-registry";
import { HpaDetails } from "../components/+config-autoscalers";
import { LimitRangeDetails } from "../components/+config-limit-ranges";
import { ConfigMapDetails } from "../components/+config-maps";
import { PodDisruptionBudgetDetails } from "../components/+config-pod-disruption-budgets";
import { ResourceQuotaDetails } from "../components/+config-resource-quotas";
import { SecretDetails } from "../components/+config-secrets";
import { CRDDetails } from "../components/+custom-resources";
import { EventDetails } from "../components/+events";
import { KubeEventDetails } from "../components/+events/kube-event-details";
import { NamespaceDetails } from "../components/+namespaces";
import { EndpointDetails } from "../components/+network-endpoints";
import { IngressDetails } from "../components/+network-ingresses";
import { NetworkPolicyDetails } from "../components/+network-policies";
import { ServiceDetails } from "../components/+network-services";
import { NodeDetails } from "../components/+nodes";
import { PodSecurityPolicyDetails } from "../components/+pod-security-policies";
import { StorageClassDetails } from "../components/+storage-classes";
import { PersistentVolumeClaimDetails } from "../components/+storage-volume-claims";
import { PersistentVolumeDetails } from "../components/+storage-volumes";
import { ClusterRoleDetails } from "../components/+user-management/+cluster-roles";
import { ClusterRoleBindingDetails } from "../components/+user-management/+cluster-role-bindings";
import { RoleDetails } from "../components/+user-management/+roles";
import { RoleBindingDetails } from "../components/+user-management/+role-bindings";
import { ServiceAccountsDetails } from "../components/+user-management/+service-accounts";
import { CronJobDetails } from "../components/+workloads-cronjobs";
import { DaemonSetDetails } from "../components/+workloads-daemonsets";
import { DeploymentDetails } from "../components/+workloads-deployments";
import { JobDetails } from "../components/+workloads-jobs";
import { PodDetails } from "../components/+workloads-pods";
import { ReplicaSetDetails } from "../components/+workloads-replicasets";
import { StatefulSetDetails } from "../components/+workloads-statefulsets";
import type { KubeObjectDetailsProps } from "../components/kube-object";
export function intiKubeObjectDetailRegistry() {
KubeObjectDetailRegistry.getInstance()
.add([
{
kind: "HorizontalPodAutoscaler",
apiVersions: ["autoscaling/v2beta1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.HorizontalPodAutoscaler>) => <HpaDetails {...props}/>,
}
},
{
kind: "HorizontalPodAutoscaler",
apiVersions: ["autoscaling/v2beta1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "LimitRange",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.LimitRange>) => <LimitRangeDetails {...props}/>,
}
},
{
kind: "ConfigMap",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.ConfigMap>) => <ConfigMapDetails {...props}/>,
}
},
{
kind: "ConfigMap",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "PodDisruptionBudget",
apiVersions: ["policy/v1beta1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.PodDisruptionBudget>) => <PodDisruptionBudgetDetails {...props}/>,
}
},
{
kind: "ResourceQuota",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.ResourceQuota>) => <ResourceQuotaDetails {...props}/>,
}
},
{
kind: "Secret",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Secret>) => <SecretDetails {...props}/>,
}
},
{
kind: "CustomResourceDefinition",
apiVersions: ["apiextensions.k8s.io/v1", "apiextensions.k8s.io/v1beta1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.CustomResourceDefinition>) => <CRDDetails {...props}/>,
}
},
{
kind: "Event",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.KubeEvent>) => <EventDetails {...props}/>,
}
},
{
kind: "Namespace",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Namespace>) => <NamespaceDetails {...props}/>,
}
},
{
kind: "Endpoints",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Endpoint>) => <EndpointDetails {...props}/>,
}
},
{
kind: "Endpoints",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Ingress",
apiVersions: ["networking.k8s.io/v1", "extensions/v1beta1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Ingress>) => <IngressDetails {...props}/>,
}
},
{
kind: "Ingress",
apiVersions: ["networking.k8s.io/v1", "extensions/v1beta1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "NetworkPolicy",
apiVersions: ["networking.k8s.io/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.NetworkPolicy>) => <NetworkPolicyDetails {...props}/>,
}
},
{
kind: "NetworkPolicy",
apiVersions: ["networking.k8s.io/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Service",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Service>) => <ServiceDetails {...props}/>,
}
},
{
kind: "Service",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Node",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Node>) => <NodeDetails {...props}/>,
}
},
{
kind: "Node",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "PodSecurityPolicy",
apiVersions: ["policy/v1beta1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.PodSecurityPolicy>) => <PodSecurityPolicyDetails {...props}/>,
}
},
{
kind: "StorageClass",
apiVersions: ["storage.k8s.io/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.StorageClass>) => <StorageClassDetails {...props}/>,
}
},
{
kind: "StorageClass",
apiVersions: ["storage.k8s.io/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "PersistentVolumeClaim",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.PersistentVolumeClaim>) => <PersistentVolumeClaimDetails {...props}/>,
}
},
{
kind: "PersistentVolumeClaim",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "PersistentVolume",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.PersistentVolume>) => <PersistentVolumeDetails {...props}/>,
}
},
{
kind: "PersistentVolume",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Role",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Role>) => <RoleDetails {...props}/>,
}
},
{
kind: "Role",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "ClusterRole",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.ClusterRole>) => <ClusterRoleDetails {...props}/>,
}
},
{
kind: "ClusterRole",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "RoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.RoleBinding>) => <RoleBindingDetails {...props}/>,
}
},
{
kind: "RoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "ClusterRoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.ClusterRoleBinding>) => <ClusterRoleBindingDetails {...props}/>,
}
},
{
kind: "ClusterRoleBinding",
apiVersions: ["rbac.authorization.k8s.io/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "ServiceAccount",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.ServiceAccount>) => <ServiceAccountsDetails {...props}/>,
}
},
{
kind: "ServiceAccount",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.CronJob>) => <CronJobDetails {...props}/>,
}
},
{
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "DaemonSet",
apiVersions: ["apps/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.DaemonSet>) => <DaemonSetDetails {...props}/>,
}
},
{
kind: "DaemonSet",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Deployment",
apiVersions: ["apps/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Deployment>) => <DeploymentDetails {...props}/>,
}
},
{
kind: "Deployment",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Job",
apiVersions: ["batch/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Job>) => <JobDetails {...props}/>,
}
},
{
kind: "Job",
apiVersions: ["batch/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "Pod",
apiVersions: ["v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.Pod>) => <PodDetails {...props}/>,
}
},
{
kind: "Pod",
apiVersions: ["v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.ReplicaSet>) => <ReplicaSetDetails {...props}/>,
}
},
{
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
},
{
kind: "StatefulSet",
apiVersions: ["apps/v1"],
components: {
Details: (props: KubeObjectDetailsProps<endpoints.StatefulSet>) => <StatefulSetDetails {...props}/>,
}
},
{
kind: "StatefulSet",
apiVersions: ["apps/v1"],
priority: 5,
components: {
Details: (props: KubeObjectDetailsProps<KubeObject>) => <KubeEventDetails {...props}/>,
}
}
]);
}

View File

@ -0,0 +1,68 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { KubeObjectMenuRegistry } from "../../extensions/registries";
import { ServiceAccountMenu } from "../components/+user-management/+service-accounts";
import { CronJobMenu } from "../components/+workloads-cronjobs";
import { DeploymentMenu } from "../components/+workloads-deployments";
import { ReplicaSetMenu } from "../components/+workloads-replicasets";
import { StatefulSetMenu } from "../components/+workloads-statefulsets";
export function initKubeObjectMenuRegistry() {
KubeObjectMenuRegistry.getInstance()
.add([
{
kind: "ServiceAccount",
apiVersions: ["v1"],
components: {
MenuItem: ServiceAccountMenu,
}
},
{
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
components: {
MenuItem: CronJobMenu
}
},
{
kind: "Deployment",
apiVersions: ["apps/v1"],
components: {
MenuItem: DeploymentMenu
}
},
{
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
components: {
MenuItem: ReplicaSetMenu
}
},
{
kind: "StatefulSet",
apiVersions: ["apps/v1"],
components: {
MenuItem: StatefulSetMenu
}
}
]);
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import * as registries from "../../extensions/registries";
export function initRegistries() {
registries.AppPreferenceRegistry.createInstance();
registries.CatalogEntityDetailRegistry.createInstance();
registries.ClusterPageMenuRegistry.createInstance();
registries.ClusterPageRegistry.createInstance();
registries.CommandRegistry.createInstance();
registries.EntitySettingRegistry.createInstance();
registries.GlobalPageRegistry.createInstance();
registries.KubeObjectDetailRegistry.createInstance();
registries.KubeObjectMenuRegistry.createInstance();
registries.KubeObjectStatusRegistry.createInstance();
registries.PageMenuRegistry.createInstance();
registries.StatusBarRegistry.createInstance();
registries.WelcomeMenuRegistry.createInstance();
registries.WorkloadsOverviewDetailRegistry.createInstance();
}

View File

@ -19,19 +19,22 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { entitySettingsURL } from "../../../common/routes";
import { catalogURL, preferencesURL } from "../../common/routes";
import { WelcomeMenuRegistry } from "../../extensions/registries";
import { navigate } from "../navigation";
commandRegistry.add({
id: "cluster.viewCurrentClusterSettings",
title: "Cluster: View Settings",
scope: "global",
action: () => navigate(entitySettingsURL({
params: {
entityId: getActiveClusterEntity()?.id,
}
})),
isActive: (context) => !!context.entity
});
export function initWelcomeMenuRegistry() {
WelcomeMenuRegistry.getInstance()
.add([
{
title: "Browse Your Catalog",
icon: "view_list",
click: () => navigate(catalogURL())
},
{
title: "Configure Preferences",
icon: "settings",
click: () => navigate(preferencesURL())
}
]);
}

View File

@ -20,29 +20,26 @@
*/
import React from "react";
import { commandRegistry } from "../../../extensions/registries";
import { CommandOverlay } from "../command-palette";
import { HotbarAddCommand } from "./hotbar-add-command";
import { HotbarRemoveCommand } from "./hotbar-remove-command";
import { HotbarSwitchCommand } from "./hotbar-switch-command";
import { isAllowedResource } from "../../common/rbac";
import { WorkloadsOverviewDetailRegistry } from "../../extensions/registries";
import { Events } from "../components/+events";
import { OverviewStatuses } from "../components/+workloads-overview/overview-statuses";
commandRegistry.add({
id: "hotbar.switchHotbar",
title: "Hotbar: Switch ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarSwitchCommand />)
});
commandRegistry.add({
id: "hotbar.addHotbar",
title: "Hotbar: Add Hotbar ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarAddCommand />)
});
commandRegistry.add({
id: "hotbar.removeHotbar",
title: "Hotbar: Remove Hotbar ...",
scope: "global",
action: () => CommandOverlay.open(<HotbarRemoveCommand />)
});
export function initWorkloadsOverviewDetailRegistry() {
WorkloadsOverviewDetailRegistry.getInstance()
.add([
{
components: {
Details: (props: any) => <OverviewStatuses {...props} />,
}
},
{
priority: 5,
components: {
Details: () => (
isAllowedResource("events") && <Events compact hideFilters className="box grow" />
)
}
}
]);
}

Some files were not shown because too many files have changed in this diff Show More