mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into fix-hpa-metrics-values
This commit is contained in:
commit
b996211c9b
58 files changed
+1069
-668
No files matched your search
@@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
echo "status=create" >> $GITHUB_OUTPUT
|
||||
- uses: peter-evans/create-pull-request@v4
|
||||
if: ${{ steps.bump.outputs.status == "create" }}
|
||||
if: ${{ steps.bump.outputs.status == 'create' }}
|
||||
with:
|
||||
add-paths: package.json
|
||||
commit-message: Update package.json version to next preminor because of recent release
|
||||
|
||||
@@ -34,5 +34,6 @@ jobs:
|
||||
uses: ./.github/workflows/publish-release-npm.yml
|
||||
needs: release
|
||||
if: ${{ needs.release.outputs.version != '' }}
|
||||
secrets: inherit
|
||||
with:
|
||||
version: ${{ needs.release.outputs.version }}
|
||||
+12
-12
@@ -3,7 +3,7 @@
|
||||
"productName": "OpenLens",
|
||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "6.4.0-alpha.2",
|
||||
"version": "6.4.0-alpha.3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lensapp/lens.git"
|
||||
@@ -262,12 +262,12 @@
|
||||
"history": "^4.10.1",
|
||||
"hpagent": "^1.2.0",
|
||||
"http-proxy": "^1.18.1",
|
||||
"immer": "^9.0.17",
|
||||
"immer": "^9.0.18",
|
||||
"joi": "^17.7.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^16.7.0",
|
||||
"lodash": "^4.17.15",
|
||||
"marked": "^4.2.5",
|
||||
"marked": "^4.2.12",
|
||||
"md5-file": "^5.0.0",
|
||||
"mobx": "^6.7.0",
|
||||
"mobx-observable-history": "^2.0.3",
|
||||
@@ -312,7 +312,7 @@
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||
"@sentry/types": "^6.19.7",
|
||||
"@swc/cli": "^0.1.59",
|
||||
"@swc/core": "^1.3.25",
|
||||
"@swc/core": "^1.3.26",
|
||||
"@swc/jest": "^0.2.24",
|
||||
"@testing-library/dom": "^7.31.2",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
@@ -370,8 +370,8 @@
|
||||
"@types/webpack-dev-server": "^4.7.2",
|
||||
"@types/webpack-env": "^1.18.0",
|
||||
"@types/webpack-node-externals": "^2.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.1",
|
||||
"@typescript-eslint/parser": "^5.48.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||
"@typescript-eslint/parser": "^5.48.2",
|
||||
"adr": "^1.4.3",
|
||||
"ansi_up": "^5.1.0",
|
||||
"chalk": "^4.1.2",
|
||||
@@ -387,13 +387,13 @@
|
||||
"electron": "^19.1.9",
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-notarize": "^0.3.0",
|
||||
"esbuild": "^0.16.16",
|
||||
"esbuild-loader": "^2.20.0",
|
||||
"eslint": "^8.31.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"esbuild": "^0.17.0",
|
||||
"esbuild-loader": "^2.21.0",
|
||||
"eslint": "^8.32.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.3",
|
||||
"eslint-plugin-header": "^3.1.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-react": "7.31.11",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-react": "^7.32.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"fork-ts-checker-webpack-plugin": "^6.5.2",
|
||||
|
||||
@@ -8,7 +8,7 @@ import { CatalogEntity, CatalogCategory, categoryVersion } from "../catalog/cata
|
||||
import { broadcastMessage } from "../ipc";
|
||||
import { app } from "electron";
|
||||
import type { CatalogEntityConstructor, CatalogEntitySpec } from "../catalog/catalog-entity";
|
||||
import { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../ipc/navigation-events";
|
||||
import { requestClusterActivation, requestClusterDisconnection } from "../../renderer/ipc";
|
||||
import KubeClusterCategoryIcon from "./icons/kubernetes.svg";
|
||||
import getClusterByIdInjectable from "../cluster-store/get-by-id.injectable";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../ipc/navigation-events";
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type AppNavigationChannel = MessageChannel<string>;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { IpcRendererNavigationEvents } from "../../renderer/navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../ipc/navigation-events";
|
||||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
export type ClusterFrameNavigationChannel = MessageChannel<string>;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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 { IpcMain } from "electron";
|
||||
|
||||
const ipcMainInjectionToken = getInjectionToken<IpcMain>({
|
||||
id: "ipc-main-injection-token",
|
||||
});
|
||||
|
||||
export default ipcMainInjectionToken;
|
||||
@@ -12,17 +12,17 @@ import { toJS } from "../utils/toJS";
|
||||
import type { ClusterFrameInfo } from "../cluster-frames";
|
||||
import { clusterFrameMap } from "../cluster-frames";
|
||||
import type { Disposer } from "../utils";
|
||||
import ipcMainInjectable from "../../main/utils/channel/ipc-main/ipc-main.injectable";
|
||||
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable";
|
||||
import loggerInjectable from "../logger.injectable";
|
||||
import ipcMainInjectionToken from "./ipc-main-injection-token";
|
||||
|
||||
export const broadcastMainChannel = "ipc:broadcast-main";
|
||||
|
||||
export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any) {
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
|
||||
ipcMain.handle(channel, async (event, ...args) => {
|
||||
return sanitizePayload(await listener(event, ...args));
|
||||
@@ -90,7 +90,7 @@ export async function broadcastMessage(channel: string, ...args: any[]): Promise
|
||||
export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: any[]) => any): Disposer {
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
|
||||
ipcMain.on(channel, listener);
|
||||
|
||||
|
||||
File renamed without changes.
@@ -27,6 +27,10 @@ import { getLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-exten
|
||||
import maybeKubeApiInjectable from "../../common/k8s-api/maybe-kube-api.injectable";
|
||||
import { DeploymentApi as InternalDeploymentApi, IngressApi as InternalIngressApi, NodeApi, PersistentVolumeClaimApi, PodApi } from "../../common/k8s-api/endpoints";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../../common/k8s-api/stores-apis-can-be-created.token";
|
||||
import type { JsonApiConfig } from "../../common/k8s-api/json-api";
|
||||
import type { KubeJsonApi as InternalKubeJsonApi } from "../../common/k8s-api/kube-json-api";
|
||||
import createKubeJsonApiInjectable from "../../common/k8s-api/create-kube-json-api.injectable";
|
||||
import type { RequestInit } from "node-fetch";
|
||||
|
||||
export const apiManager = asLegacyGlobalForExtensionApi(apiManagerInjectable);
|
||||
export const forCluster = asLegacyGlobalFunctionForExtensionApi(createKubeApiForClusterInjectable);
|
||||
@@ -107,11 +111,24 @@ export {
|
||||
type KubeStatusData,
|
||||
} from "../../common/k8s-api/kube-object";
|
||||
|
||||
export {
|
||||
KubeJsonApi,
|
||||
type KubeJsonApiData,
|
||||
export type {
|
||||
KubeJsonApiData,
|
||||
} from "../../common/k8s-api/kube-json-api";
|
||||
|
||||
function KubeJsonApiCstr(config: JsonApiConfig, reqInit?: RequestInit) {
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
const createKubeJsonApi = di.inject(createKubeJsonApiInjectable);
|
||||
|
||||
return createKubeJsonApi(config, reqInit);
|
||||
}
|
||||
|
||||
export const KubeJsonApi = Object.assign(
|
||||
KubeJsonApiCstr as unknown as new (config: JsonApiConfig, reqInit?: RequestInit) => InternalKubeJsonApi,
|
||||
{
|
||||
forCluster,
|
||||
},
|
||||
);
|
||||
|
||||
export abstract class KubeObjectStore<
|
||||
K extends KubeObject = KubeObject,
|
||||
A extends InternalKubeApi<K, D> = InternalKubeApi<K, KubeJsonApiDataFor<K>>,
|
||||
|
||||
@@ -73,14 +73,14 @@ export * from "../../renderer/components/dialog";
|
||||
export * from "../../renderer/components/line-progress";
|
||||
export * from "../../renderer/components/menu";
|
||||
|
||||
export type {
|
||||
CreateNotificationOptions,
|
||||
Notification,
|
||||
NotificationId,
|
||||
NotificationMessage,
|
||||
export {
|
||||
NotificationStatus,
|
||||
ShowNotification,
|
||||
NotificationsStore,
|
||||
type CreateNotificationOptions,
|
||||
type Notification,
|
||||
type NotificationId,
|
||||
type NotificationMessage,
|
||||
type ShowNotification,
|
||||
type NotificationsStore,
|
||||
} from "../../renderer/components/notifications";
|
||||
|
||||
export const Notifications = {
|
||||
|
||||
+1
-1
@@ -1141,7 +1141,7 @@ exports[`preferences - navigation to terminal preferences given in preferences,
|
||||
class="Select__single-value css-1dimb5e-singleValue"
|
||||
>
|
||||
<span
|
||||
style="font-family: RobotoMono; font-size: 12px;"
|
||||
style="font-family: RobotoMono, var(--font-terminal); font-size: 12px;"
|
||||
>
|
||||
RobotoMono
|
||||
</span>
|
||||
|
||||
+20
-56
@@ -5,66 +5,30 @@
|
||||
import React from "react";
|
||||
import { SubTitle } from "../../../../../../renderer/components/layout/sub-title";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { UserStore } from "../../../../../../common/user-store";
|
||||
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SelectOption } from "../../../../../../renderer/components/select";
|
||||
import { Select } from "../../../../../../renderer/components/select";
|
||||
import type { Logger } from "../../../../../../common/logger";
|
||||
import { action } from "mobx";
|
||||
import loggerInjectable from "../../../../../../common/logger.injectable";
|
||||
import type { TerminalFontPreferencePresenter } from "./terminal-font-options.injectable";
|
||||
import terminalFontPreferencePresenterInjectable from "./terminal-font-options.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
userStore: UserStore;
|
||||
logger: Logger;
|
||||
model: TerminalFontPreferencePresenter;
|
||||
}
|
||||
|
||||
const NonInjectedTerminalFontFamily = observer(
|
||||
({ userStore, logger }: Dependencies) => {
|
||||
const NonInjectedTerminalFontFamily = observer(({ model }: Dependencies) => (
|
||||
<section>
|
||||
<SubTitle title="Font family" />
|
||||
<Select
|
||||
themeName="lens"
|
||||
controlShouldRenderValue
|
||||
value={model.current.get()}
|
||||
options={model.options.get()}
|
||||
onChange={model.onSelection}
|
||||
/>
|
||||
</section>
|
||||
));
|
||||
|
||||
// fonts must be declared in `fonts.scss` and at `template.html` (if early-preloading required)
|
||||
const supportedCustomFonts: SelectOption<string>[] = [
|
||||
"RobotoMono", "Anonymous Pro", "IBM Plex Mono", "JetBrains Mono", "Red Hat Mono",
|
||||
"Source Code Pro", "Space Mono", "Ubuntu Mono",
|
||||
].map(customFont => {
|
||||
const { fontFamily, fontSize } = userStore.terminalConfig;
|
||||
|
||||
return {
|
||||
label: <span style={{ fontFamily: customFont, fontSize }}>{customFont}</span>,
|
||||
value: customFont,
|
||||
isSelected: fontFamily === customFont,
|
||||
};
|
||||
});
|
||||
|
||||
const onFontFamilyChange = action(({ value: fontFamily }: SelectOption<string>) => {
|
||||
logger.info(`setting terminal font to ${fontFamily}`);
|
||||
|
||||
userStore.terminalConfig.fontFamily = fontFamily; // save to external storage
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<section>
|
||||
<SubTitle title="Font family" />
|
||||
<Select
|
||||
themeName="lens"
|
||||
controlShouldRenderValue
|
||||
value={userStore.terminalConfig.fontFamily}
|
||||
options={supportedCustomFonts}
|
||||
onChange={onFontFamilyChange as any}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const TerminalFontFamily = withInjectables<Dependencies>(
|
||||
NonInjectedTerminalFontFamily,
|
||||
|
||||
{
|
||||
getProps: (di) => ({
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
},
|
||||
);
|
||||
export const TerminalFontFamily = withInjectables<Dependencies>(NonInjectedTerminalFontFamily, {
|
||||
getProps: (di) => ({
|
||||
model: di.inject(terminalFontPreferencePresenterInjectable),
|
||||
}),
|
||||
});
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 type { IComputedValue } from "mobx";
|
||||
import { action, computed } from "mobx";
|
||||
import React from "react";
|
||||
import type { SingleValue } from "react-select";
|
||||
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
|
||||
import { defaultTerminalFontFamily } from "../../../../../../common/vars";
|
||||
import type { SelectOption } from "../../../../../../renderer/components/select";
|
||||
import { terminalFontInjectionToken } from "../../../../../terminal/renderer/fonts/token";
|
||||
|
||||
export interface TerminalFontPreferencePresenter {
|
||||
readonly options: IComputedValue<SelectOption<string>[]>;
|
||||
readonly current: IComputedValue<string>;
|
||||
onSelection: (selection: SingleValue<SelectOption<string>>) => void;
|
||||
}
|
||||
|
||||
const terminalFontPreferencePresenterInjectable = getInjectable({
|
||||
id: "terminal-font-preference-presenter",
|
||||
instantiate: (di): TerminalFontPreferencePresenter => {
|
||||
const userStore = di.inject(userStoreInjectable);
|
||||
const terminalFonts = di.injectMany(terminalFontInjectionToken);
|
||||
|
||||
return {
|
||||
options: computed(() => terminalFonts.map(font => ({
|
||||
label: (
|
||||
<span
|
||||
style={{
|
||||
fontFamily: `${font.name}, var(--font-terminal)`,
|
||||
fontSize: userStore.terminalConfig.fontSize,
|
||||
}}
|
||||
>
|
||||
{font.name}
|
||||
</span>
|
||||
),
|
||||
value: font.name,
|
||||
isSelected: userStore.terminalConfig.fontFamily === font.name,
|
||||
}))),
|
||||
current: computed(() => userStore.terminalConfig.fontFamily),
|
||||
onSelection: action(selection => {
|
||||
userStore.terminalConfig.fontFamily = selection?.value ?? defaultTerminalFontFamily;
|
||||
}),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default terminalFontPreferencePresenterInjectable;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import AnonymousPro from "./AnonymousPro-Regular.ttf";
|
||||
|
||||
const anonymousProTerminalFontInjectable = getInjectable({
|
||||
id: "anonymous-pro-terminal-font",
|
||||
instantiate: () => ({
|
||||
name:"Anonymous Pro",
|
||||
url: AnonymousPro,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default anonymousProTerminalFontInjectable;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
|
||||
const terminalFontsInjectable = getInjectable({
|
||||
id: "terminal-fonts",
|
||||
instantiate: (di) => di.injectMany(terminalFontInjectionToken),
|
||||
});
|
||||
|
||||
export default terminalFontsInjectable;
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import IBMPlexMono from "./IBMPlexMono-Regular.ttf";
|
||||
|
||||
const ibmPlexMonoTerminalFontInjectable = getInjectable({
|
||||
id: "ibm-plex-mono-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "IBM Plex Mono",
|
||||
url: IBMPlexMono,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default ibmPlexMonoTerminalFontInjectable;
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import JetBrainsMono from "./JetBrainsMono-Regular.ttf";
|
||||
|
||||
const jetbrainsMonoTerminalFontInjectable = getInjectable({
|
||||
id: "jetbrains-mono-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "JetBrains Mono",
|
||||
url: JetBrainsMono,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default jetbrainsMonoTerminalFontInjectable;
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getGlobalOverride } from "../../../../common/test-utils/get-global-override";
|
||||
import loadTerminalFontInjectable from "./load-font.injectable";
|
||||
|
||||
export default getGlobalOverride(loadTerminalFontInjectable, () => async () => {});
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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 type { TerminalFont } from "./token";
|
||||
|
||||
export type LoadTerminalFont = (font: TerminalFont) => Promise<void>;
|
||||
|
||||
const loadTerminalFontInjectable = getInjectable({
|
||||
id: "load-terminal-font",
|
||||
instantiate: (): LoadTerminalFont => async (font) => {
|
||||
const fontLoaded = document.fonts.check(`10px ${font.name}`);
|
||||
|
||||
if (fontLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fontFace = new FontFace(font.name, `url(${font.url})`);
|
||||
|
||||
document.fonts.add(fontFace);
|
||||
await fontFace.load();
|
||||
},
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default loadTerminalFontInjectable;
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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 { beforeFrameStartsFirstInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
|
||||
import terminalFontsInjectable from "./fonts.injectable";
|
||||
import loadTerminalFontInjectable from "./load-font.injectable";
|
||||
|
||||
const preloadTerminalFontsInjectable = getInjectable({
|
||||
id: "preload-terminal-fonts",
|
||||
instantiate: (di) => ({
|
||||
id: "preload-terminal-fonts",
|
||||
run: async () => {
|
||||
const terminalFonts = di.inject(terminalFontsInjectable);
|
||||
const loadTerminalFont = di.inject(loadTerminalFontInjectable);
|
||||
|
||||
await Promise.allSettled(terminalFonts.map(loadTerminalFont));
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeFrameStartsFirstInjectionToken,
|
||||
});
|
||||
|
||||
export default preloadTerminalFontsInjectable;
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import RedHatMono from "./RedHatMono-Regular.ttf";
|
||||
|
||||
const redHatMonoTerminalFontInjectable = getInjectable({
|
||||
id: "red-hat-mono-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "Red Hat Mono",
|
||||
url: RedHatMono,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default redHatMonoTerminalFontInjectable;
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import RobotoMono from "./Roboto-Mono.ttf"; // patched font with icons
|
||||
|
||||
const robotoMonoTerminalFontInjectable = getInjectable({
|
||||
id: "roboto-mono-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "RobotoMono",
|
||||
url: RobotoMono,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default robotoMonoTerminalFontInjectable;
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import SourceCodePro from "./SourceCodePro-Regular.ttf";
|
||||
|
||||
const sourceCodeProTerminalFontInjectable = getInjectable({
|
||||
id: "source-code-pro-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "Source Code Pro",
|
||||
url: SourceCodePro,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default sourceCodeProTerminalFontInjectable;
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import SpaceMono from "./SpaceMono-Regular.ttf";
|
||||
|
||||
const spaceMonoTerminalFontInjectable = getInjectable({
|
||||
id: "space-mono-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "Space Mono",
|
||||
url: SpaceMono,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default spaceMonoTerminalFontInjectable;
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
export interface TerminalFont {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const terminalFontInjectionToken = getInjectionToken<TerminalFont>({
|
||||
id: "terminal-font-token",
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { terminalFontInjectionToken } from "./token";
|
||||
import UbuntuMono from "./UbuntuMono-Regular.ttf";
|
||||
|
||||
const ubunutuMonoTerminalFontInjectable = getInjectable({
|
||||
id: "ubunutu-mono-terminal-font",
|
||||
instantiate: () => ({
|
||||
name: "Ubuntu Mono",
|
||||
url: UbuntuMono,
|
||||
}),
|
||||
injectionToken: terminalFontInjectionToken,
|
||||
});
|
||||
|
||||
export default ubunutuMonoTerminalFontInjectable;
|
||||
@@ -4,11 +4,11 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { reaction } from "mobx";
|
||||
import ipcMainInjectionToken from "../../common/ipc/ipc-main-injection-token";
|
||||
import { catalogInitChannel } from "../../common/ipc/catalog";
|
||||
import { disposer, toJS } from "../../common/utils";
|
||||
import { getStartableStoppable } from "../../common/utils/get-startable-stoppable";
|
||||
import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable";
|
||||
import ipcMainInjectable from "../utils/channel/ipc-main/ipc-main.injectable";
|
||||
import catalogSyncBroadcasterInjectable from "./broadcaster.injectable";
|
||||
|
||||
const catalogSyncToRendererInjectable = getInjectable({
|
||||
@@ -16,7 +16,7 @@ const catalogSyncToRendererInjectable = getInjectable({
|
||||
|
||||
instantiate: (di) => {
|
||||
const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
const catalogSyncBroadcaster = di.inject(catalogSyncBroadcasterInjectable);
|
||||
|
||||
return getStartableStoppable(
|
||||
|
||||
@@ -145,31 +145,31 @@ export class ClusterManager {
|
||||
} else {
|
||||
entity.status.phase = (() => {
|
||||
if (!cluster) {
|
||||
this.dependencies.logger.debug(`${logPrefix} setting entity ${entity.getName()} to DISCONNECTED, reason="no cluster"`);
|
||||
this.dependencies.logger.silly(`${logPrefix} setting entity ${entity.getName()} to DISCONNECTED, reason="no cluster"`);
|
||||
|
||||
return LensKubernetesClusterStatus.DISCONNECTED;
|
||||
}
|
||||
|
||||
if (cluster.accessible) {
|
||||
this.dependencies.logger.debug(`${logPrefix} setting entity ${entity.getName()} to CONNECTED, reason="cluster is accessible"`);
|
||||
this.dependencies.logger.silly(`${logPrefix} setting entity ${entity.getName()} to CONNECTED, reason="cluster is accessible"`);
|
||||
|
||||
return LensKubernetesClusterStatus.CONNECTED;
|
||||
}
|
||||
|
||||
if (!cluster.disconnected) {
|
||||
this.dependencies.logger.debug(`${logPrefix} setting entity ${entity.getName()} to CONNECTING, reason="cluster is not disconnected"`);
|
||||
this.dependencies.logger.silly(`${logPrefix} setting entity ${entity.getName()} to CONNECTING, reason="cluster is not disconnected"`);
|
||||
|
||||
return LensKubernetesClusterStatus.CONNECTING;
|
||||
}
|
||||
|
||||
// Extensions are not allowed to use the Lens specific status phases
|
||||
if (!lensSpecificClusterStatuses.has(entity?.status?.phase)) {
|
||||
this.dependencies.logger.debug(`${logPrefix} not clearing entity ${entity.getName()} status, reason="custom string"`);
|
||||
this.dependencies.logger.silly(`${logPrefix} not clearing entity ${entity.getName()} status, reason="custom string"`);
|
||||
|
||||
return entity.status.phase;
|
||||
}
|
||||
|
||||
this.dependencies.logger.debug(`${logPrefix} setting entity ${entity.getName()} to DISCONNECTED, reason="fallthrough"`);
|
||||
this.dependencies.logger.silly(`${logPrefix} setting entity ${entity.getName()} to DISCONNECTED, reason="fallthrough"`);
|
||||
|
||||
return LensKubernetesClusterStatus.DISCONNECTED;
|
||||
})();
|
||||
|
||||
+2
-2
@@ -3,15 +3,15 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token";
|
||||
import { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling";
|
||||
import { delay } from "../../../../common/utils";
|
||||
import ipcMainInjectable from "../../../utils/channel/ipc-main/ipc-main.injectable";
|
||||
|
||||
const waitUntilBundledExtensionsAreLoadedInjectable = getInjectable({
|
||||
id: "wait-until-bundled-extensions-are-loaded",
|
||||
|
||||
instantiate: (di) => {
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
|
||||
return async () => {
|
||||
const viewHasLoaded = new Promise<void>((resolve) => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { iter } from "../../../common/utils";
|
||||
import clusterFramesInjectable from "../../../common/cluster-frames.injectable";
|
||||
import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../../../common/ipc/navigation-events";
|
||||
import showApplicationWindowInjectable from "./show-application-window.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
|
||||
import assert from "assert";
|
||||
|
||||
+2
-2
@@ -4,14 +4,14 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IpcMainEvent } from "electron";
|
||||
import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
|
||||
import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token";
|
||||
import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token";
|
||||
|
||||
const enlistMessageChannelListenerInjectable = getInjectable({
|
||||
id: "enlist-message-channel-listener-for-main",
|
||||
|
||||
instantiate: (di) => {
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
|
||||
return ({ channel, handler }) => {
|
||||
const nativeOnCallback = (_: IpcMainEvent, message: unknown) => {
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IpcMainInvokeEvent } from "electron";
|
||||
import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
|
||||
import type { Disposer } from "../../../../common/utils";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import type { RequestChannelListener } from "./listener-tokens";
|
||||
import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token";
|
||||
|
||||
export type EnlistRequestChannelListener = <TChannel extends RequestChannel<unknown, unknown>>(listener: RequestChannelListener<TChannel>) => Disposer;
|
||||
|
||||
@@ -15,7 +15,7 @@ const enlistRequestChannelListenerInjectable = getInjectable({
|
||||
id: "enlist-request-channel-listener-for-main",
|
||||
|
||||
instantiate: (di): EnlistRequestChannelListener => {
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
|
||||
return ({ channel, handler }) => {
|
||||
const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => handler(request);
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { ipcMain } from "electron";
|
||||
import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token";
|
||||
|
||||
const ipcMainInjectable = getInjectable({
|
||||
id: "ipc-main",
|
||||
instantiate: () => ipcMain,
|
||||
causesSideEffects: true,
|
||||
injectionToken: ipcMainInjectionToken,
|
||||
});
|
||||
|
||||
export default ipcMainInjectable;
|
||||
-1
@@ -16,7 +16,6 @@ const setupKubernetesClusterCatalogAddMenuListenerInjectable = getInjectable({
|
||||
instantiate: (di) => ({
|
||||
id: "setup-kubernetes-cluster-catalog-add-menu-listener",
|
||||
run: () => {
|
||||
// NOTE: these have to be here so that they are initialized only after the `runAfter` is ran
|
||||
const navigateToAddCluster = di.inject(navigateToAddClusterInjectable);
|
||||
const addSyncEntries = di.inject(addSyncEntriesInjectable);
|
||||
const kubernetesClusterCategory = di.inject(kubernetesClusterCategoryInjectable);
|
||||
|
||||
@@ -232,22 +232,6 @@ iframe {
|
||||
}
|
||||
}
|
||||
|
||||
#fonts-preloading {
|
||||
> span {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
|
||||
&:before {
|
||||
width: 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
content: "text-example"; // some text required to start applying/rendering font in document
|
||||
font-family: inherit; // font-family must be specified via style="" (see: template.html)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// app's common loading indicator, displaying on the route transitions
|
||||
#loading {
|
||||
position: absolute;
|
||||
|
||||
@@ -88,7 +88,15 @@ export class ClusterFrameHandler {
|
||||
() => {
|
||||
this.dependencies.logger.info(`[LENS-VIEW]: remove dashboard, clusterId=${clusterId}`);
|
||||
this.views.delete(clusterId);
|
||||
parentElem.removeChild(iframe);
|
||||
|
||||
// Must only remove iframe from DOM after it unloads old code. Else it crashes
|
||||
iframe.addEventListener("load", () => parentElem.removeChild(iframe), {
|
||||
once: true,
|
||||
});
|
||||
|
||||
// This causes the old code to be unloaded.
|
||||
iframe.setAttribute("src", "");
|
||||
|
||||
dispose();
|
||||
},
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import React, { useState } from "react";
|
||||
import commandOverlayInjectable from "./command-overlay.injectable";
|
||||
import type { CatalogEntity } from "../../../common/catalog";
|
||||
import { broadcastMessage } from "../../../common/ipc";
|
||||
import { IpcRendererNavigationEvents } from "../../navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../../../common/ipc/navigation-events";
|
||||
import type { RegisteredCommand } from "./registered-commands/commands";
|
||||
import { iter } from "../../utils";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
|
||||
@@ -9,7 +9,8 @@ import type { TabId } from "../dock/store";
|
||||
import type { TerminalApi } from "../../../api/terminal-api";
|
||||
import terminalSpawningPoolInjectable from "./terminal-spawning-pool.injectable";
|
||||
import terminalConfigInjectable from "../../../../common/user-store/terminal-config.injectable";
|
||||
import terminalCopyOnSelectInjectable from "../../../../common/user-store/terminal-copy-on-select.injectable";
|
||||
import terminalCopyOnSelectInjectable
|
||||
from "../../../../common/user-store/terminal-copy-on-select.injectable";
|
||||
import isMacInjectable from "../../../../common/vars/is-mac.injectable";
|
||||
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
|
||||
import xtermColorThemeInjectable from "../../../themes/terminal-colors.injectable";
|
||||
|
||||
@@ -44,58 +44,3 @@
|
||||
font-display: block;
|
||||
src: url("../fonts/MaterialIcons-Regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
|
||||
// Terminal fonts (monospaced)
|
||||
// Source: https://fonts.google.com/?category=Monospace
|
||||
@font-face {
|
||||
font-family: "Anonymous Pro";
|
||||
src: local("Anonymous Pro"), url("../fonts/AnonymousPro-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "IBM Plex Mono";
|
||||
src: local("IBM Plex Mono"), url("../fonts/IBMPlexMono-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "JetBrains Mono";
|
||||
src: local("JetBrains Mono"), url("../fonts/JetBrainsMono-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Red Hat Mono";
|
||||
src: local("Red Hat Mono"), url("../fonts/RedHatMono-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Code Pro";
|
||||
src: local("Source Code Pro"), url("../fonts/SourceCodePro-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Mono";
|
||||
src: local("Space Mono"), url("../fonts/SpaceMono-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Ubuntu Mono";
|
||||
src: local("Ubuntu Mono"), url("../fonts/UbuntuMono-Regular.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
// Patched RobotoMono font with icons
|
||||
// RobotoMono Windows Compatible for using in terminal
|
||||
// https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/RobotoMono
|
||||
@font-face {
|
||||
font-family: "RobotoMono";
|
||||
src: local("RobotoMono"), url("../fonts/Roboto-Mono-nerd.ttf") format("truetype");
|
||||
font-display: block;
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`kube-object-list-layout given pod store renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="ItemListLayout flex column KubeObjectListLayout Pods"
|
||||
>
|
||||
<div
|
||||
class="header flex gaps align-center"
|
||||
>
|
||||
<h5
|
||||
class="title"
|
||||
>
|
||||
Pods
|
||||
</h5>
|
||||
<div
|
||||
class="info-panel box grow"
|
||||
>
|
||||
0 items
|
||||
</div>
|
||||
<div
|
||||
class="NamespaceSelectFilterParent"
|
||||
data-testid="namespace-select-filter"
|
||||
>
|
||||
<div
|
||||
class="Select theme-dark NamespaceSelect NamespaceSelectFilter css-b62m3t-container"
|
||||
>
|
||||
<span
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
id="react-select-kube-object-list-layout-namespace-select-input-live-region"
|
||||
/>
|
||||
<span
|
||||
aria-atomic="false"
|
||||
aria-live="polite"
|
||||
aria-relevant="additions text"
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
/>
|
||||
<div
|
||||
class="Select__control css-13cymwt-control"
|
||||
>
|
||||
<div
|
||||
class="Select__value-container Select__value-container--is-multi css-1fdsijx-ValueContainer"
|
||||
>
|
||||
<div
|
||||
class="Select__placeholder css-1jqq78o-placeholder"
|
||||
id="react-select-kube-object-list-layout-namespace-select-input-placeholder"
|
||||
>
|
||||
All namespaces
|
||||
</div>
|
||||
<div
|
||||
class="Select__input-container css-qbdosj-Input"
|
||||
data-value=""
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-describedby="react-select-kube-object-list-layout-namespace-select-input-placeholder"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
class="Select__input"
|
||||
id="kube-object-list-layout-namespace-select-input"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
|
||||
>
|
||||
<span
|
||||
class="Select__indicator-separator css-1u9des2-indicatorSeparator"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="Select__indicator Select__dropdown-indicator css-1xc3v61-indicatorContainer"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="css-tj5bde-Svg"
|
||||
focusable="false"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
>
|
||||
<path
|
||||
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="items box grow flex column"
|
||||
>
|
||||
<div
|
||||
class="Table flex column KubeObjectListLayout Pods box grow dark selectable scrollable autoSize virtual"
|
||||
>
|
||||
<div
|
||||
class="Spinner singleColor center"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="AddRemoveButtons flex gaps"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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 "@testing-library/jest-dom/extend-expect";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
|
||||
import toggleKubeDetailsPaneInjectable from "../kube-detail-params/toggle-details.injectable";
|
||||
import type { DiRender } from "../test-utils/renderFor";
|
||||
import { renderFor } from "../test-utils/renderFor";
|
||||
import { KubeObjectListLayout } from "./index";
|
||||
import appPathsStateInjectable from "../../../common/app-paths/app-paths-state.injectable";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
|
||||
import createClusterInjectable from "../../../main/create-cluster/create-cluster.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
|
||||
describe("kube-object-list-layout", () => {
|
||||
let di: DiContainer;
|
||||
let render: DiRender;
|
||||
let podStore: PodStore;
|
||||
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
contextName: "some-context-name",
|
||||
id: "some-cluster-id",
|
||||
kubeConfigPath: "/some-path-to-a-kubeconfig",
|
||||
}, {
|
||||
clusterServerUrl: "https://localhost:8080",
|
||||
}));
|
||||
|
||||
render = renderFor(di);
|
||||
|
||||
di.override(subscribeStoresInjectable, () => jest.fn().mockImplementation(() => jest.fn()));
|
||||
di.override(kubeSelectedUrlParamInjectable, () => ({
|
||||
get: () => "path",
|
||||
}));
|
||||
di.override(toggleKubeDetailsPaneInjectable, () => null);
|
||||
di.override(appPathsStateInjectable, () => ({
|
||||
get: () => ({}),
|
||||
}));
|
||||
|
||||
podStore = di.inject(podStoreInjectable);
|
||||
});
|
||||
|
||||
describe("given pod store", () => {
|
||||
let result: RenderResult;
|
||||
|
||||
it("renders", () => {
|
||||
result = render((
|
||||
<div>
|
||||
<KubeObjectListLayout
|
||||
className="Pods"
|
||||
store={podStore}
|
||||
tableId = "workloads_pods"
|
||||
isConfigurable
|
||||
renderHeaderTitle="Pods"
|
||||
renderTableContents={pod => [
|
||||
<div key={pod.getName()}>{pod.getName()}</div>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
|
||||
expect(result.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("given resourcename", () => {
|
||||
it("uses resourcename in search placeholder", () => {
|
||||
result = render((
|
||||
<div>
|
||||
<KubeObjectListLayout
|
||||
className="Pods"
|
||||
store={podStore}
|
||||
tableId = "workloads_pods"
|
||||
isConfigurable
|
||||
renderHeaderTitle="Pods"
|
||||
renderTableContents={pod => [
|
||||
<div key={pod.getName()}>{pod.getName()}</div>,
|
||||
]}
|
||||
resourceName="My Custom Items"
|
||||
searchFilters={[() => null]}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
|
||||
expect(result.getByPlaceholderText("Search My Custom Items...")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -40,6 +40,12 @@ export interface KubeObjectListLayoutProps<
|
||||
store: KubeObjectStore<K, A, D>;
|
||||
dependentStores?: SubscribableStore[];
|
||||
subscribeStores?: boolean;
|
||||
|
||||
/**
|
||||
* Customize resource name for e.g. search input ("Search <ResourceName>..."")
|
||||
* If not provided, ResourceNames is used instead with a fallback to resource kind.
|
||||
*/
|
||||
resourceName?: string;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
@@ -132,7 +138,7 @@ class NonInjectedKubeObjectListLayout<
|
||||
onDetails,
|
||||
...layoutProps
|
||||
} = this.props;
|
||||
const placeholderString = ResourceNames[ResourceKindMap[store.api.kind]] || store.api.kind;
|
||||
const resourceName = this.props.resourceName || ResourceNames[ResourceKindMap[store.api.kind]] || store.api.kind;
|
||||
|
||||
return (
|
||||
<ItemListLayout<K, false>
|
||||
@@ -151,7 +157,7 @@ class NonInjectedKubeObjectListLayout<
|
||||
),
|
||||
searchProps: {
|
||||
...searchProps,
|
||||
placeholder: `Search ${placeholderString}...`,
|
||||
placeholder: `Search ${resourceName}...`,
|
||||
},
|
||||
info: (
|
||||
<>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { observable } from "mobx";
|
||||
import React, { useState } from "react";
|
||||
import { broadcastMessage } from "../../../common/ipc";
|
||||
import type { CatalogEntity, CatalogEntityContextMenu } from "../../api/catalog-entity";
|
||||
import { IpcRendererNavigationEvents } from "../../navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../../../common/ipc/navigation-events";
|
||||
import { Avatar } from "../avatar";
|
||||
import { Icon } from "../icon";
|
||||
import { Menu, MenuItem } from "../menu";
|
||||
|
||||
@@ -6,8 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import userStoreInjectable from "../../common/user-store/user-store.injectable";
|
||||
import React from "react";
|
||||
import navigateToKubernetesPreferencesInjectable from "../../features/preferences/common/navigate-to-kubernetes-preferences.injectable";
|
||||
import discoverAllKubeconfigSyncKindsInjectable from "../../features/preferences/renderer/preference-items/kubernetes/kubeconfig-sync/discover-all-sync-kinds.injectable";
|
||||
import { action } from "mobx";
|
||||
import { runInAction } from "mobx";
|
||||
import showSuccessNotificationInjectable from "../components/notifications/show-success-notification.injectable";
|
||||
|
||||
const addSyncEntriesInjectable = getInjectable({
|
||||
@@ -16,14 +15,11 @@ const addSyncEntriesInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const userStore = di.inject(userStoreInjectable);
|
||||
const navigateToKubernetesPreferences = di.inject(navigateToKubernetesPreferencesInjectable);
|
||||
const discoverAllKubeconfigSyncKinds = di.inject(discoverAllKubeconfigSyncKindsInjectable);
|
||||
const showSuccessNotification = di.inject(showSuccessNotificationInjectable);
|
||||
|
||||
return async (filePaths: string[]) => {
|
||||
const kinds = await discoverAllKubeconfigSyncKinds(filePaths);
|
||||
|
||||
action(() => {
|
||||
for (const [path] of kinds) {
|
||||
return async (paths: string[]) => {
|
||||
runInAction(() => {
|
||||
for (const path of paths) {
|
||||
userStore.syncKubeconfigEntries.set(path, {});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import observableHistoryInjectable from "../navigation/observable-history.inject
|
||||
import { runInAction } from "mobx";
|
||||
import type { NavigateToUrl } from "../../common/front-end-routing/navigate-to-url-injection-token";
|
||||
import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token";
|
||||
import { IpcRendererNavigationEvents } from "../navigation/events";
|
||||
import { IpcRendererNavigationEvents } from "../../common/ipc/navigation-events";
|
||||
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
|
||||
|
||||
const navigateToUrlInjectable = getInjectable({
|
||||
|
||||
@@ -5,17 +5,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="fonts-preloading">
|
||||
<span style="font-family: 'Material Icons'" />
|
||||
<span style="font-family: 'RobotoMono'" />
|
||||
<span style="font-family: 'Anonymous Pro'" />
|
||||
<span style="font-family: 'IBM Plex Mono'" />
|
||||
<span style="font-family: 'JetBrains Mono'" />
|
||||
<span style="font-family: 'Red Hat Mono'" />
|
||||
<span style="font-family: 'Source Code Pro'" />
|
||||
<span style="font-family: 'Space Mono'" />
|
||||
<span style="font-family: 'Ubuntu Mono'" />
|
||||
</div>
|
||||
<div id="terminal-init"></div>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+5
-1
@@ -32,4 +32,8 @@ declare module "*.png";
|
||||
declare module "*.eot";
|
||||
declare module "*.woff";
|
||||
declare module "*.woff2";
|
||||
declare module "*.ttf";
|
||||
|
||||
declare module "*.ttf" {
|
||||
const content: string;
|
||||
export = content;
|
||||
}
|
||||
@@ -25,19 +25,19 @@ const server = new WebpackDevServer({
|
||||
host: "localhost",
|
||||
port: webpackDevServerPort,
|
||||
static: buildDir, // aka `devServer.contentBase` in webpack@4
|
||||
hot: "only", // use HMR only without errors
|
||||
hot: true,
|
||||
liveReload: false,
|
||||
historyApiFallback: true,
|
||||
compress: true, // enable gzip for everything served
|
||||
devMiddleware: {
|
||||
writeToDisk: false,
|
||||
index: "OpenLensDev.html",
|
||||
publicPath: "/build",
|
||||
},
|
||||
proxy: {
|
||||
"^/$": "/build/",
|
||||
},
|
||||
client: {
|
||||
reconnect: true,
|
||||
overlay: false, // don't show warnings and errors on top of rendered app view
|
||||
logging: "error",
|
||||
logging: "info",
|
||||
},
|
||||
}, compiler);
|
||||
|
||||
|
||||
Reference in new issue
Block a user