diff --git a/package-lock.json b/package-lock.json index d00efc567c7a..946b5f816855 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4524,6 +4524,10 @@ "resolved": "packages/bump-version-for-cron", "link": true }, + "node_modules/@k8slens/cluster-settings": { + "resolved": "packages/cluster-settings", + "link": true + }, "node_modules/@k8slens/computed-channel": { "resolved": "packages/technical-features/messaging/computed-channel", "link": true @@ -34142,6 +34146,25 @@ "integrity": "sha512-ZOzvDRWp8dCVBmgnkIqYCArgdFOO9YzocZp8Ra25N/RStKiWvMOXHMz+GjSeVNe5TstaTmTWPucGJkDw0XXJWA==", "dev": true }, + "packages/cluster-settings": { + "name": "@k8slens/cluster-settings", + "version": "6.5.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@ogre-tools/injectable": "^15.1.2", + "@swc/cli": "^0.1.61", + "@swc/core": "^1.3.37", + "@types/node": "^16.18.11", + "@types/semver": "^7.3.13", + "rimraf": "^4.1.2" + } + }, + "packages/cluster-settings/node_modules/@types/node": { + "version": "16.18.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.18.tgz", + "integrity": "sha512-fwGw1uvQAzabxL1pyoknPlJIF2t7+K90uTqynleKRx24n3lYcxWa3+KByLhgkF8GEAK2c7hC8Ki0RkNM5H15jQ==", + "dev": true + }, "packages/core": { "name": "@k8slens/core", "version": "6.5.0-alpha.3", @@ -34150,6 +34173,7 @@ "@astronautlabs/jsonpath": "^1.1.0", "@hapi/call": "^9.0.1", "@hapi/subtext": "^7.1.0", + "@k8slens/cluster-settings": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1", "@kubernetes/client-node": "^0.18.1", "@material-ui/styles": "^4.11.5", diff --git a/packages/cluster-settings/.swcrc b/packages/cluster-settings/.swcrc new file mode 100644 index 000000000000..8e7a530f1644 --- /dev/null +++ b/packages/cluster-settings/.swcrc @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2022" + } +} diff --git a/packages/cluster-settings/README.md b/packages/cluster-settings/README.md new file mode 100644 index 000000000000..c3d3b890f486 --- /dev/null +++ b/packages/cluster-settings/README.md @@ -0,0 +1,3 @@ +# Description + +The package exports tokens needed for external configuration of Cluster Settings page. diff --git a/packages/cluster-settings/package.json b/packages/cluster-settings/package.json new file mode 100644 index 000000000000..199347dcf40c --- /dev/null +++ b/packages/cluster-settings/package.json @@ -0,0 +1,31 @@ +{ + "name": "@k8slens/cluster-settings", + "version": "6.5.0-alpha.1", + "description": "Injection token exporter for cluster settings configuration", + "license": "MIT", + "private": false, + "mode": "production", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "clean": "rimraf dist/", + "generate-types": "tsc --d --declarationDir ./dist --declarationMap --emitDeclarationOnly", + "build": "npm run generate-types && swc ./src/index.ts -d ./dist", + "prepare:test": "npm run build" + }, + "devDependencies": { + "@ogre-tools/injectable": "^15.1.2", + "@swc/cli": "^0.1.61", + "@swc/core": "^1.3.37", + "@types/node": "^16.18.11", + "@types/semver": "^7.3.13", + "rimraf": "^4.1.2" + } +} diff --git a/packages/cluster-settings/src/index.ts b/packages/cluster-settings/src/index.ts new file mode 100644 index 000000000000..181c69d46a16 --- /dev/null +++ b/packages/cluster-settings/src/index.ts @@ -0,0 +1,30 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; + +type ClusterPreferences = { + clusterName?: string; + icon?: string | null; +} + +export interface ClusterIconMenuItem { + id: string; + title: string; + disabled?: (preferences: ClusterPreferences) => boolean; + onClick: (preferences: ClusterPreferences) => void; +} + +export interface ClusterIconSettingComponentProps { + preferences: ClusterPreferences; +} + +export interface ClusterIconSettingsComponent { + id: string; + Component: React.ComponentType; +} + +export const clusterIconSettingsMenuInjectionToken = getInjectionToken({ + id: "cluster-icon-settings-menu-injection-token", +}); + +export const clusterIconSettingsComponentInjectionToken = getInjectionToken({ + id: "cluster-icon-settings-component-injection-token", +}); \ No newline at end of file diff --git a/packages/cluster-settings/tsconfig.json b/packages/cluster-settings/tsconfig.json new file mode 100644 index 000000000000..534a5fd44776 --- /dev/null +++ b/packages/cluster-settings/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist/", + "paths": { + "*": [ + "node_modules/*", + "types/*" + ] + }, + }, + "include": [ + "src/**/*", + ], + "exclude": [ + "node_modules", + ] +} diff --git a/packages/core/package.json b/packages/core/package.json index 42c39d61810f..ad6e7e45aec3 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -120,6 +120,7 @@ "@astronautlabs/jsonpath": "^1.1.0", "@hapi/call": "^9.0.1", "@hapi/subtext": "^7.1.0", + "@k8slens/cluster-settings": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1", "@kubernetes/client-node": "^0.18.1", "@material-ui/styles": "^4.11.5", diff --git a/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap b/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap index 97eac8fca270..6c22436089a8 100644 --- a/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap +++ b/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap @@ -51,3 +51,55 @@ exports[`Icon settings given no external registrations for cluster settings menu `; + +exports[`Icon settings given no registrations for cluster settings component injection token renders 1`] = ` + +
+
+
+
+
+ + +
+
+ + + more_horiz + + +
+
+
+ +`; diff --git a/packages/core/src/renderer/components/cluster-settings/__tests__/icon-settings.test.tsx b/packages/core/src/renderer/components/cluster-settings/__tests__/icon-settings.test.tsx index 74fd2a665463..31bf6718545e 100644 --- a/packages/core/src/renderer/components/cluster-settings/__tests__/icon-settings.test.tsx +++ b/packages/core/src/renderer/components/cluster-settings/__tests__/icon-settings.test.tsx @@ -2,8 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { DiContainer } from "@ogre-tools/injectable"; -import { getInjectable } from "@ogre-tools/injectable"; + import type { RenderResult } from "@testing-library/react"; import React from "react"; import { KubernetesCluster } from "../../../../common/catalog-entities"; @@ -13,13 +12,18 @@ import { renderFor } from "../../test-utils/renderFor"; import { ClusterIconSetting } from "../icon-settings"; import { screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { clusterIconSettingsMenuInjectionToken } from "../cluster-settings-menu-injection-token"; +import type { ClusterIconSettingComponentProps } from "@k8slens/cluster-settings"; +import { clusterIconSettingsComponentInjectionToken, clusterIconSettingsMenuInjectionToken } from "@k8slens/cluster-settings"; import { runInAction } from "mobx"; +import { getInjectable, type DiContainer } from "@ogre-tools/injectable"; const cluster = new Cluster({ contextName: "some-context", id: "some-id", kubeConfigPath: "/some/path/to/kubeconfig", + preferences: { + clusterName: "some-cluster-name", + }, }, { clusterServerUrl: "https://localhost:9999", }); @@ -53,6 +57,29 @@ const newMenuItem = getInjectable({ injectionToken: clusterIconSettingsMenuInjectionToken, }); +function CustomSettingsComponent(props: ClusterIconSettingComponentProps) { + return ( +
+ Test React Component + + Cluster + {props.preferences.clusterName} + +
+ ); +} + +const newSettingsReactComponent = getInjectable({ + id: "cluster-icon-settings-react-component", + + instantiate: () => ({ + id: "test-react-component", + Component: CustomSettingsComponent, + }), + + injectionToken: clusterIconSettingsComponentInjectionToken, +}); + describe("Icon settings", () => { let rendered: RenderResult; let di: DiContainer; @@ -98,4 +125,30 @@ describe("Icon settings", () => { expect(rendered.getByText("Hello World")).toBeInTheDocument(); }); }); + + describe("given no registrations for cluster settings component injection token", () => { + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("does not have any external components", async () => { + expect(rendered.queryByTestId("test-react-component")).not.toBeInTheDocument(); + }); + }); + + describe("given registration for cluster settings component injection token", () => { + beforeEach(() => { + runInAction(() => { + di.register(newSettingsReactComponent); + }); + }); + + it("renders external component", async () => { + expect(rendered.queryByTestId("my-react-component")).toBeInTheDocument(); + }); + + it("external component has cluster preferences in props", async () => { + expect(rendered.getByText(/some-cluster-name/)).toBeInTheDocument(); + }); + }); }); diff --git a/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-clear-item.injectable.ts b/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-clear-item.injectable.ts index 697c68bb4009..87f8c87940aa 100644 --- a/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-clear-item.injectable.ts +++ b/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-clear-item.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { clusterIconSettingsMenuInjectionToken } from "./cluster-settings-menu-injection-token"; +import { clusterIconSettingsMenuInjectionToken } from "@k8slens/cluster-settings"; const clusterIconSettingsMenuClearItem = getInjectable({ id: "cluster-icon-settings-menu-clear-item", diff --git a/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-injection-token.ts b/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-injection-token.ts deleted file mode 100644 index 15dbba2754e3..000000000000 --- a/packages/core/src/renderer/components/cluster-settings/cluster-settings-menu-injection-token.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * 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 { ClusterPreferences } from "../../../common/cluster-types"; - -export interface ClusterIconMenuItem { - id: string; - title: string; - disabled?: (preferences: ClusterPreferences) => boolean; - onClick: (preferences: ClusterPreferences) => void; -} - -export const clusterIconSettingsMenuInjectionToken = getInjectionToken({ - id: "cluster-icon-settings-menu-injection-token", -}); diff --git a/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx b/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx index 94706f17a5cf..a802807c175a 100644 --- a/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx +++ b/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx @@ -15,8 +15,8 @@ import { FilePicker, OverSizeLimitStyle } from "../file-picker"; import { MenuActions, MenuItem } from "../menu"; import type { ShowNotification } from "../notifications"; import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable"; -import type { ClusterIconMenuItem } from "./cluster-settings-menu-injection-token"; -import { clusterIconSettingsMenuInjectionToken } from "./cluster-settings-menu-injection-token"; +import { clusterIconSettingsComponentInjectionToken, clusterIconSettingsMenuInjectionToken } from "@k8slens/cluster-settings"; +import type { ClusterIconMenuItem, ClusterIconSettingsComponent } from "@k8slens/cluster-settings"; export interface ClusterIconSettingProps { cluster: Cluster; @@ -25,6 +25,7 @@ export interface ClusterIconSettingProps { interface Dependencies { menuItems: IComputedValue; + settingComponents: IComputedValue; showErrorNotification: ShowNotification; } @@ -95,6 +96,14 @@ const NonInjectedClusterIconSetting = observer((props: ClusterIconSettingProps & )} + {props.settingComponents.get().map(item => { + return ( + + ); + })} ); }); @@ -106,6 +115,7 @@ export const ClusterIconSetting = withInjectables