diff --git a/src/extensions/extension-loader/extension-loader.ts b/src/extensions/extension-loader/extension-loader.ts index fb0c42e1ac..db3e924209 100644 --- a/src/extensions/extension-loader/extension-loader.ts +++ b/src/extensions/extension-loader/extension-loader.ts @@ -263,7 +263,6 @@ export class ExtensionLoader { registries.EntitySettingRegistry.getInstance().add(extension.entitySettings), registries.StatusBarRegistry.getInstance().add(extension.statusBarItems), registries.CommandRegistry.getInstance().add(extension.commands), - registries.WelcomeBannerRegistry.getInstance().add(extension.welcomeBanners), registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems), registries.TopBarRegistry.getInstance().add(extension.topBarItems), ]; diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index 388f6ba1f2..2ccb2cfe7a 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -28,6 +28,7 @@ import { catalogEntityRegistry, EntityFilter } from "../renderer/api/catalog-ent import { catalogCategoryRegistry, CategoryFilter } from "../renderer/api/catalog-category-registry"; import type { KubernetesCluster } from "../common/catalog-entities"; import type { WelcomeMenuRegistration } from "../renderer/components/+welcome/welcome-menu-items/welcome-menu-registration"; +import type { WelcomeBannerRegistration } from "../renderer/components/+welcome/welcome-banner-items/welcome-banner-registration"; export class LensRendererExtension extends LensExtension { globalPages: registries.PageRegistration[] = []; @@ -42,7 +43,7 @@ export class LensRendererExtension extends LensExtension { kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = []; commands: registries.CommandRegistration[] = []; welcomeMenus: WelcomeMenuRegistration[] = []; - welcomeBanners: registries.WelcomeBannerRegistration[] = []; + welcomeBanners: WelcomeBannerRegistration[] = []; catalogEntityDetailItems: registries.CatalogEntityDetailRegistration[] = []; topBarItems: registries.TopBarRegistration[] = []; diff --git a/src/extensions/registries/index.ts b/src/extensions/registries/index.ts index b9c249ce4c..2cd822f77a 100644 --- a/src/extensions/registries/index.ts +++ b/src/extensions/registries/index.ts @@ -30,7 +30,6 @@ export * from "./kube-object-menu-registry"; export * from "./kube-object-status-registry"; export * from "./command-registry"; export * from "./entity-setting-registry"; -export * from "./welcome-banner-registry"; export * from "./catalog-entity-detail-registry"; export * from "./workloads-overview-detail-registry"; export * from "./topbar-registry"; diff --git a/src/renderer/components/+welcome/__test__/welcome.test.tsx b/src/renderer/components/+welcome/__test__/welcome.test.tsx index fa94149caa..f7ae85bfea 100644 --- a/src/renderer/components/+welcome/__test__/welcome.test.tsx +++ b/src/renderer/components/+welcome/__test__/welcome.test.tsx @@ -22,50 +22,60 @@ import React from "react"; import { screen } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; -import { Welcome } from "../welcome"; -import { TopBarRegistry, WelcomeBannerRegistry } from "../../../../extensions/registries"; -import { defaultWidth } from "../welcome"; +import { defaultWidth, Welcome } from "../welcome"; +import { computed } from "mobx"; +import { TopBarRegistry } from "../../../../extensions/registries"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import type { DiRender } from "../../test-utils/renderFor"; import { renderFor } from "../../test-utils/renderFor"; +import type { ConfigurableDependencyInjectionContainer } from "@ogre-tools/injectable"; +import rendererExtensionsInjectable from "../../../../extensions/renderer-extensions.injectable"; +import { LensRendererExtension } from "../../../../extensions/lens-renderer-extension"; +import type { WelcomeBannerRegistration } from "../welcome-banner-items/welcome-banner-registration"; -jest.mock( - "electron", - () => ({ - ipcRenderer: { - on: jest.fn(), - }, - app: { - getPath: () => "tmp", - }, - }), -); +jest.mock("electron", () => ({ + ipcRenderer: { + on: jest.fn(), + }, + app: { + getPath: () => "tmp", + }, +})); describe("", () => { let render: DiRender; + let di: ConfigurableDependencyInjectionContainer; + let welcomeBannersStub: WelcomeBannerRegistration[]; beforeEach(() => { - const di = getDiForUnitTesting(); + di = getDiForUnitTesting(); render = renderFor(di); + welcomeBannersStub = []; + + di.override(rendererExtensionsInjectable, () => + computed(() => [ + new TestExtension({ + id: "some-id", + welcomeBanners: welcomeBannersStub, + }), + ]), + ); + TopBarRegistry.createInstance(); - WelcomeBannerRegistry.createInstance(); }); afterEach(() => { TopBarRegistry.resetInstance(); - WelcomeBannerRegistry.resetInstance(); }); it("renders registered in WelcomeBannerRegistry and hide logo", async () => { const testId = "testId"; - WelcomeBannerRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ - { - Banner: () =>
, - }, - ]); + welcomeBannersStub.push({ + Banner: () =>
, + }); const { container } = render(); @@ -74,16 +84,15 @@ describe("", () => { }); it("calculates max width from WelcomeBanner.width registered in WelcomeBannerRegistry", async () => { - WelcomeBannerRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ - { - width: 100, - Banner: () =>
, - }, - { - width: 800, - Banner: () =>
, - }, - ]); + welcomeBannersStub.push({ + width: 100, + Banner: () =>
, + }); + + welcomeBannersStub.push({ + width: 800, + Banner: () =>
, + }); render(); @@ -99,3 +108,25 @@ describe("", () => { }); }); }); + +class TestExtension extends LensRendererExtension { + constructor({ + id, + welcomeBanners, + }: { + id: string; + welcomeBanners: WelcomeBannerRegistration[]; + }) { + super({ + id, + absolutePath: "irrelevant", + isBundled: false, + isCompatible: false, + isEnabled: false, + manifest: { name: id, version: "some-version" }, + manifestPath: "irrelevant", + }); + + this.welcomeBanners = welcomeBanners; + } +} diff --git a/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-items.injectable.ts b/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-items.injectable.ts new file mode 100644 index 0000000000..288bb540ce --- /dev/null +++ b/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-items.injectable.ts @@ -0,0 +1,37 @@ +/** + * 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 { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import rendererExtensionsInjectable from "../../../../extensions/renderer-extensions.injectable"; +import { computed } from "mobx"; + +const welcomeBannerItemsInjectable = getInjectable({ + instantiate: (di) => { + const extensions = di.inject(rendererExtensionsInjectable); + + return computed(() => [ + ...extensions.get().flatMap((extension) => extension.welcomeBanners), + ]); + }, + + lifecycle: lifecycleEnum.singleton, +}); + +export default welcomeBannerItemsInjectable; diff --git a/src/extensions/registries/welcome-banner-registry.ts b/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.d.ts similarity index 91% rename from src/extensions/registries/welcome-banner-registry.ts rename to src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.d.ts index 1102dc8a3f..ec7cf3cbdb 100644 --- a/src/extensions/registries/welcome-banner-registry.ts +++ b/src/renderer/components/+welcome/welcome-banner-items/welcome-banner-registration.d.ts @@ -19,8 +19,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { BaseRegistry } from "./base-registry"; - /** * WelcomeBannerRegistration is for an extension to register * Provide a Banner component to be renderered in the welcome screen. @@ -35,5 +33,3 @@ export interface WelcomeBannerRegistration { */ width?: number } - -export class WelcomeBannerRegistry extends BaseRegistry { } diff --git a/src/renderer/components/+welcome/welcome.tsx b/src/renderer/components/+welcome/welcome.tsx index f90ede88b8..56aefbfc3c 100644 --- a/src/renderer/components/+welcome/welcome.tsx +++ b/src/renderer/components/+welcome/welcome.tsx @@ -26,22 +26,24 @@ import type { IComputedValue } from "mobx"; import Carousel from "react-material-ui-carousel"; import { Icon } from "../icon"; import { productName, slackUrl } from "../../../common/vars"; -import { WelcomeBannerRegistry } from "../../../extensions/registries"; import { withInjectables } from "@ogre-tools/injectable-react"; import welcomeMenuItemsInjectable from "./welcome-menu-items/welcome-menu-items.injectable"; import type { WelcomeMenuRegistration } from "./welcome-menu-items/welcome-menu-registration"; +import welcomeBannerItemsInjectable from "./welcome-banner-items/welcome-banner-items.injectable"; +import type { WelcomeBannerRegistration } from "./welcome-banner-items/welcome-banner-registration"; export const defaultWidth = 320; interface Dependencies { welcomeMenuItems: IComputedValue + welcomeBannerItems: IComputedValue } -const NonInjectedWelcome: React.FC = ({ welcomeMenuItems }) => { - const welcomeBanner = WelcomeBannerRegistry.getInstance().getItems(); +const NonInjectedWelcome: React.FC = ({ welcomeMenuItems, welcomeBannerItems }) => { + const welcomeBanners = welcomeBannerItems.get(); // if there is banner with specified width, use it to calculate the width of the container - const maxWidth = welcomeBanner.reduce((acc, curr) => { + const maxWidth = welcomeBanners.reduce((acc, curr) => { const currWidth = curr.width ?? 0; if (acc > currWidth) { @@ -57,10 +59,10 @@ const NonInjectedWelcome: React.FC = ({ welcomeMenuItems }) => { style={{ width: `${maxWidth}px` }} data-testid="welcome-banner-container" > - {welcomeBanner.length > 0 ? ( + {welcomeBanners.length > 0 ? ( 1} + indicators={welcomeBanners.length > 1} autoPlay={true} navButtonsAlwaysInvisible={true} indicatorIconButtonProps={{ @@ -75,7 +77,7 @@ const NonInjectedWelcome: React.FC = ({ welcomeMenuItems }) => { }} interval={8000} > - {welcomeBanner.map((item, index) => ( + {welcomeBanners.map((item, index) => ( ))} @@ -142,6 +144,7 @@ export const Welcome = withInjectables( { getProps: (di) => ({ welcomeMenuItems: di.inject(welcomeMenuItemsInjectable), + welcomeBannerItems: di.inject(welcomeBannerItemsInjectable), }), }, ); diff --git a/src/renderer/initializers/registries.ts b/src/renderer/initializers/registries.ts index 4fddb35b3d..3130fe6984 100644 --- a/src/renderer/initializers/registries.ts +++ b/src/renderer/initializers/registries.ts @@ -33,7 +33,6 @@ export function initRegistries() { registries.KubeObjectMenuRegistry.createInstance(); registries.KubeObjectStatusRegistry.createInstance(); registries.StatusBarRegistry.createInstance(); - registries.WelcomeBannerRegistry.createInstance(); registries.WorkloadsOverviewDetailRegistry.createInstance(); registries.TopBarRegistry.createInstance(); }