mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Move everything else related to selecting namespaces into context
- Use only the context for the namespace-select-filter-model Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
d7474fe443
commit
3fd68bfcc1
@ -7,10 +7,25 @@
|
||||
* This type is used for KubeObjectStores
|
||||
*/
|
||||
export interface ClusterContext {
|
||||
readonly allNamespaces: string[]; // available / allowed namespaces from cluster.ts
|
||||
readonly contextNamespaces: string[]; // selected by user (see: namespace-select.tsx)
|
||||
/**
|
||||
* A computed getter for all the namespaces that this cluster knows about
|
||||
*/
|
||||
readonly allNamespaces: string[];
|
||||
|
||||
/**
|
||||
* The computed getter of namespaces that are currently selected
|
||||
*/
|
||||
readonly contextNamespaces: string[];
|
||||
|
||||
readonly hasSelectedAll: boolean;
|
||||
|
||||
isLoadingAll(namespaces: string[]): boolean;
|
||||
isGlobalWatchEnabled(): boolean;
|
||||
}
|
||||
|
||||
export interface NamespaceScopedClusterContext extends ClusterContext {
|
||||
selectAllNamespaces(): void;
|
||||
toggleNamespace(namespace: string): void;
|
||||
selectNamespace(namespace: string): void;
|
||||
deselectNamespace(namespace: string): void;
|
||||
}
|
||||
|
||||
@ -3,18 +3,21 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterContext } from "./cluster-frame-context";
|
||||
import type { NamespaceScopedClusterContext } from "./cluster-frame-context";
|
||||
import namespaceStoreInjectable from "../components/+namespaces/store.injectable";
|
||||
import hostedClusterInjectable from "./hosted-cluster.injectable";
|
||||
import assert from "assert";
|
||||
import { computed } from "mobx";
|
||||
import selectedNamespaceStorageInjectable from "../components/+namespaces/namespace-storage.injectable";
|
||||
import { toggle } from "../utils";
|
||||
|
||||
const clusterFrameContextForNamespacedResourcesInjectable = getInjectable({
|
||||
id: "cluster-frame-context-for-namespaced-resources",
|
||||
|
||||
instantiate: (di): ClusterContext => {
|
||||
instantiate: (di): NamespaceScopedClusterContext => {
|
||||
const cluster = di.inject(hostedClusterInjectable);
|
||||
const namespaceStore = di.inject(namespaceStoreInjectable);
|
||||
const selectedNamespaceStorage = di.inject(selectedNamespaceStorageInjectable);
|
||||
|
||||
assert(cluster, "This can only be injected within a cluster frame");
|
||||
|
||||
@ -25,20 +28,37 @@ const clusterFrameContextForNamespacedResourcesInjectable = getInjectable({
|
||||
}
|
||||
|
||||
if (namespaceStore.items.length > 0) {
|
||||
// namespaces from kubernetes api
|
||||
// namespaces from kubernetes api
|
||||
return namespaceStore.items.map((namespace) => namespace.getName());
|
||||
}
|
||||
|
||||
// fallback to cluster resolved namespaces because we could not load list
|
||||
return cluster.allowedNamespaces.slice();
|
||||
});
|
||||
const contextNamespaces = computed(() => namespaceStore.contextNamespaces);
|
||||
const contextNamespaces = computed(() => {
|
||||
const storedState = selectedNamespaceStorage.get();
|
||||
|
||||
if (!storedState || storedState.length === 0) {
|
||||
return allNamespaces.get();
|
||||
}
|
||||
|
||||
const state = new Set(storedState);
|
||||
const currentlyKnownNamespaces = new Set(allNamespaces.get());
|
||||
|
||||
for (const namespace of storedState) {
|
||||
if (!currentlyKnownNamespaces.has(namespace)) {
|
||||
state.delete(namespace);
|
||||
}
|
||||
}
|
||||
|
||||
return [...state];
|
||||
});
|
||||
const hasSelectedAll = computed(() => {
|
||||
const namespaces = new Set(contextNamespaces.get());
|
||||
|
||||
return allNamespaces.get().length > 1
|
||||
&& cluster.accessibleNamespaces.length === 0
|
||||
&& allNamespaces.get().every(ns => namespaces.has(ns));
|
||||
&& cluster.accessibleNamespaces.length === 0
|
||||
&& allNamespaces.get().every(ns => namespaces.has(ns));
|
||||
});
|
||||
|
||||
return {
|
||||
@ -48,6 +68,24 @@ const clusterFrameContextForNamespacedResourcesInjectable = getInjectable({
|
||||
&& allNamespaces.get().every(ns => namespaces.includes(ns))
|
||||
),
|
||||
isGlobalWatchEnabled: () => cluster.isGlobalWatchEnabled,
|
||||
selectAllNamespaces: () => {
|
||||
selectedNamespaceStorage.set([]);
|
||||
},
|
||||
selectNamespace: (namespace) => {
|
||||
selectedNamespaceStorage.set([namespace]);
|
||||
},
|
||||
toggleNamespace: (namespace) => {
|
||||
const nextState = new Set(contextNamespaces.get());
|
||||
|
||||
toggle(nextState, namespace);
|
||||
selectedNamespaceStorage.set([...nextState]);
|
||||
},
|
||||
deselectNamespace: (namespace) => {
|
||||
const nextState = new Set(contextNamespaces.get());
|
||||
|
||||
nextState.delete(namespace);
|
||||
selectedNamespaceStorage.set([...nextState]);
|
||||
},
|
||||
get allNamespaces() {
|
||||
return allNamespaces.get();
|
||||
},
|
||||
|
||||
@ -3,16 +3,16 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import namespaceStoreInjectable from "../store.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
|
||||
export type FilterByNamespace = (namespace: string) => void;
|
||||
|
||||
const filterByNamespaceInjectable = getInjectable({
|
||||
id: "filter-by-namespace",
|
||||
instantiate: (di): FilterByNamespace => {
|
||||
const namespaceStore = di.inject(namespaceStoreInjectable);
|
||||
const context = di.inject(clusterFrameContextForNamespacedResourcesInjectable);
|
||||
|
||||
return (namespace) => namespaceStore.selectSingle(namespace);
|
||||
return (namespace) => context.selectNamespace(namespace);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
*/
|
||||
import { namespaceSelectFilterModelFor } from "./namespace-select-filter-model";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import namespaceStoreInjectable from "../store.injectable";
|
||||
import isMultiSelectionKeyInjectable from "./is-selection-key.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
|
||||
@ -12,7 +11,6 @@ const namespaceSelectFilterModelInjectable = getInjectable({
|
||||
id: "namespace-select-filter-model",
|
||||
|
||||
instantiate: (di) => namespaceSelectFilterModelFor({
|
||||
namespaceStore: di.inject(namespaceStoreInjectable),
|
||||
isMultiSelectionKey: di.inject(isMultiSelectionKeyInjectable),
|
||||
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
|
||||
}),
|
||||
|
||||
@ -5,16 +5,15 @@
|
||||
import React from "react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { observable, action, computed, comparer } from "mobx";
|
||||
import type { NamespaceStore } from "../store";
|
||||
import type { ActionMeta, MultiValue } from "react-select";
|
||||
import { Icon } from "../../icon";
|
||||
import type { SelectOption } from "../../select";
|
||||
import { observableCrate } from "../../../utils";
|
||||
import type { IsMultiSelectionKey } from "./is-selection-key.injectable";
|
||||
import type { NamespaceScopedClusterContext } from "../../../cluster-frame-context/cluster-frame-context";
|
||||
|
||||
interface Dependencies {
|
||||
context: NamespaceScopedClusterContext;
|
||||
namespaceStore: NamespaceStore;
|
||||
isMultiSelectionKey: IsMultiSelectionKey;
|
||||
}
|
||||
|
||||
@ -45,7 +44,7 @@ enum SelectMenuState {
|
||||
}
|
||||
|
||||
export function namespaceSelectFilterModelFor(dependencies: Dependencies): NamespaceSelectFilterModel {
|
||||
const { isMultiSelectionKey, namespaceStore, context } = dependencies;
|
||||
const { isMultiSelectionKey, context } = dependencies;
|
||||
|
||||
let didToggle = false;
|
||||
let isMultiSelection = false;
|
||||
@ -111,7 +110,7 @@ export function namespaceSelectFilterModelFor(dependencies: Dependencies): Names
|
||||
onChange: (_, action) => {
|
||||
switch (action.action) {
|
||||
case "clear":
|
||||
namespaceStore.selectAll();
|
||||
context.selectAllNamespaces();
|
||||
break;
|
||||
case "deselect-option":
|
||||
case "select-option":
|
||||
@ -119,11 +118,11 @@ export function namespaceSelectFilterModelFor(dependencies: Dependencies): Names
|
||||
didToggle = true;
|
||||
|
||||
if (action.option.value === selectAllNamespaces) {
|
||||
namespaceStore.selectAll();
|
||||
context.selectAllNamespaces();
|
||||
} else if (isMultiSelection) {
|
||||
namespaceStore.toggleSingle(action.option.value);
|
||||
context.toggleNamespace(action.option.value);
|
||||
} else {
|
||||
namespaceStore.selectSingle(action.option.value);
|
||||
context.selectNamespace(action.option.value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -15,6 +15,8 @@ import type { Fetch } from "../../../common/fetch/fetch.injectable";
|
||||
import fetchInjectable from "../../../common/fetch/fetch.injectable";
|
||||
import { Namespace } from "../../../common/k8s-api/endpoints";
|
||||
import { createMockResponseFromString } from "../../../test-utils/mock-responses";
|
||||
import type { NamespaceScopedClusterContext } from "../../cluster-frame-context/cluster-frame-context";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
|
||||
import createClusterInjectable from "../../cluster/create-cluster.injectable";
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
@ -43,6 +45,7 @@ function createNamespace(name: string): Namespace {
|
||||
describe("<NamespaceSelectFilter />", () => {
|
||||
let di: DiContainer;
|
||||
let namespaceStore: NamespaceStore;
|
||||
let context: NamespaceScopedClusterContext;
|
||||
let fetchMock: AsyncFnMock<Fetch>;
|
||||
let result: RenderResult;
|
||||
let cleanup: Disposer;
|
||||
@ -69,6 +72,7 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
}));
|
||||
|
||||
namespaceStore = di.inject(namespaceStoreInjectable);
|
||||
context = di.inject(clusterFrameContextForNamespacedResourcesInjectable);
|
||||
|
||||
const subscribeStores = di.inject(subscribeStoresInjectable);
|
||||
|
||||
@ -138,7 +142,7 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
});
|
||||
|
||||
it("has only 'test-2' is selected in the store", () => {
|
||||
expect(namespaceStore.contextNamespaces).toEqual(["test-2"]);
|
||||
expect(context.contextNamespaces).toEqual(["test-2"]);
|
||||
});
|
||||
|
||||
it("closes menu", () => {
|
||||
@ -172,7 +176,7 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
});
|
||||
|
||||
it("has only 'test-1' is selected in the store", () => {
|
||||
expect(namespaceStore.contextNamespaces).toEqual(["test-1"]);
|
||||
expect(context.contextNamespaces).toEqual(["test-1"]);
|
||||
});
|
||||
|
||||
it("closes menu", () => {
|
||||
@ -197,7 +201,7 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
});
|
||||
|
||||
it("has both 'test-1' and 'test-3' as selected in the store", () => {
|
||||
expect(new Set(namespaceStore.contextNamespaces)).toEqual(new Set(["test-1", "test-3"]));
|
||||
expect(new Set(context.contextNamespaces)).toEqual(new Set(["test-1", "test-3"]));
|
||||
});
|
||||
|
||||
it("keeps menu open", () => {
|
||||
@ -214,7 +218,7 @@ describe("<NamespaceSelectFilter />", () => {
|
||||
});
|
||||
|
||||
it("has all of 'test-1', 'test-3', and 'test-13' selected in the store", () => {
|
||||
expect(new Set(namespaceStore.contextNamespaces)).toEqual(new Set(["test-1", "test-3", "test-13"]));
|
||||
expect(new Set(context.contextNamespaces)).toEqual(new Set(["test-1", "test-3", "test-13"]));
|
||||
});
|
||||
|
||||
it("'test-13' is not sorted to the top of the list", () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user