1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Remove WelcomeBannerRegistry in favor of reactive solution

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>
Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2021-12-28 13:13:19 +02:00
parent 04ac2ff3dd
commit c5613a2e6a
No known key found for this signature in database
GPG Key ID: 5F465B5672372402
8 changed files with 112 additions and 47 deletions

View File

@ -263,7 +263,6 @@ export class ExtensionLoader {
registries.EntitySettingRegistry.getInstance().add(extension.entitySettings), registries.EntitySettingRegistry.getInstance().add(extension.entitySettings),
registries.StatusBarRegistry.getInstance().add(extension.statusBarItems), registries.StatusBarRegistry.getInstance().add(extension.statusBarItems),
registries.CommandRegistry.getInstance().add(extension.commands), registries.CommandRegistry.getInstance().add(extension.commands),
registries.WelcomeBannerRegistry.getInstance().add(extension.welcomeBanners),
registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems), registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems),
registries.TopBarRegistry.getInstance().add(extension.topBarItems), registries.TopBarRegistry.getInstance().add(extension.topBarItems),
]; ];

View File

@ -28,6 +28,7 @@ import { catalogEntityRegistry, EntityFilter } from "../renderer/api/catalog-ent
import { catalogCategoryRegistry, CategoryFilter } from "../renderer/api/catalog-category-registry"; import { catalogCategoryRegistry, CategoryFilter } from "../renderer/api/catalog-category-registry";
import type { KubernetesCluster } from "../common/catalog-entities"; import type { KubernetesCluster } from "../common/catalog-entities";
import type { WelcomeMenuRegistration } from "../renderer/components/+welcome/welcome-menu-items/welcome-menu-registration"; 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 { export class LensRendererExtension extends LensExtension {
globalPages: registries.PageRegistration[] = []; globalPages: registries.PageRegistration[] = [];
@ -42,7 +43,7 @@ export class LensRendererExtension extends LensExtension {
kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = []; kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = [];
commands: registries.CommandRegistration[] = []; commands: registries.CommandRegistration[] = [];
welcomeMenus: WelcomeMenuRegistration[] = []; welcomeMenus: WelcomeMenuRegistration[] = [];
welcomeBanners: registries.WelcomeBannerRegistration[] = []; welcomeBanners: WelcomeBannerRegistration[] = [];
catalogEntityDetailItems: registries.CatalogEntityDetailRegistration<CatalogEntity>[] = []; catalogEntityDetailItems: registries.CatalogEntityDetailRegistration<CatalogEntity>[] = [];
topBarItems: registries.TopBarRegistration[] = []; topBarItems: registries.TopBarRegistration[] = [];

View File

@ -30,7 +30,6 @@ export * from "./kube-object-menu-registry";
export * from "./kube-object-status-registry"; export * from "./kube-object-status-registry";
export * from "./command-registry"; export * from "./command-registry";
export * from "./entity-setting-registry"; export * from "./entity-setting-registry";
export * from "./welcome-banner-registry";
export * from "./catalog-entity-detail-registry"; export * from "./catalog-entity-detail-registry";
export * from "./workloads-overview-detail-registry"; export * from "./workloads-overview-detail-registry";
export * from "./topbar-registry"; export * from "./topbar-registry";

View File

@ -22,50 +22,60 @@
import React from "react"; import React from "react";
import { screen } from "@testing-library/react"; import { screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect"; import "@testing-library/jest-dom/extend-expect";
import { Welcome } from "../welcome"; import { defaultWidth, Welcome } from "../welcome";
import { TopBarRegistry, WelcomeBannerRegistry } from "../../../../extensions/registries"; import { computed } from "mobx";
import { defaultWidth } from "../welcome"; import { TopBarRegistry } from "../../../../extensions/registries";
import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import type { DiRender } from "../../test-utils/renderFor"; import type { DiRender } from "../../test-utils/renderFor";
import { renderFor } 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( jest.mock("electron", () => ({
"electron", ipcRenderer: {
() => ({ on: jest.fn(),
ipcRenderer: { },
on: jest.fn(), app: {
}, getPath: () => "tmp",
app: { },
getPath: () => "tmp", }));
},
}),
);
describe("<Welcome/>", () => { describe("<Welcome/>", () => {
let render: DiRender; let render: DiRender;
let di: ConfigurableDependencyInjectionContainer;
let welcomeBannersStub: WelcomeBannerRegistration[];
beforeEach(() => { beforeEach(() => {
const di = getDiForUnitTesting(); di = getDiForUnitTesting();
render = renderFor(di); render = renderFor(di);
welcomeBannersStub = [];
di.override(rendererExtensionsInjectable, () =>
computed(() => [
new TestExtension({
id: "some-id",
welcomeBanners: welcomeBannersStub,
}),
]),
);
TopBarRegistry.createInstance(); TopBarRegistry.createInstance();
WelcomeBannerRegistry.createInstance();
}); });
afterEach(() => { afterEach(() => {
TopBarRegistry.resetInstance(); TopBarRegistry.resetInstance();
WelcomeBannerRegistry.resetInstance();
}); });
it("renders <Banner /> registered in WelcomeBannerRegistry and hide logo", async () => { it("renders <Banner /> registered in WelcomeBannerRegistry and hide logo", async () => {
const testId = "testId"; const testId = "testId";
WelcomeBannerRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ welcomeBannersStub.push({
{ Banner: () => <div data-testid={testId} />,
Banner: () => <div data-testid={testId} />, });
},
]);
const { container } = render(<Welcome />); const { container } = render(<Welcome />);
@ -74,16 +84,15 @@ describe("<Welcome/>", () => {
}); });
it("calculates max width from WelcomeBanner.width registered in WelcomeBannerRegistry", async () => { it("calculates max width from WelcomeBanner.width registered in WelcomeBannerRegistry", async () => {
WelcomeBannerRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => [ welcomeBannersStub.push({
{ width: 100,
width: 100, Banner: () => <div />,
Banner: () => <div />, });
},
{ welcomeBannersStub.push({
width: 800, width: 800,
Banner: () => <div />, Banner: () => <div />,
}, });
]);
render(<Welcome />); render(<Welcome />);
@ -99,3 +108,25 @@ describe("<Welcome/>", () => {
}); });
}); });
}); });
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;
}
}

