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

fixed hotbar-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-04-08 15:07:27 -04:00
parent 6d720db036
commit 9add1d15e4
47 changed files with 505 additions and 463 deletions

View File

@ -5,69 +5,21 @@
import { anyObject } from "jest-mock-extended"; import { anyObject } from "jest-mock-extended";
import mockFs from "mock-fs"; import mockFs from "mock-fs";
import logger from "../../main/logger";
import type { CatalogEntity, CatalogEntityData, CatalogEntityKindData } from "../catalog"; import type { CatalogEntity, CatalogEntityData, CatalogEntityKindData } from "../catalog";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable"; import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import hotbarStoreInjectable from "../hotbar-store.injectable"; import hotbarStoreInjectable from "../hotbars/store.injectable";
import { HotbarStore } from "../hotbar-store"; import type { HotbarStore } from "../hotbars/store";
import catalogEntityRegistryInjectable from "../../main/catalog/entity-registry.injectable";
import { computed } from "mobx";
import hasCategoryForEntityInjectable from "../catalog/has-category-for-entity.injectable";
import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable"; import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
import loggerInjectable from "../logger.injectable";
import type { Logger } from "../logger";
jest.mock("../../main/catalog/catalog-entity-registry", () => ({ console.log("I am here as reminder against mockfs (and to fix console logging)");
catalogEntityRegistry: {
items: [
getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "1dfa26e2ebab15780a3547e9c7fa785c",
name: "mycluster",
source: "local",
labels: {},
},
}),
getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "55b42c3c7ba3b04193416cda405269a5",
name: "my_shiny_cluster",
source: "remote",
labels: {},
},
}),
getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "catalog-entity",
name: "Catalog",
source: "app",
labels: {},
},
}),
],
},
}));
function getMockCatalogEntity(data: Partial<CatalogEntityData> & CatalogEntityKindData): CatalogEntity { function getMockCatalogEntity(data: Partial<CatalogEntityData> & CatalogEntityKindData): CatalogEntity {
return { return {
@ -84,69 +36,81 @@ function getMockCatalogEntity(data: Partial<CatalogEntityData> & CatalogEntityKi
} as CatalogEntity; } as CatalogEntity;
} }
const testCluster = getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "test",
name: "test",
labels: {},
},
});
const minikubeCluster = getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "minikube",
name: "minikube",
labels: {},
},
});
const awsCluster = getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "aws",
name: "aws",
labels: {},
},
});
describe("HotbarStore", () => { describe("HotbarStore", () => {
let di: DiContainer; let di: DiContainer;
let hotbarStore: HotbarStore; let hotbarStore: HotbarStore;
let testCluster: CatalogEntity;
let minikubeCluster: CatalogEntity;
let awsCluster: CatalogEntity;
let logger: jest.Mocked<Logger>;
beforeEach(async () => { beforeEach(async () => {
di = getDiForUnitTesting({ doGeneralOverrides: true }); di = getDiForUnitTesting({ doGeneralOverrides: true, overrideHotbarStore: false });
testCluster = getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "some-test-id",
name: "my-test-cluster",
source: "local",
labels: {},
},
});
minikubeCluster = getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "some-minikube-id",
name: "my-minikube-cluster",
source: "local",
labels: {},
},
});
awsCluster = getMockCatalogEntity({
apiVersion: "v1",
kind: "Cluster",
status: {
phase: "Running",
},
metadata: {
uid: "some-aws-id",
name: "my-aws-cluster",
source: "local",
labels: {},
},
});
di.override(hasCategoryForEntityInjectable, () => () => true);
logger = di.inject(loggerInjectable) as jest.Mocked<Logger>;
const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
const catalogCatalogEntity = di.inject(catalogCatalogEntityInjectable);
catalogEntityRegistry.addComputedSource("some-id", computed(() => [
testCluster,
minikubeCluster,
awsCluster,
catalogCatalogEntity,
]));
di.permitSideEffects(getConfigurationFileModelInjectable); di.permitSideEffects(getConfigurationFileModelInjectable);
di.permitSideEffects(appVersionInjectable); di.permitSideEffects(appVersionInjectable);
di.permitSideEffects(hotbarStoreInjectable);
di.override(hotbarStoreInjectable, () => {
HotbarStore.resetInstance();
return HotbarStore.createInstance({
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
});
});
}); });
afterEach(() => { afterEach(() => {
mockFs.restore(); mockFs.restore();
}); });
describe("given no migrations", () => { describe("given no previous data in store, running all migrations", () => {
beforeEach(async () => { beforeEach(async () => {
mockFs(); mockFs();
@ -186,7 +150,7 @@ describe("HotbarStore", () => {
it("removes items", () => { it("removes items", () => {
hotbarStore.addToHotbar(testCluster); hotbarStore.addToHotbar(testCluster);
hotbarStore.removeFromHotbar("test"); hotbarStore.removeFromHotbar("some-test-id");
hotbarStore.removeFromHotbar("catalog-entity"); hotbarStore.removeFromHotbar("catalog-entity");
const items = hotbarStore.getActive().items.filter(Boolean); const items = hotbarStore.getActive().items.filter(Boolean);
@ -211,7 +175,7 @@ describe("HotbarStore", () => {
hotbarStore.restackItems(1, 5); hotbarStore.restackItems(1, 5);
expect(hotbarStore.getActive().items[5]).toBeTruthy(); expect(hotbarStore.getActive().items[5]).toBeTruthy();
expect(hotbarStore.getActive().items[5]?.entity.uid).toEqual("test"); expect(hotbarStore.getActive().items[5]?.entity.uid).toEqual("some-test-id");
}); });
it("moves items down", () => { it("moves items down", () => {
@ -224,7 +188,7 @@ describe("HotbarStore", () => {
const items = hotbarStore.getActive().items.map(item => item?.entity.uid || null); const items = hotbarStore.getActive().items.map(item => item?.entity.uid || null);
expect(items.slice(0, 4)).toEqual(["aws", "catalog-entity", "test", "minikube"]); expect(items.slice(0, 4)).toEqual(["some-aws-id", "catalog-entity", "some-test-id", "some-minikube-id"]);
}); });
it("moves items up", () => { it("moves items up", () => {
@ -237,28 +201,21 @@ describe("HotbarStore", () => {
const items = hotbarStore.getActive().items.map(item => item?.entity.uid || null); const items = hotbarStore.getActive().items.map(item => item?.entity.uid || null);
expect(items.slice(0, 4)).toEqual(["catalog-entity", "minikube", "aws", "test"]); expect(items.slice(0, 4)).toEqual(["catalog-entity", "some-minikube-id", "some-aws-id", "some-test-id"]);
}); });
it("logs an error if cellIndex is out of bounds", () => { it("logs an error if cellIndex is out of bounds", () => {
hotbarStore.add({ name: "hottest", id: "hottest" }); hotbarStore.add({ name: "hottest", id: "hottest" });
hotbarStore.setActiveHotbar("hottest"); hotbarStore.setActiveHotbar("hottest");
const { error } = logger;
const mocked = jest.fn();
logger.error = mocked;
hotbarStore.addToHotbar(testCluster, -1); hotbarStore.addToHotbar(testCluster, -1);
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject()); expect(logger.error).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
hotbarStore.addToHotbar(testCluster, 12); hotbarStore.addToHotbar(testCluster, 12);
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject()); expect(logger.error).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
hotbarStore.addToHotbar(testCluster, 13); hotbarStore.addToHotbar(testCluster, 13);
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject()); expect(logger.error).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
logger.error = error;
}); });
it("throws an error if getId is invalid or returns not a string", () => { it("throws an error if getId is invalid or returns not a string", () => {
@ -275,7 +232,7 @@ describe("HotbarStore", () => {
hotbarStore.addToHotbar(testCluster); hotbarStore.addToHotbar(testCluster);
hotbarStore.restackItems(1, 1); hotbarStore.restackItems(1, 1);
expect(hotbarStore.getActive().items[1]?.entity.uid).toEqual("test"); expect(hotbarStore.getActive().items[1]?.entity.uid).toEqual("some-test-id");
}); });
it("new items takes first empty cell", () => { it("new items takes first empty cell", () => {
@ -284,7 +241,7 @@ describe("HotbarStore", () => {
hotbarStore.restackItems(0, 3); hotbarStore.restackItems(0, 3);
hotbarStore.addToHotbar(minikubeCluster); hotbarStore.addToHotbar(minikubeCluster);
expect(hotbarStore.getActive().items[0]?.entity.uid).toEqual("minikube"); expect(hotbarStore.getActive().items[0]?.entity.uid).toEqual("some-minikube-id");
}); });
it("throws if invalid arguments provided", () => { it("throws if invalid arguments provided", () => {
@ -315,7 +272,7 @@ describe("HotbarStore", () => {
}); });
}); });
describe("given pre beta-5 configurations", () => { describe("given data from 5.0.0-beta.3 and version being 5.0.0-beta.10", () => {
beforeEach(async () => { beforeEach(async () => {
const configurationToBeMigrated = { const configurationToBeMigrated = {
"some-electron-app-path-for-user-data": { "some-electron-app-path-for-user-data": {
@ -332,7 +289,7 @@ describe("HotbarStore", () => {
items: [ items: [
{ {
entity: { entity: {
uid: "1dfa26e2ebab15780a3547e9c7fa785c", uid: "some-aws-id",
}, },
}, },
{ {
@ -381,13 +338,15 @@ describe("HotbarStore", () => {
mockFs(configurationToBeMigrated); mockFs(configurationToBeMigrated);
di.override(appVersionInjectable, () => "5.0.0-beta.10");
await di.runSetups(); await di.runSetups();
hotbarStore = di.inject(hotbarStoreInjectable); hotbarStore = di.inject(hotbarStoreInjectable);
}); });
it("allows to retrieve a hotbar", () => { it("allows to retrieve a hotbar", () => {
const hotbar = hotbarStore.getById("3caac17f-aec2-4723-9694-ad204465d935"); const hotbar = hotbarStore.findById("3caac17f-aec2-4723-9694-ad204465d935");
expect(hotbar?.id).toBe("3caac17f-aec2-4723-9694-ad204465d935"); expect(hotbar?.id).toBe("3caac17f-aec2-4723-9694-ad204465d935");
}); });
@ -403,17 +362,9 @@ describe("HotbarStore", () => {
expect(items[0]).toEqual({ expect(items[0]).toEqual({
entity: { entity: {
name: "mycluster", name: "my-aws-cluster",
source: "local", source: "local",
uid: "1dfa26e2ebab15780a3547e9c7fa785c", uid: "some-aws-id",
},
});
expect(items[1]).toEqual({
entity: {
name: "my_shiny_cluster",
source: "remote",
uid: "55b42c3c7ba3b04193416cda405269a5",
}, },
}); });
}); });

View File

@ -10,7 +10,7 @@ import { ipcMain, ipcRenderer } from "electron";
import type { IEqualsComparer } from "mobx"; import type { IEqualsComparer } from "mobx";
import { makeObservable, reaction, runInAction } from "mobx"; import { makeObservable, reaction, runInAction } from "mobx";
import type { Disposer } from "./utils"; import type { Disposer } from "./utils";
import { getAppVersion, Singleton, toJS } from "./utils"; import { Singleton, toJS } from "./utils";
import logger from "../main/logger"; import logger from "../main/logger";
import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc"; import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc";
import isEqual from "lodash/isEqual"; import isEqual from "lodash/isEqual";
@ -59,8 +59,6 @@ export abstract class BaseStore<T> extends Singleton {
this.storeConfig = getConfigurationFileModel({ this.storeConfig = getConfigurationFileModel({
...this.params, ...this.params,
projectName: "lens",
projectVersion: getAppVersion(),
cwd: this.cwd(), cwd: this.cwd(),
}); });

View File

@ -6,7 +6,6 @@
import { navigate } from "../../renderer/navigation"; import { navigate } from "../../renderer/navigation";
import type { CatalogEntityMetadata, CatalogEntitySpec, CatalogEntityStatus } from "../catalog"; import type { CatalogEntityMetadata, CatalogEntitySpec, CatalogEntityStatus } from "../catalog";
import { CatalogCategory, CatalogEntity, categoryVersion } from "../catalog"; import { CatalogCategory, CatalogEntity, categoryVersion } from "../catalog";
import { catalogCategoryRegistry } from "../catalog/catalog-category-registry";
interface GeneralEntitySpec extends CatalogEntitySpec { interface GeneralEntitySpec extends CatalogEntitySpec {
path: string; path: string;
@ -54,5 +53,3 @@ export class GeneralCategory extends CatalogCategory {
}, },
}; };
} }
catalogCategoryRegistry.add(new GeneralCategory());

View File

@ -158,5 +158,3 @@ class KubernetesClusterCategory extends CatalogCategory {
} }
export const kubernetesClusterCategory = new KubernetesClusterCategory(); export const kubernetesClusterCategory = new KubernetesClusterCategory();
catalogCategoryRegistry.add(kubernetesClusterCategory);

View File

@ -69,5 +69,3 @@ export class WebLinkCategory extends CatalogCategory {
}, },
}; };
} }
catalogCategoryRegistry.add(new WebLinkCategory());

View File

@ -3,96 +3,10 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { action, computed, observable, makeObservable } from "mobx"; import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import { once } from "lodash"; import catalogCategoryRegistryInjectable from "./category-registry.injectable";
import { iter, getOrInsertMap, strictSet } from "../utils";
import type { Disposer } from "../utils";
import type { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
export type CategoryFilter = (category: CatalogCategory) => any; /**
* @deprecated use `di.inject(catalogCategoryRegistryInjectable)` instead
export class CatalogCategoryRegistry { */
protected categories = observable.set<CatalogCategory>(); export const catalogCategoryRegistry = asLegacyGlobalForExtensionApi(catalogCategoryRegistryInjectable);
protected groupKinds = new Map<string, Map<string, CatalogCategory>>();
protected filters = observable.set<CategoryFilter>([], {
deep: false,
});
constructor() {
makeObservable(this);
}
@action add(category: CatalogCategory): Disposer {
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group);
this.categories.add(category);
strictSet(byGroup, category.spec.names.kind, category);
return () => {
this.categories.delete(category);
byGroup.delete(category.spec.names.kind);
};
}
@computed get items() {
return Array.from(this.categories);
}
@computed get filteredItems() {
return Array.from(
iter.reduce(
this.filters,
iter.filter,
this.items.values(),
),
);
}
getForGroupKind<T extends CatalogCategory>(group: string, kind: string): T | undefined {
return this.groupKinds.get(group)?.get(kind) as T;
}
getEntityForData(data: CatalogEntityData & CatalogEntityKindData) {
const category = this.getCategoryForEntity(data);
if (!category) {
return null;
}
const splitApiVersion = data.apiVersion.split("/");
const version = splitApiVersion[1];
const specVersion = category.spec.versions.find((v) => v.name === version);
if (!specVersion) {
return null;
}
return new specVersion.entityClass(data);
}
getCategoryForEntity<T extends CatalogCategory>(data: CatalogEntityData & CatalogEntityKindData): T | undefined {
const splitApiVersion = data.apiVersion.split("/");
const group = splitApiVersion[0];
return this.getForGroupKind(group, data.kind);
}
getByName(name: string) {
return this.items.find(category => category.metadata?.name == name);
}
/**
* Add a new filter to the set of category filters
* @param fn The function that should return a truthy value if that category should be displayed
* @returns A function to remove that filter
*/
addCatalogCategoryFilter(fn: CategoryFilter): Disposer {
this.filters.add(fn);
return once(() => void this.filters.delete(fn));
}
}
export const catalogCategoryRegistry = new CatalogCategoryRegistry();

View File

@ -0,0 +1,23 @@
/**
* 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 { GeneralCategory, kubernetesClusterCategory, WebLinkCategory } from "../catalog-entities";
import { CatalogCategoryRegistry } from "./category-registry";
const catalogCategoryRegistryInjectable = getInjectable({
id: "catalog-category-registry",
instantiate: () => {
const registry = new CatalogCategoryRegistry();
// TODO: move to different place
registry.add(new GeneralCategory());
registry.add(kubernetesClusterCategory);
registry.add(new WebLinkCategory());
return registry;
},
});
export default catalogCategoryRegistryInjectable;

View File

@ -0,0 +1,103 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { action, computed, observable, makeObservable } from "mobx";
import { once } from "lodash";
import { iter, getOrInsertMap, strictSet } from "../utils";
import type { Disposer } from "../utils";
import type { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
export type CategoryFilter = (category: CatalogCategory) => any;
export class CatalogCategoryRegistry {
protected readonly categories = observable.set<CatalogCategory>();
protected readonly groupKinds = new Map<string, Map<string, CatalogCategory>>();
protected readonly filters = observable.set<CategoryFilter>([], {
deep: false,
});
constructor() {
makeObservable(this);
}
@action add(category: CatalogCategory): Disposer {
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group);
this.categories.add(category);
strictSet(byGroup, category.spec.names.kind, category);
return () => {
this.categories.delete(category);
byGroup.delete(category.spec.names.kind);
};
}
@computed get items() {
return Array.from(this.categories);
}
@computed get filteredItems() {
return Array.from(
iter.reduce(
this.filters,
iter.filter,
this.items.values(),
),
);
}
getForGroupKind<T extends CatalogCategory>(group: string, kind: string): T | undefined {
return this.groupKinds.get(group)?.get(kind) as T;
}
getEntityForData(data: CatalogEntityData & CatalogEntityKindData) {
const category = this.getCategoryForEntity(data);
if (!category) {
return null;
}
const splitApiVersion = data.apiVersion.split("/");
const version = splitApiVersion[1];
const specVersion = category.spec.versions.find((v) => v.name === version);
if (!specVersion) {
return null;
}
return new specVersion.entityClass(data);
}
hasCategoryForEntity({ kind, apiVersion }: CatalogEntityData & CatalogEntityKindData): boolean {
const splitApiVersion = apiVersion.split("/");
const group = splitApiVersion[0];
return this.groupKinds.get(group)?.has(kind) ?? false;
}
getCategoryForEntity<T extends CatalogCategory>(data: CatalogEntityData & CatalogEntityKindData): T | undefined {
const splitApiVersion = data.apiVersion.split("/");
const group = splitApiVersion[0];
return this.getForGroupKind(group, data.kind);
}
getByName(name: string) {
return this.items.find(category => category.metadata?.name == name);
}
/**
* Add a new filter to the set of category filters
* @param fn The function that should return a truthy value if that category should be displayed
* @returns A function to remove that filter
*/
addCatalogCategoryFilter(fn: CategoryFilter): Disposer {
this.filters.add(fn);
return once(() => void this.filters.delete(fn));
}
}

View File

@ -0,0 +1,20 @@
/**
* 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 { CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
import catalogCategoryRegistryInjectable from "./category-registry.injectable";
export type HasCategoryForEntity = (data: CatalogEntityData & CatalogEntityKindData) => boolean;
const hasCategoryForEntityInjectable = getInjectable({
id: "has-category-for-entity",
instantiate: (di): HasCategoryForEntity => {
const registry = di.inject(catalogCategoryRegistryInjectable);
return (data) => registry.hasCategoryForEntity(data);
},
});
export default hasCategoryForEntityInjectable;

View File

@ -4,4 +4,5 @@
*/ */
export * from "./catalog-category-registry"; export * from "./catalog-category-registry";
export * from "./category-registry";
export * from "./catalog-entity"; export * from "./catalog-entity";

View File

@ -0,0 +1,20 @@
/**
* 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 hotbarStoreInjectable from "./store.injectable";
import type { CreateHotbarData, CreateHotbarOptions } from "./types";
export type AddHotbar = (data: CreateHotbarData, opts?: CreateHotbarOptions) => void;
const addHotbarInjectable = getInjectable({
id: "add-hotbar",
instantiate: (di): AddHotbar => {
const store = di.inject(hotbarStoreInjectable);
return (data, opts) => store.add(data, opts);
},
});
export default addHotbarInjectable;

View File

@ -3,8 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import catalogCatalogEntityInjectable from "./catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable"; import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
import { HotbarStore } from "./hotbar-store"; import { HotbarStore } from "./store";
import loggerInjectable from "../logger.injectable";
const hotbarStoreInjectable = getInjectable({ const hotbarStoreInjectable = getInjectable({
id: "hotbar-store", id: "hotbar-store",
@ -14,6 +15,7 @@ const hotbarStoreInjectable = getInjectable({
return HotbarStore.createInstance({ return HotbarStore.createInstance({
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable), catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
logger: di.inject(loggerInjectable),
}); });
}, },

View File

@ -3,23 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { action, comparer, observable, makeObservable, computed, runInAction } from "mobx"; import { action, comparer, observable, makeObservable, computed } from "mobx";
import { BaseStore } from "./base-store"; import { BaseStore } from "../base-store";
import migrations from "../migrations/hotbar-store"; import migrations from "../../migrations/hotbar-store";
import { toJS } from "./utils"; import { toJS } from "../utils";
import type { CatalogEntity } from "./catalog"; import type { CatalogEntity } from "../catalog";
import logger from "../main/logger"; import { broadcastMessage } from "../ipc";
import { broadcastMessage } from "./ipc"; import type { Hotbar, CreateHotbarData, CreateHotbarOptions } from "./types";
import type { import { defaultHotbarCells, getEmptyHotbar } from "./types";
Hotbar, import { hotbarTooManyItemsChannel } from "../ipc/hotbar";
CreateHotbarData, import type { GeneralEntity } from "../catalog-entities";
CreateHotbarOptions } from "./hotbar-types"; import type { Logger } from "../logger";
import { import assert from "assert";
defaultHotbarCells,
getEmptyHotbar,
} from "./hotbar-types";
import { hotbarTooManyItemsChannel } from "./ipc/hotbar";
import type { GeneralEntity } from "./catalog-entities";
export interface HotbarStoreModel { export interface HotbarStoreModel {
hotbars: Hotbar[]; hotbars: Hotbar[];
@ -27,7 +22,8 @@ export interface HotbarStoreModel {
} }
interface Dependencies { interface Dependencies {
catalogCatalogEntity: GeneralEntity; readonly catalogCatalogEntity: GeneralEntity;
readonly logger: Logger;
} }
export class HotbarStore extends BaseStore<HotbarStoreModel> { export class HotbarStore extends BaseStore<HotbarStoreModel> {
@ -35,7 +31,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
@observable hotbars: Hotbar[] = []; @observable hotbars: Hotbar[] = [];
@observable private _activeHotbarId!: string; @observable private _activeHotbarId!: string;
constructor(private dependencies: Dependencies) { constructor(private readonly dependencies: Dependencies) {
super({ super({
configName: "lens-hotbar-store", configName: "lens-hotbar-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
@ -62,7 +58,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
this._activeHotbarId = this.hotbars[hotbar].id; this._activeHotbarId = this.hotbars[hotbar].id;
} }
} else if (typeof hotbar === "string") { } else if (typeof hotbar === "string") {
if (this.getById(hotbar)) { if (this.findById(hotbar)) {
this._activeHotbarId = hotbar; this._activeHotbarId = hotbar;
} }
} else { } else {
@ -121,47 +117,34 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
} }
getActive(): Hotbar { getActive(): Hotbar {
const hotbar = this.getById(this.activeHotbarId); const hotbar = this.findById(this.activeHotbarId);
if (hotbar) { assert(hotbar, "There MUST always be an active hotbar");
return hotbar;
}
runInAction(() => { return hotbar;
if (this.hotbars.length === 0) {
this.hotbars.push(getEmptyHotbar("Default"));
}
this._activeHotbarId = this.hotbars[0].id;
});
return this.hotbars[0];
} }
getByName(name: string) { findByName(name: string) {
return this.hotbars.find((hotbar) => hotbar.name === name); return this.hotbars.find((hotbar) => hotbar.name === name);
} }
getById(id: string) { findById(id: string) {
return this.hotbars.find((hotbar) => hotbar.id === id); return this.hotbars.find((hotbar) => hotbar.id === id);
} }
add = action( @action
( add(data: CreateHotbarData, { setActive = false }: CreateHotbarOptions = {}) {
data: CreateHotbarData, const hotbar = getEmptyHotbar(data.name, data.id);
{ setActive = false }: CreateHotbarOptions = {},
) => {
const hotbar = getEmptyHotbar(data.name, data.id);
this.hotbars.push(hotbar); this.hotbars.push(hotbar);
if (setActive) { if (setActive) {
this._activeHotbarId = hotbar.id; this._activeHotbarId = hotbar.id;
} }
}, }
);
setHotbarName = action((id: string, name: string): void => { @action
setHotbarName(id: string, name: string): void {
const index = this.hotbars.findIndex((hotbar) => hotbar.id === id); const index = this.hotbars.findIndex((hotbar) => hotbar.id === id);
if (index < 0) { if (index < 0) {
@ -172,19 +155,18 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
} }
this.hotbars[index].name = name; this.hotbars[index].name = name;
}); }
remove = action((hotbar: Hotbar) => { @action
if (this.hotbars.length <= 1) { remove(hotbar: Hotbar) {
throw new Error("Cannot remove the last hotbar"); assert(this.hotbars.length >= 2, "Cannot remove the last hotbar");
}
this.hotbars = this.hotbars.filter((h) => h !== hotbar); this.hotbars = this.hotbars.filter((h) => h !== hotbar);
if (this.activeHotbarId === hotbar.id) { if (this.activeHotbarId === hotbar.id) {
this.setActiveHotbar(0); this.setActiveHotbar(0);
} }
}); }
@action @action
addToHotbar(item: CatalogEntity, cellIndex?: number) { addToHotbar(item: CatalogEntity, cellIndex?: number) {
@ -223,7 +205,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
} else if (0 <= cellIndex && cellIndex < hotbar.items.length) { } else if (0 <= cellIndex && cellIndex < hotbar.items.length) {
hotbar.items[cellIndex] = newItem; hotbar.items[cellIndex] = newItem;
} else { } else {
logger.error( this.dependencies.logger.error(
`[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`, `[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`,
{ entityId: uid, hotbarId: hotbar.id, cellIndex }, { entityId: uid, hotbarId: hotbar.id, cellIndex },
); );
@ -260,8 +242,9 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
findClosestEmptyIndex(from: number, direction = 1) { findClosestEmptyIndex(from: number, direction = 1) {
let index = from; let index = from;
const hotbar = this.getActive();
while (this.getActive().items[index] != null) { while (hotbar.items[index] != null) {
index += direction; index += direction;
} }
@ -328,11 +311,9 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
return false; return false;
} }
return ( const indexInActiveHotbar = this.getActive().items.findIndex(item => item?.entity.uid === entity.getId());
this.getActive().items.findIndex(
(item) => item?.entity.uid === entity.getId(), return indexInActiveHotbar >= 0;
) >= 0
);
} }
getDisplayLabel(hotbar: Hotbar): string { getDisplayLabel(hotbar: Hotbar): string {

View File

@ -4,8 +4,8 @@
*/ */
import * as uuid from "uuid"; import * as uuid from "uuid";
import type { Tuple } from "./utils"; import type { Tuple } from "../utils";
import { tuple } from "./utils"; import { tuple } from "../utils";
export interface HotbarItem { export interface HotbarItem {
entity: { entity: {

View File

@ -4,6 +4,7 @@
*/ */
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { iter } from "../../common/utils";
const legacyGlobalDis = new Map<Environments, DiContainer>(); const legacyGlobalDis = new Map<Environments, DiContainer>();
@ -20,13 +21,17 @@ export const setLegacyGlobalDiForExtensionApi = (
}; };
export const getLegacyGlobalDiForExtensionApi = () => { export const getLegacyGlobalDiForExtensionApi = () => {
const globalDis = [...legacyGlobalDis.values()]; if (legacyGlobalDis.size > 1) {
if (globalDis.length > 1) {
throw new Error("Tried to get DI container using legacy globals where there is multiple containers available."); throw new Error("Tried to get DI container using legacy globals where there is multiple containers available.");
} }
return globalDis[0]; const di = iter.first(legacyGlobalDis.values());
if (!di) {
throw new Error("Tried to get DI container using legacy globals where there is no containers available.");
}
return di;
}; };
export function getEnvironmentSpecificLegacyGlobalDiForExtensionApi(environment: Environments) { export function getEnvironmentSpecificLegacyGlobalDiForExtensionApi(environment: Environments) {

View File

@ -3,10 +3,6 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
/**
* @jest-environment jsdom
*/
import { clearKubeconfigEnvVars } from "../utils/clear-kube-env-vars"; import { clearKubeconfigEnvVars } from "../utils/clear-kube-env-vars";
describe("clearKubeconfigEnvVars tests", () => { describe("clearKubeconfigEnvVars tests", () => {

View File

@ -227,7 +227,6 @@ export const computeDiff = ({ directoryForKubeConfigs, createCluster }: Dependen
} }
} }
} catch (error) { } catch (error) {
console.log(error);
logger.warn(`${logPrefix} Failed to compute diff: ${error}`, { filePath }); logger.warn(`${logPrefix} Failed to compute diff: ${error}`, { filePath });
source.clear(); // clear source if we have failed so as to not show outdated information source.clear(); // clear source if we have failed so as to not show outdated information
} }

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import catalogEntityRegistryInjectable from "../catalog/catalog-entity-registry.injectable"; import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable";
import { generalCatalogEntityInjectionToken } from "../../common/catalog-entities/general-catalog-entities/general-catalog-entity-injection-token"; import { generalCatalogEntityInjectionToken } from "../../common/catalog-entities/general-catalog-entities/general-catalog-entity-injection-token";
import { computed } from "mobx"; import { computed } from "mobx";

View File

@ -3,50 +3,10 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { action, computed, type IComputedValue, type IObservableArray, makeObservable, observable } from "mobx"; import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import type { CatalogCategoryRegistry, CatalogEntity } from "../../common/catalog"; import catalogEntityRegistryInjectable from "./entity-registry.injectable";
import { catalogCategoryRegistry } from "../../common/catalog";
import { iter } from "../../common/utils";
export class CatalogEntityRegistry { /**
protected sources = observable.map<string, IComputedValue<CatalogEntity[]>>(); * @deprecated use `di.inject(catalogEntityRegistryInjectable)` instead
*/
constructor(private categoryRegistry: CatalogCategoryRegistry) { export const catalogEntityRegistry = asLegacyGlobalForExtensionApi(catalogEntityRegistryInjectable);
makeObservable(this);
}
@action addObservableSource(id: string, source: IObservableArray<CatalogEntity>) {
this.sources.set(id, computed(() => source));
}
@action addComputedSource(id: string, source: IComputedValue<CatalogEntity[]>) {
this.sources.set(id, source);
}
@action removeSource(id: string) {
this.sources.delete(id);
}
@computed get items(): CatalogEntity[] {
return Array.from(
iter.filter(
iter.flatMap(this.sources.values(), source => source.get()),
entity => this.categoryRegistry.getCategoryForEntity(entity),
),
);
}
findById(id: string): CatalogEntity | undefined {
return this.items.find(entity => entity.getId() === id);
}
filterItemsForApiKind(apiVersion: string, kind: string): CatalogEntity[] {
return this.items.filter((item) => item.apiVersion === apiVersion && item.kind === kind);
}
filterItemsByPredicate<E extends CatalogEntity>(filter: (item: CatalogEntity) => item is E): E[] {
return this.items.filter(filter);
}
}
export const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry);

View File

@ -3,12 +3,14 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { catalogEntityRegistry } from "./catalog-entity-registry"; import hasCategoryForEntityInjectable from "../../common/catalog/has-category-for-entity.injectable";
import { CatalogEntityRegistry } from "./entity-registry";
const catalogEntityRegistryInjectable = getInjectable({ const catalogEntityRegistryInjectable = getInjectable({
id: "catalog-entity-registry", id: "catalog-entity-registry",
instantiate: () => catalogEntityRegistry, instantiate: (di) => new CatalogEntityRegistry({
causesSideEffects: true, hasCategoryForEntity: di.inject(hasCategoryForEntityInjectable),
}),
}); });
export default catalogEntityRegistryInjectable; export default catalogEntityRegistryInjectable;

View File

@ -0,0 +1,54 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { action, computed, type IComputedValue, type IObservableArray, makeObservable, observable } from "mobx";
import type { CatalogEntity } from "../../common/catalog";
import type { HasCategoryForEntity } from "../../common/catalog/has-category-for-entity.injectable";
import { iter } from "../../common/utils";
interface Dependencies {
readonly hasCategoryForEntity: HasCategoryForEntity;
}
export class CatalogEntityRegistry {
protected sources = observable.map<string, IComputedValue<CatalogEntity[]>>();
constructor(protected readonly dependencies: Dependencies) {
makeObservable(this);
}
@action addObservableSource(id: string, source: IObservableArray<CatalogEntity>) {
this.sources.set(id, computed(() => source));
}
@action addComputedSource(id: string, source: IComputedValue<CatalogEntity[]>) {
this.sources.set(id, source);
}
@action removeSource(id: string) {
this.sources.delete(id);
}
@computed get items(): CatalogEntity[] {
return Array.from(
iter.filter(
iter.flatMap(this.sources.values(), source => source.get()),
entity => this.dependencies.hasCategoryForEntity(entity),
),
);
}
findById(id: string): CatalogEntity | undefined {
return this.items.find(entity => entity.getId() === id);
}
filterItemsForApiKind(apiVersion: string, kind: string): CatalogEntity[] {
return this.items.filter((item) => item.apiVersion === apiVersion && item.kind === kind);
}
filterItemsByPredicate<E extends CatalogEntity>(filter: (item: CatalogEntity) => item is E): E[] {
return this.items.filter(filter);
}
}

View File

@ -4,7 +4,7 @@
*/ */
import glob from "glob"; import glob from "glob";
import { kebabCase, memoize, noop } from "lodash/fp"; import { kebabCase, memoize } from "lodash/fp";
import { createContainer } from "@ogre-tools/injectable"; import { createContainer } from "@ogre-tools/injectable";
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
@ -26,7 +26,6 @@ import clusterStoreInjectable from "../common/cluster-store/cluster-store.inject
import type { ClusterStore } from "../common/cluster-store/cluster-store"; import type { ClusterStore } from "../common/cluster-store/cluster-store";
import type { Cluster } from "../common/cluster/cluster"; import type { Cluster } from "../common/cluster/cluster";
import userStoreInjectable from "../common/user-store/user-store.injectable"; import userStoreInjectable from "../common/user-store/user-store.injectable";
import type { UserStore } from "../common/user-store";
import isMacInjectable from "../common/vars/is-mac.injectable"; import isMacInjectable from "../common/vars/is-mac.injectable";
import isWindowsInjectable from "../common/vars/is-windows.injectable"; import isWindowsInjectable from "../common/vars/is-windows.injectable";
import isLinuxInjectable from "../common/vars/is-linux.injectable"; import isLinuxInjectable from "../common/vars/is-linux.injectable";
@ -34,11 +33,29 @@ import getAbsolutePathInjectable from "../common/path/get-absolute-path.injectab
import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake"; import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake";
import joinPathsInjectable from "../common/path/join-paths.injectable"; import joinPathsInjectable from "../common/path/join-paths.injectable";
import { joinPathsFake } from "../common/test-utils/join-paths-fake"; import { joinPathsFake } from "../common/test-utils/join-paths-fake";
import hotbarStoreInjectable from "../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../common/hotbars/store.injectable";
export interface GetDiOptions {
doGeneralOverrides?: boolean;
overrideHotbarStore?: boolean;
overrideUserStore?: boolean;
overrideExtensionsStore?: boolean;
overrideClusterStore?: boolean;
overrideFileSystemProvisionerStore?: boolean;
}
export function getDiForUnitTesting(opts: GetDiOptions = {}) {
const {
doGeneralOverrides = false,
} = opts;
const {
overrideHotbarStore = doGeneralOverrides,
overrideUserStore = doGeneralOverrides,
overrideExtensionsStore = doGeneralOverrides,
overrideClusterStore = doGeneralOverrides,
overrideFileSystemProvisionerStore = doGeneralOverrides,
} = opts;
export const getDiForUnitTesting = (
{ doGeneralOverrides } = { doGeneralOverrides: false },
) => {
const di = createContainer(); const di = createContainer();
setLegacyGlobalDiForExtensionApi(di, Environments.main); setLegacyGlobalDiForExtensionApi(di, Environments.main);
@ -55,6 +72,26 @@ export const getDiForUnitTesting = (
di.preventSideEffects(); di.preventSideEffects();
if (overrideHotbarStore) {
di.override(hotbarStoreInjectable, () => ({}));
}
if (overrideUserStore) {
di.override(userStoreInjectable, () => ({}));
}
if (overrideExtensionsStore) {
di.override(extensionsStoreInjectable, () => ({ isEnabled: (opts) => (void opts, false) }) as ExtensionsStore);
}
if (overrideClusterStore) {
di.override(clusterStoreInjectable, () => ({ getById: (id) => (void id, {}) as Cluster }) as ClusterStore);
}
if (overrideFileSystemProvisionerStore) {
di.override(fileSystemProvisionerStoreInjectable, () => ({}) as FileSystemProvisionerStore);
}
if (doGeneralOverrides) { if (doGeneralOverrides) {
di.override(isMacInjectable, () => true); di.override(isMacInjectable, () => true);
di.override(isWindowsInjectable, () => false); di.override(isWindowsInjectable, () => false);
@ -63,17 +100,6 @@ export const getDiForUnitTesting = (
di.override(getAbsolutePathInjectable, () => getAbsolutePathFake); di.override(getAbsolutePathInjectable, () => getAbsolutePathFake);
di.override(joinPathsInjectable, () => joinPathsFake); di.override(joinPathsInjectable, () => joinPathsFake);
// eslint-disable-next-line unused-imports/no-unused-vars-ts
di.override(extensionsStoreInjectable, () => ({ isEnabled: ({ id, isBundled }) => false }) as ExtensionsStore);
di.override(hotbarStoreInjectable, () => ({}));
di.override(fileSystemProvisionerStoreInjectable, () => ({}) as FileSystemProvisionerStore);
// eslint-disable-next-line unused-imports/no-unused-vars-ts
di.override(clusterStoreInjectable, () => ({ getById: (id): Cluster => ({}) as Cluster }) as ClusterStore);
di.override(userStoreInjectable, () => ({}) as UserStore);
di.override( di.override(
getElectronAppPathInjectable, getElectronAppPathInjectable,
() => (name: string) => `some-electron-app-path-for-${kebabCase(name)}`, () => (name: string) => `some-electron-app-path-for-${kebabCase(name)}`,
@ -104,16 +130,16 @@ export const getDiForUnitTesting = (
}); });
di.override(loggerInjectable, () => ({ di.override(loggerInjectable, () => ({
warn: noop, warn: jest.fn(),
debug: noop, debug: jest.fn(),
error: (message: string, ...args: any) => console.error(message, ...args), error: jest.fn(),
info: noop, info: jest.fn(),
silly: noop, silly: jest.fn(),
})); }));
} }
return di; return di;
}; }
const getInjectableFilePaths = memoize(() => [ const getInjectableFilePaths = memoize(() => [
...glob.sync("./**/*.injectable.{ts,tsx}", { cwd: __dirname }), ...glob.sync("./**/*.injectable.{ts,tsx}", { cwd: __dirname }),

View File

@ -59,7 +59,7 @@ import assert from "assert";
import windowManagerInjectable from "./window-manager.injectable"; import windowManagerInjectable from "./window-manager.injectable";
import navigateToPreferencesInjectable from "../common/front-end-routing/routes/preferences/navigate-to-preferences.injectable"; import navigateToPreferencesInjectable from "../common/front-end-routing/routes/preferences/navigate-to-preferences.injectable";
import syncGeneralCatalogEntitiesInjectable from "./catalog-sources/sync-general-catalog-entities.injectable"; import syncGeneralCatalogEntitiesInjectable from "./catalog-sources/sync-general-catalog-entities.injectable";
import hotbarStoreInjectable from "../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../common/hotbars/store.injectable";
import applicationMenuItemsInjectable from "./menu/application-menu-items.injectable"; import applicationMenuItemsInjectable from "./menu/application-menu-items.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { init } from "@sentry/electron/main"; import { init } from "@sentry/electron/main";

View File

@ -5,7 +5,7 @@
// Cleans up a store that had the state related data stored // Cleans up a store that had the state related data stored
import type { MigrationDeclaration } from "../helpers"; import type { MigrationDeclaration } from "../helpers";
import { getEmptyHotbar } from "../../common/hotbar-types"; import { getEmptyHotbar } from "../../common/hotbars/types";
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import catalogCatalogEntityInjectable from "../../common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable"; import catalogCatalogEntityInjectable from "../../common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";

View File

@ -4,7 +4,7 @@
*/ */
// Cleans up a store that had the state related data stored // Cleans up a store that had the state related data stored
import type { Hotbar } from "../../common/hotbar-types"; import type { Hotbar } from "../../common/hotbars/types";
import * as uuid from "uuid"; import * as uuid from "uuid";
import type { MigrationDeclaration } from "../helpers"; import type { MigrationDeclaration } from "../helpers";

View File

@ -8,8 +8,8 @@ import { isNull } from "lodash";
import path from "path"; import path from "path";
import * as uuid from "uuid"; import * as uuid from "uuid";
import type { ClusterStoreModel } from "../../common/cluster-store/cluster-store"; import type { ClusterStoreModel } from "../../common/cluster-store/cluster-store";
import type { Hotbar, HotbarItem } from "../../common/hotbar-types"; import type { Hotbar, HotbarItem } from "../../common/hotbars/types";
import { defaultHotbarCells, getEmptyHotbar } from "../../common/hotbar-types"; import { defaultHotbarCells, getEmptyHotbar } from "../../common/hotbars/types";
import type { MigrationDeclaration } from "../helpers"; import type { MigrationDeclaration } from "../helpers";
import { migrationLog } from "../helpers"; import { migrationLog } from "../helpers";
import { generateNewIdFor } from "../utils"; import { generateNewIdFor } from "../utils";

View File

@ -3,8 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { Hotbar } from "../../common/hotbar-types"; import type { Hotbar } from "../../common/hotbars/types";
import { catalogEntityRegistry } from "../../main/catalog"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import catalogEntityRegistryInjectable from "../../main/catalog/entity-registry.injectable";
import type { MigrationDeclaration } from "../helpers"; import type { MigrationDeclaration } from "../helpers";
export default { export default {
@ -12,6 +13,8 @@ export default {
run(store) { run(store) {
const rawHotbars = store.get("hotbars"); const rawHotbars = store.get("hotbars");
const hotbars: Hotbar[] = Array.isArray(rawHotbars) ? rawHotbars : []; const hotbars: Hotbar[] = Array.isArray(rawHotbars) ? rawHotbars : [];
const di = getLegacyGlobalDiForExtensionApi();
const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
for (const hotbar of hotbars) { for (const hotbar of hotbars) {
for (let i = 0; i < hotbar.items.length; i += 1) { for (let i = 0; i < hotbar.items.length; i += 1) {

View File

@ -40,7 +40,7 @@ import historyInjectable from "./navigation/history.injectable";
import themeStoreInjectable from "./theme-store.injectable"; import themeStoreInjectable from "./theme-store.injectable";
import navigateToAddClusterInjectable from "../common/front-end-routing/routes/add-cluster/navigate-to-add-cluster.injectable"; import navigateToAddClusterInjectable from "../common/front-end-routing/routes/add-cluster/navigate-to-add-cluster.injectable";
import addSyncEntriesInjectable from "./initializers/add-sync-entries.injectable"; import addSyncEntriesInjectable from "./initializers/add-sync-entries.injectable";
import hotbarStoreInjectable from "../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../common/hotbars/store.injectable";
import { bindEvents } from "./navigation/events"; import { bindEvents } from "./navigation/events";
import assert from "assert"; import assert from "assert";
import openDeleteClusterDialogInjectable from "./components/delete-cluster-dialog/open.injectable"; import openDeleteClusterDialogInjectable from "./components/delete-cluster-dialog/open.injectable";

View File

@ -13,7 +13,7 @@ import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
import type { AdditionalCategoryColumnRegistration, CategoryColumnRegistration } from "../custom-category-columns"; import type { AdditionalCategoryColumnRegistration, CategoryColumnRegistration } from "../custom-category-columns";
import type { CategoryColumns, GetCategoryColumnsParams } from "../get-category-columns.injectable"; import type { CategoryColumns, GetCategoryColumnsParams } from "../get-category-columns.injectable";
import getCategoryColumnsInjectable from "../get-category-columns.injectable"; import getCategoryColumnsInjectable from "../get-category-columns.injectable";
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
class TestCategory extends CatalogCategory { class TestCategory extends CatalogCategory {
apiVersion = "catalog.k8slens.dev/v1alpha1"; apiVersion = "catalog.k8slens.dev/v1alpha1";

View File

@ -41,8 +41,8 @@ import catalogRouteParametersInjectable from "./catalog-route-parameters.injecta
import { browseCatalogTab } from "./catalog-browse-tab"; import { browseCatalogTab } from "./catalog-browse-tab";
import type { AppEvent } from "../../../common/app-event-bus/event-bus"; import type { AppEvent } from "../../../common/app-event-bus/event-bus";
import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable"; import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
interface Dependencies { interface Dependencies {
catalogPreviousActiveTabStorage: { set: (value: string ) => void; get: () => string }; catalogPreviousActiveTabStorage: { set: (value: string ) => void; get: () => string };

View File

@ -9,17 +9,17 @@ import { MenuItem } from "../menu";
import type { CatalogEntity } from "../../api/catalog-entity"; import type { CatalogEntity } from "../../api/catalog-entity";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
interface Dependencies { interface Dependencies {
hotbarStore: HotbarStore; hotbarStore: HotbarStore;
} }
interface HotbarToggleMenuItemProps { interface HotbarToggleMenuItemProps {
entity: CatalogEntity; entity: CatalogEntity;
addContent: ReactNode; addContent: ReactNode;
removeContent: ReactNode; removeContent: ReactNode;
} }
function NonInjectedHotbarToggleMenuItem({ function NonInjectedHotbarToggleMenuItem({

View File

@ -10,8 +10,8 @@ import { Avatar } from "../avatar";
import { Icon } from "../icon"; import { Icon } from "../icon";
import React from "react"; import React from "react";
import type { RegisteredAdditionalCategoryColumn } from "./custom-category-columns"; import type { RegisteredAdditionalCategoryColumn } from "./custom-category-columns";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
const renderEntityName = (hotbarStore: HotbarStore) => (entity: CatalogEntity) => { const renderEntityName = (hotbarStore: HotbarStore) => (entity: CatalogEntity) => {
const isItemInHotbar = hotbarStore.isAddedToActive(entity); const isItemInHotbar = hotbarStore.isAddedToActive(entity);

View File

@ -16,7 +16,7 @@ import { createClusterInjectionToken } from "../../../../common/cluster/create-c
import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable"; import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable";
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 hotbarStoreInjectable from "../../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
import type { OpenDeleteClusterDialog } from "../open.injectable"; import type { OpenDeleteClusterDialog } from "../open.injectable";
import openDeleteClusterDialogInjectable from "../open.injectable"; import openDeleteClusterDialogInjectable from "../open.injectable";

View File

@ -17,9 +17,9 @@ import { Icon } from "../icon";
import { Select } from "../select"; import { Select } from "../select";
import { Checkbox } from "../checkbox"; import { Checkbox } from "../checkbox";
import { requestClearClusterAsDeleting, requestDeleteCluster, requestSetClusterAsDeleting } from "../../ipc"; import { requestClearClusterAsDeleting, requestDeleteCluster, requestSetClusterAsDeleting } from "../../ipc";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { DeleteClusterDialogState } from "./state.injectable"; import type { DeleteClusterDialogState } from "./state.injectable";
import deleteClusterDialogStateInjectable from "./state.injectable"; import deleteClusterDialogStateInjectable from "./state.injectable";

View File

@ -11,7 +11,7 @@ import type { DiContainer } from "@ogre-tools/injectable";
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 hotbarStoreInjectable from "../../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
import { ThemeStore } from "../../../theme.store"; import { ThemeStore } from "../../../theme.store";
import { ConfirmDialog } from "../../confirm-dialog"; import { ConfirmDialog } from "../../confirm-dialog";
import { UserStore } from "../../../../common/user-store"; import { UserStore } from "../../../../common/user-store";
@ -19,7 +19,7 @@ import mockFs from "mock-fs";
import directoryForUserDataInjectable from "../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForUserDataInjectable from "../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import getConfigurationFileModelInjectable from "../../../../common/get-configuration-file-model/get-configuration-file-model.injectable"; import getConfigurationFileModelInjectable from "../../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
import appVersionInjectable from "../../../../common/get-configuration-file-model/app-version/app-version.injectable"; import appVersionInjectable from "../../../../common/get-configuration-file-model/app-version/app-version.injectable";
import type { HotbarStore } from "../../../../common/hotbar-store"; import type { HotbarStore } from "../../../../common/hotbars/store";
const mockHotbars: Partial<Record<string, any>> = { const mockHotbars: Partial<Record<string, any>> = {
"1": { "1": {

View File

@ -7,11 +7,11 @@ import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { InputValidator } from "../input"; import type { InputValidator } from "../input";
import { Input } from "../input"; import { Input } from "../input";
import type { CreateHotbarData, CreateHotbarOptions } from "../../../common/hotbar-types"; import type { CreateHotbarData, CreateHotbarOptions } from "../../../common/hotbars/types";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable";
import uniqueHotbarNameInjectable from "../input/validators/unique-hotbar-name.injectable"; import uniqueHotbarNameInjectable from "../input/validators/unique-hotbar-name.injectable";
import addHotbarInjectable from "../../../common/hotbars/add-hotbar.injectable";
interface Dependencies { interface Dependencies {
closeCommandOverlay: () => void; closeCommandOverlay: () => void;
@ -51,7 +51,7 @@ const NonInjectedHotbarAddCommand = observer(({ closeCommandOverlay, addHotbar,
export const HotbarAddCommand = withInjectables<Dependencies>(NonInjectedHotbarAddCommand, { export const HotbarAddCommand = withInjectables<Dependencies>(NonInjectedHotbarAddCommand, {
getProps: (di, props) => ({ getProps: (di, props) => ({
closeCommandOverlay: di.inject(commandOverlayInjectable).close, closeCommandOverlay: di.inject(commandOverlayInjectable).close,
addHotbar: di.inject(hotbarStoreInjectable).add, addHotbar: di.inject(addHotbarInjectable),
uniqueHotbarName: di.inject(uniqueHotbarNameInjectable), uniqueHotbarName: di.inject(uniqueHotbarNameInjectable),
...props, ...props,
}), }),

View File

@ -16,12 +16,12 @@ import { DragDropContext, Draggable, Droppable, type DropResult } from "react-be
import { HotbarSelector } from "./hotbar-selector"; import { HotbarSelector } from "./hotbar-selector";
import { HotbarCell } from "./hotbar-cell"; import { HotbarCell } from "./hotbar-cell";
import { HotbarIcon } from "./hotbar-icon"; import { HotbarIcon } from "./hotbar-icon";
import type { HotbarItem } from "../../../common/hotbar-types"; import type { HotbarItem } from "../../../common/hotbars/types";
import { defaultHotbarCells } from "../../../common/hotbar-types"; import { defaultHotbarCells } from "../../../common/hotbars/types";
import { action, makeObservable, observable } from "mobx"; import { action, makeObservable, observable } from "mobx";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
export interface HotbarMenuProps { export interface HotbarMenuProps {
className?: IClassName; className?: IClassName;
@ -118,7 +118,7 @@ class NonInjectedHotbarMenu extends React.Component<Dependencies & HotbarMenuPro
<Draggable <Draggable
draggableId={item.entity.uid} draggableId={item.entity.uid}
key={item.entity.uid} key={item.entity.uid}
index={0} index={0}
> >
{(provided, snapshot) => { {(provided, snapshot) => {
const style = { const style = {

View File

@ -6,19 +6,15 @@
import React from "react"; import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Select } from "../select"; import { Select } from "../select";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import { ConfirmDialog } from "../confirm-dialog"; import { ConfirmDialog } from "../confirm-dialog";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
import type { Hotbar } from "../../../common/hotbar-types"; import type { HotbarStore } from "../../../common/hotbars/store";
interface Dependencies { interface Dependencies {
closeCommandOverlay: () => void; closeCommandOverlay: () => void;
hotbarStore: { hotbarStore: HotbarStore;
hotbars: Hotbar[];
remove: (hotbar: Hotbar) => void;
getDisplayLabel: (hotbar: Hotbar) => string;
};
} }
const NonInjectedHotbarRemoveCommand = observer(({ const NonInjectedHotbarRemoveCommand = observer(({

View File

@ -6,22 +6,18 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Select } from "../select"; import { Select } from "../select";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { InputValidator } from "../input"; import type { InputValidator } from "../input";
import { Input } from "../input"; import { Input } from "../input";
import type { Hotbar } from "../../../common/hotbar-types"; import type { Hotbar } from "../../../common/hotbars/types";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
import uniqueHotbarNameInjectable from "../input/validators/unique-hotbar-name.injectable"; import uniqueHotbarNameInjectable from "../input/validators/unique-hotbar-name.injectable";
import type { HotbarStore } from "../../../common/hotbars/store";
interface Dependencies { interface Dependencies {
closeCommandOverlay: () => void; closeCommandOverlay: () => void;
hotbarStore: { hotbarStore: HotbarStore;
hotbars: Hotbar[];
getById: (id: string) => Hotbar | undefined;
setHotbarName: (id: string, name: string) => void;
getDisplayLabel: (hotbar: Hotbar) => string;
};
uniqueHotbarName: InputValidator<false>; uniqueHotbarName: InputValidator<false>;
} }

View File

@ -7,22 +7,18 @@ import styles from "./hotbar-selector.module.scss";
import React, { useRef, useState } from "react"; import React, { useRef, useState } from "react";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { Badge } from "../badge"; import { Badge } from "../badge";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import { HotbarSwitchCommand } from "./hotbar-switch-command"; import { HotbarSwitchCommand } from "./hotbar-switch-command";
import { Tooltip, TooltipPosition } from "../tooltip"; import { Tooltip, TooltipPosition } from "../tooltip";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { Hotbar } from "../../../common/hotbar-types"; import type { Hotbar } from "../../../common/hotbars/types";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";
import type { HotbarStore } from "../../../common/hotbars/store";
interface Dependencies { interface Dependencies {
hotbarStore: { hotbarStore: HotbarStore;
switchToPrevious: () => void;
switchToNext: () => void;
getActive: () => Hotbar;
getDisplayIndex: (hotbar: Hotbar) => string;
};
openCommandOverlay: (component: React.ReactElement) => void; openCommandOverlay: (component: React.ReactElement) => void;
} }

View File

@ -6,15 +6,15 @@
import React from "react"; import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Select } from "../select"; import { Select } from "../select";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { CommandOverlay } from "../command-palette"; import type { CommandOverlay } from "../command-palette";
import { HotbarAddCommand } from "./hotbar-add-command"; import { HotbarAddCommand } from "./hotbar-add-command";
import { HotbarRemoveCommand } from "./hotbar-remove-command"; import { HotbarRemoveCommand } from "./hotbar-remove-command";
import { HotbarRenameCommand } from "./hotbar-rename-command"; import { HotbarRenameCommand } from "./hotbar-rename-command";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
import type { Hotbar } from "../../../common/hotbar-types"; import type { Hotbar } from "../../../common/hotbars/types";
const hotbarAddAction = Symbol("hotbar-add"); const hotbarAddAction = Symbol("hotbar-add");
const hotbarRemoveAction = Symbol("hotbar-remove"); const hotbarRemoveAction = Symbol("hotbar-remove");

View File

@ -4,17 +4,21 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
import { inputValidator } from "../input_validators"; import { inputValidator } from "../input_validators";
const uniqueHotbarNameInjectable = getInjectable({ const uniqueHotbarNameInjectable = getInjectable({
id: "unique-hotbar-name", id: "unique-hotbar-name",
instantiate: di => inputValidator({ instantiate: di => {
condition: ({ required }) => required, const store = di.inject(hotbarStoreInjectable);
message: () => "Hotbar with this name already exists",
validate: value => !di.inject(hotbarStoreInjectable).getByName(value), return inputValidator({
}), condition: ({ required }) => required,
message: () => "Hotbar with this name already exists",
validate: value => !store.findByName(value),
});
},
}); });
export default uniqueHotbarNameInjectable; export default uniqueHotbarNameInjectable;

View File

@ -11,8 +11,8 @@ import { KubernetesCluster } from "../../../../common/catalog-entities";
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 hotbarStoreInjectable from "../../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../../common/hotbar-store"; import type { HotbarStore } from "../../../../common/hotbars/store";
const clusterEntity = new KubernetesCluster({ const clusterEntity = new KubernetesCluster({
metadata: { metadata: {

View File

@ -16,8 +16,8 @@ import { Menu, MenuItem } from "../menu";
import { ConfirmDialog } from "../confirm-dialog"; import { ConfirmDialog } from "../confirm-dialog";
import { Tooltip } from "../tooltip"; import { Tooltip } from "../tooltip";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../common/hotbar-store"; import type { HotbarStore } from "../../../common/hotbars/store";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
const contextMenu: CatalogEntityContextMenuContext = observable({ const contextMenu: CatalogEntityContextMenuContext = observable({

View File

@ -195,8 +195,6 @@ describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
expect(queryByTitle("Application")).toHaveAttribute("aria-expanded"); expect(queryByTitle("Application")).toHaveAttribute("aria-expanded");
expect(queryByTitle("Kubernetes")).toHaveAttribute("aria-expanded"); expect(queryByTitle("Kubernetes")).toHaveAttribute("aria-expanded");
}); });
// console.log(prettyDOM());
}); });
it("skips sections without headings", async () => { it("skips sections without headings", async () => {

View File

@ -4,7 +4,7 @@
*/ */
import glob from "glob"; import glob from "glob";
import { isEqual, isPlainObject, memoize, noop } from "lodash/fp"; import { isEqual, isPlainObject, memoize } from "lodash/fp";
import { createContainer } from "@ogre-tools/injectable"; import { createContainer } from "@ogre-tools/injectable";
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import getValueFromRegisteredChannelInjectable from "./app-paths/get-value-from-registered-channel/get-value-from-registered-channel.injectable"; import getValueFromRegisteredChannelInjectable from "./app-paths/get-value-from-registered-channel/get-value-from-registered-channel.injectable";
@ -32,7 +32,7 @@ import getAbsolutePathInjectable from "../common/path/get-absolute-path.injectab
import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake"; import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake";
import joinPathsInjectable from "../common/path/join-paths.injectable"; import joinPathsInjectable from "../common/path/join-paths.injectable";
import { joinPathsFake } from "../common/test-utils/join-paths-fake"; import { joinPathsFake } from "../common/test-utils/join-paths-fake";
import hotbarStoreInjectable from "../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../common/hotbars/store.injectable";
import terminalSpawningPoolInjectable from "./components/dock/terminal/terminal-spawning-pool.injectable"; import terminalSpawningPoolInjectable from "./components/dock/terminal/terminal-spawning-pool.injectable";
import hostedClusterIdInjectable from "../common/cluster-store/hosted-cluster-id.injectable"; import hostedClusterIdInjectable from "../common/cluster-store/hosted-cluster-id.injectable";
import createStorageInjectable from "./utils/create-storage/create-storage.injectable"; import createStorageInjectable from "./utils/create-storage/create-storage.injectable";
@ -130,10 +130,11 @@ export const getDiForUnitTesting = (
di.override(focusWindowInjectable, () => () => {}); di.override(focusWindowInjectable, () => () => {});
di.override(loggerInjectable, () => ({ di.override(loggerInjectable, () => ({
warn: noop, warn: jest.fn(),
debug: noop, debug: jest.fn(),
error: (message: string, ...args: any) => console.error(message, ...args), error: jest.fn(),
info: noop, info: jest.fn(),
silly: jest.fn(),
})); }));
} }

View File

@ -11,7 +11,7 @@ import { areArgsUpdateAvailableFromMain, UpdateAvailableChannel, onCorrect, ipcR
import { Notifications, notificationsStore } from "../components/notifications"; import { Notifications, notificationsStore } from "../components/notifications";
import { Button } from "../components/button"; import { Button } from "../components/button";
import { isMac } from "../../common/vars"; import { isMac } from "../../common/vars";
import { defaultHotbarCells } from "../../common/hotbar-types"; import { defaultHotbarCells } from "../../common/hotbars/types";
import { type ListNamespaceForbiddenArgs, clusterListNamespaceForbiddenChannel, isListNamespaceForbiddenArgs } from "../../common/ipc/cluster"; import { type ListNamespaceForbiddenArgs, clusterListNamespaceForbiddenChannel, isListNamespaceForbiddenArgs } from "../../common/ipc/cluster";
import { hotbarTooManyItemsChannel } from "../../common/ipc/hotbar"; import { hotbarTooManyItemsChannel } from "../../common/ipc/hotbar";
@ -31,7 +31,7 @@ function RenderYesButtons(props: { backchannel: string; notificationId: string }
<Button <Button
light light
label="Yes" label="Yes"
onClick={() => sendToBackchannel(props.backchannel, props.notificationId, { doUpdate: true, now: true })} onClick={() => sendToBackchannel(props.backchannel, props.notificationId, { doUpdate: true, now: true })}
/> />
); );
} }
@ -41,13 +41,13 @@ function RenderYesButtons(props: { backchannel: string; notificationId: string }
<Button <Button
light light
label="Yes, now" label="Yes, now"
onClick={() => sendToBackchannel(props.backchannel, props.notificationId, { doUpdate: true, now: true })} onClick={() => sendToBackchannel(props.backchannel, props.notificationId, { doUpdate: true, now: true })}
/> />
<Button <Button
active active
outlined outlined
label="Yes, later" label="Yes, later"
onClick={() => sendToBackchannel(props.backchannel, props.notificationId, { doUpdate: true, now: false })} onClick={() => sendToBackchannel(props.backchannel, props.notificationId, { doUpdate: true, now: false })}
/> />
</> </>
); );
@ -72,7 +72,7 @@ function UpdateAvailableHandler(event: IpcRendererEvent, ...[backchannel, update
active active
outlined outlined
label="No" label="No"
onClick={() => sendToBackchannel(backchannel, notificationId, { doUpdate: false })} onClick={() => sendToBackchannel(backchannel, notificationId, { doUpdate: false })}
/> />
</div> </div>
</div> </div>