diff --git a/src/behaviours/cluster/workloads/overview/extension-api/__snapshots__/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx.snap b/src/behaviours/cluster/workloads/overview/extension-api/__snapshots__/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx.snap
new file mode 100644
index 0000000000..88991eb4d3
--- /dev/null
+++ b/src/behaviours/cluster/workloads/overview/extension-api/__snapshots__/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx.snap
@@ -0,0 +1,1539 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`disable workloads overview details when cluster is not relevant given extension should be enabled for the cluster, when navigating renders 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some detail component
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`disable workloads overview details when cluster is not relevant given extension shouldn't be enabled for the cluster, when navigating renders 1`] = `
+
+
+
+`;
+
+exports[`disable workloads overview details when cluster is not relevant given not yet known if extension should be enabled for the cluster, when navigating renders 1`] = `
+
+
+
+`;
diff --git a/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx
new file mode 100644
index 0000000000..931eedb567
--- /dev/null
+++ b/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx
@@ -0,0 +1,114 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import type { AsyncFnMock } from "@async-fn/jest";
+import asyncFn from "@async-fn/jest";
+import type { RenderResult } from "@testing-library/react";
+import type { ApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
+import type { KubernetesCluster } from "../../../../../common/catalog-entities";
+import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
+import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake";
+import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
+import apiManagerInjectable from "../../../../../common/k8s-api/api-manager/manager.injectable";
+import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable";
+import React from "react";
+
+describe("disable workloads overview details when cluster is not relevant", () => {
+ let builder: ApplicationBuilder;
+ let rendered: RenderResult;
+ let isEnabledForClusterMock: AsyncFnMock<
+ (cluster: KubernetesCluster) => boolean
+ >;
+
+ beforeEach(async () => {
+ builder = getApplicationBuilder();
+
+ builder.beforeApplicationStart(({ mainDi }) => {
+ mainDi.override(apiManagerInjectable, () => ({}));
+ });
+
+ const rendererDi = builder.dis.rendererDi;
+
+ rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
+
+ builder.setEnvironmentToClusterFrame();
+
+ const getExtensionFake = getExtensionFakeFor(builder);
+
+ isEnabledForClusterMock = asyncFn();
+
+ const testExtension = getExtensionFake({
+ id: "test-extension-id",
+ name: "test-extension",
+
+ rendererOptions: {
+ isEnabledForCluster: isEnabledForClusterMock,
+
+ kubeWorkloadsOverviewItems: [
+ {
+ components: {
+ Details: () => (
+ Some detail component
+ ),
+ },
+ },
+ ],
+ },
+ });
+
+ rendered = await builder.render();
+
+ const navigateToWorkloadsOverview = rendererDi.inject(
+ navigateToWorkloadsOverviewInjectable,
+ );
+
+ navigateToWorkloadsOverview();
+
+ builder.extensions.enable(testExtension);
+ });
+
+ describe("given not yet known if extension should be enabled for the cluster, when navigating", () => {
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("does not show the detail", () => {
+ const actual = rendered.queryByTestId("some-detail-component");
+
+ expect(actual).not.toBeInTheDocument();
+ });
+ });
+
+ describe("given extension shouldn't be enabled for the cluster, when navigating", () => {
+ beforeEach(async () => {
+ await isEnabledForClusterMock.resolve(false);
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("does not show the detail", () => {
+ const actual = rendered.queryByTestId("some-detail-component");
+
+ expect(actual).not.toBeInTheDocument();
+ });
+ });
+
+ describe("given extension should be enabled for the cluster, when navigating", () => {
+ beforeEach(async () => {
+ await isEnabledForClusterMock.resolve(true);
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("shows the detail", () => {
+ const actual = rendered.getByTestId("some-detail-component");
+
+ expect(actual).toBeInTheDocument();
+ });
+ });
+});
diff --git a/src/renderer/components/+workloads-overview/detail-components.injectable.ts b/src/renderer/components/+workloads-overview/detail-components.injectable.ts
deleted file mode 100644
index cdb625a03c..0000000000
--- a/src/renderer/components/+workloads-overview/detail-components.injectable.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import { computed } from "mobx";
-import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
-import { OverviewStatuses } from "./overview-statuses";
-import { WorkloadEvents } from "../../initializers/workload-events";
-import { orderBy } from "lodash/fp";
-import type { WorkloadsOverviewDetailRegistration } from "./workloads-overview-detail-registration";
-
-const detailComponentsInjectable = getInjectable({
- id: "workload-detail-components",
-
- instantiate: (di) => {
- const extensions = di.inject(rendererExtensionsInjectable);
-
- return computed(() => {
- const extensionRegistrations = extensions
- .get()
- .flatMap((extension) => extension.kubeWorkloadsOverviewItems);
-
- const allRegistrations = [
- ...coreRegistrations,
- ...extensionRegistrations,
- ];
-
- return getRegistrationsInPriorityOrder(allRegistrations).map(
- (item) => item.components.Details,
- );
- });
- },
-});
-
-const coreRegistrations = [
- {
- components: {
- Details: OverviewStatuses,
- },
- },
- {
- priority: 5,
- components: {
- Details: WorkloadEvents,
- },
- },
-];
-
-const toRegistrationWithDefaultPriority = ({
- priority = 50,
- ...rest
-}: WorkloadsOverviewDetailRegistration) => ({
- priority,
- ...rest,
-});
-
-const getRegistrationsInPriorityOrder = (
- allRegistrations: WorkloadsOverviewDetailRegistration[],
-) =>
- orderBy(
- "priority",
- "desc",
-
- allRegistrations.map(toRegistrationWithDefaultPriority),
- );
-
-export default detailComponentsInjectable;
diff --git a/src/renderer/components/+workloads-overview/overview.tsx b/src/renderer/components/+workloads-overview/overview.tsx
index 1d26ed8b67..0510c96bc9 100644
--- a/src/renderer/components/+workloads-overview/overview.tsx
+++ b/src/renderer/components/+workloads-overview/overview.tsx
@@ -20,7 +20,7 @@ import { withInjectables } from "@ogre-tools/injectable-react";
import clusterFrameContextInjectable from "../../cluster-frame-context/cluster-frame-context.injectable";
import type { ClusterFrameContext } from "../../cluster-frame-context/cluster-frame-context";
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
-import detailComponentsInjectable from "./detail-components.injectable";
+import workloadOverviewDetailsInjectable from "./workload-overview-details/workload-overview-details.injectable";
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
import type { PodStore } from "../+workloads-pods/store";
import type { DaemonSetStore } from "../+workloads-daemonsets/store";
@@ -37,7 +37,7 @@ import type { EventStore } from "../+events/store";
import eventStoreInjectable from "../+events/store.injectable";
interface Dependencies {
- detailComponents: IComputedValue[]>;
+ detailComponents: IComputedValue[]>;
clusterFrameContext: ClusterFrameContext;
subscribeStores: SubscribeStores;
podStore: PodStore;
@@ -122,7 +122,7 @@ class NonInjectedWorkloadsOverview extends React.Component {
export const WorkloadsOverview = withInjectables(NonInjectedWorkloadsOverview, {
getProps: (di) => ({
- detailComponents: di.inject(detailComponentsInjectable),
+ detailComponents: di.inject(workloadOverviewDetailsInjectable),
clusterFrameContext: di.inject(clusterFrameContextInjectable),
subscribeStores: di.inject(subscribeStoresInjectable),
daemonSetStore: di.inject(daemonSetStoreInjectable),
diff --git a/src/renderer/components/+workloads-overview/workload-overview-details/implementations/overview-statuses.injectable.ts b/src/renderer/components/+workloads-overview/workload-overview-details/implementations/overview-statuses.injectable.ts
new file mode 100644
index 0000000000..ecb718461b
--- /dev/null
+++ b/src/renderer/components/+workloads-overview/workload-overview-details/implementations/overview-statuses.injectable.ts
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import { workloadOverviewDetailInjectionToken } from "../workload-overview-detail-injection-token";
+import { OverviewStatuses } from "../../overview-statuses";
+import { computed } from "mobx";
+
+const overviewStatusesInjectable = getInjectable({
+ id: "overview-statuses",
+
+ instantiate: () => ({
+ Component: OverviewStatuses,
+ enabled: computed(() => true),
+ orderNumber: 10,
+ }),
+
+ injectionToken: workloadOverviewDetailInjectionToken,
+});
+
+export default overviewStatusesInjectable;
diff --git a/src/renderer/components/+workloads-overview/workload-overview-details/implementations/workload-events.injectable.ts b/src/renderer/components/+workloads-overview/workload-overview-details/implementations/workload-events.injectable.ts
new file mode 100644
index 0000000000..7c76d2b829
--- /dev/null
+++ b/src/renderer/components/+workloads-overview/workload-overview-details/implementations/workload-events.injectable.ts
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import { workloadOverviewDetailInjectionToken } from "../workload-overview-detail-injection-token";
+import { computed } from "mobx";
+import { WorkloadEvents } from "../../../../initializers/workload-events";
+
+const workloadEventsInjectable = getInjectable({
+ id: "workload-events",
+
+ instantiate: () => ({
+ Component: WorkloadEvents,
+ enabled: computed(() => true),
+ orderNumber: 300,
+ }),
+
+ injectionToken: workloadOverviewDetailInjectionToken,
+});
+
+export default workloadEventsInjectable;
diff --git a/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-injection-token.ts b/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-injection-token.ts
new file mode 100644
index 0000000000..746b815fd2
--- /dev/null
+++ b/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-injection-token.ts
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectionToken } from "@ogre-tools/injectable";
+import type { IComputedValue } from "mobx";
+import type React from "react";
+
+interface WorkloadOverviewDetail {
+ orderNumber: number;
+ Component: React.ElementType<{}>;
+ enabled: IComputedValue;
+}
+
+export const workloadOverviewDetailInjectionToken =
+ getInjectionToken({
+ id: "workload-overview-detail-injection-token",
+ });
diff --git a/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-registrator.injectable.ts b/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-registrator.injectable.ts
new file mode 100644
index 0000000000..aadb736008
--- /dev/null
+++ b/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-registrator.injectable.ts
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import { computed } from "mobx";
+import getRandomIdInjectable from "../../../../common/utils/get-random-id.injectable";
+import type { LensRendererExtension } from "../../../../extensions/lens-renderer-extension";
+import extensionShouldBeEnabledForClusterFrameInjectable from "../../../extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
+import { workloadOverviewDetailInjectionToken } from "./workload-overview-detail-injection-token";
+import { extensionRegistratorInjectionToken } from "../../../../extensions/extension-loader/extension-registrator-injection-token";
+
+const workloadOverviewDetailRegistratorInjectable = getInjectable({
+ id: "workload-overview-detail-registrator",
+
+ instantiate: (di) => {
+ const getRandomId = di.inject(getRandomIdInjectable);
+
+ const getExtensionShouldBeEnabledForClusterFrame = (
+ extension: LensRendererExtension,
+ ) =>
+ di.inject(extensionShouldBeEnabledForClusterFrameInjectable, extension);
+
+ return (ext) => {
+ const extension = ext as LensRendererExtension;
+
+ const extensionShouldBeEnabledForClusterFrame =
+ getExtensionShouldBeEnabledForClusterFrame(extension);
+
+ return extension.kubeWorkloadsOverviewItems.map((registration) => {
+ const id = `workload-overview-detail-from-${
+ extension.sanitizedExtensionId
+ }-${getRandomId()}`;
+
+ return getInjectable({
+ id,
+
+ instantiate: () => ({
+ Component: registration.components.Details,
+
+ enabled: computed(() =>
+ extensionShouldBeEnabledForClusterFrame.value.get(),
+ ),
+
+ orderNumber: 200 - (registration.priority || 50),
+ }),
+
+ injectionToken: workloadOverviewDetailInjectionToken,
+ });
+ });
+ };
+ },
+
+ injectionToken: extensionRegistratorInjectionToken,
+});
+
+export default workloadOverviewDetailRegistratorInjectable;
diff --git a/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-details.injectable.ts b/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-details.injectable.ts
new file mode 100644
index 0000000000..205dddec0a
--- /dev/null
+++ b/src/renderer/components/+workloads-overview/workload-overview-details/workload-overview-details.injectable.ts
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import { computed } from "mobx";
+import { filter, map, sortBy } from "lodash/fp";
+import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
+import { workloadOverviewDetailInjectionToken } from "./workload-overview-detail-injection-token";
+import { pipeline } from "@ogre-tools/fp";
+
+const workloadOverviewDetailsInjectable = getInjectable({
+ id: "workload-overview-details",
+
+ instantiate: (di) => {
+ const computedInjectMany = di.inject(computedInjectManyInjectable);
+ const details = computedInjectMany(workloadOverviewDetailInjectionToken);
+
+ return computed(() =>
+ pipeline(
+ details.get(),
+ filter((detail) => detail.enabled.get()),
+ sortBy((detail) => detail.orderNumber),
+ map((detail) => detail.Component),
+ ),
+ );
+ },
+});
+
+export default workloadOverviewDetailsInjectable;