View File

@ -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;

View File

@ -19,8 +19,6 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 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 * WelcomeBannerRegistration is for an extension to register
* Provide a Banner component to be renderered in the welcome screen. * Provide a Banner component to be renderered in the welcome screen.
@ -35,5 +33,3 @@ export interface WelcomeBannerRegistration {
*/ */
width?: number width?: number
} }
export class WelcomeBannerRegistry extends BaseRegistry<WelcomeBannerRegistration> { }

View File

@ -26,22 +26,24 @@ import type { IComputedValue } from "mobx";
import Carousel from "react-material-ui-carousel"; import Carousel from "react-material-ui-carousel";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { productName, slackUrl } from "../../../common/vars"; import { productName, slackUrl } from "../../../common/vars";
import { WelcomeBannerRegistry } from "../../../extensions/registries";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import welcomeMenuItemsInjectable from "./welcome-menu-items/welcome-menu-items.injectable"; import welcomeMenuItemsInjectable from "./welcome-menu-items/welcome-menu-items.injectable";
import type { WelcomeMenuRegistration } from "./welcome-menu-items/welcome-menu-registration"; 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; export const defaultWidth = 320;
interface Dependencies { interface Dependencies {
welcomeMenuItems: IComputedValue<WelcomeMenuRegistration[]> welcomeMenuItems: IComputedValue<WelcomeMenuRegistration[]>
welcomeBannerItems: IComputedValue<WelcomeBannerRegistration[]>
} }
const NonInjectedWelcome: React.FC<Dependencies> = ({ welcomeMenuItems }) => { const NonInjectedWelcome: React.FC<Dependencies> = ({ welcomeMenuItems, welcomeBannerItems }) => {
const welcomeBanner = WelcomeBannerRegistry.getInstance().getItems(); const welcomeBanners = welcomeBannerItems.get();
// if there is banner with specified width, use it to calculate the width of the container // 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; const currWidth = curr.width ?? 0;
if (acc > currWidth) { if (acc > currWidth) {
@ -57,10 +59,10 @@ const NonInjectedWelcome: React.FC<Dependencies> = ({ welcomeMenuItems }) => {
style={{ width: `${maxWidth}px` }} style={{ width: `${maxWidth}px` }}
data-testid="welcome-banner-container" data-testid="welcome-banner-container"
> >
{welcomeBanner.length > 0 ? ( {welcomeBanners.length > 0 ? (
<Carousel <Carousel
stopAutoPlayOnHover={true} stopAutoPlayOnHover={true}
indicators={welcomeBanner.length > 1} indicators={welcomeBanners.length > 1}
autoPlay={true} autoPlay={true}
navButtonsAlwaysInvisible={true} navButtonsAlwaysInvisible={true}
indicatorIconButtonProps={{ indicatorIconButtonProps={{
@ -75,7 +77,7 @@ const NonInjectedWelcome: React.FC<Dependencies> = ({ welcomeMenuItems }) => {
}} }}
interval={8000} interval={8000}
> >
{welcomeBanner.map((item, index) => ( {welcomeBanners.map((item, index) => (
<item.Banner key={index} /> <item.Banner key={index} />
))} ))}
</Carousel> </Carousel>
@ -142,6 +144,7 @@ export const Welcome = withInjectables<Dependencies>(
{ {
getProps: (di) => ({ getProps: (di) => ({
welcomeMenuItems: di.inject(welcomeMenuItemsInjectable), welcomeMenuItems: di.inject(welcomeMenuItemsInjectable),
welcomeBannerItems: di.inject(welcomeBannerItemsInjectable),
}), }),
}, },
); );

View File

@ -33,7 +33,6 @@ export function initRegistries() {
registries.KubeObjectMenuRegistry.createInstance(); registries.KubeObjectMenuRegistry.createInstance();
registries.KubeObjectStatusRegistry.createInstance(); registries.KubeObjectStatusRegistry.createInstance();
registries.StatusBarRegistry.createInstance(); registries.StatusBarRegistry.createInstance();
registries.WelcomeBannerRegistry.createInstance();
registries.WorkloadsOverviewDetailRegistry.createInstance(); registries.WorkloadsOverviewDetailRegistry.createInstance();
registries.TopBarRegistry.createInstance(); registries.TopBarRegistry.createInstance();
} }