mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fixes & refactoring
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
4fcdf01ba2
commit
094245a240
@ -30,7 +30,7 @@ export class CrdResources extends React.Component<Props> {
|
|||||||
const { store } = this;
|
const { store } = this;
|
||||||
|
|
||||||
if (store && !store.isLoading && !store.isLoaded) {
|
if (store && !store.isLoading && !store.isLoaded) {
|
||||||
store.loadSelectedNamespaces();
|
store.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export interface KubeEventDetailsProps {
|
|||||||
@observer
|
@observer
|
||||||
export class KubeEventDetails extends React.Component<KubeEventDetailsProps> {
|
export class KubeEventDetails extends React.Component<KubeEventDetailsProps> {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
eventStore.loadSelectedNamespaces();
|
eventStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -32,8 +32,8 @@ export class NamespaceDetails extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
resourceQuotaStore.loadSelectedNamespaces();
|
resourceQuotaStore.loadContextNamespaces();
|
||||||
limitRangeStore.loadSelectedNamespaces();
|
limitRangeStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -103,8 +103,20 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContextNamespaces(): string[] {
|
getContextNamespaces(): string[] {
|
||||||
return Array.from(this.contextNs);
|
const namespaces = Array.from(this.contextNs);
|
||||||
|
|
||||||
|
// show all namespaces when nothing selected
|
||||||
|
if (!namespaces.length) {
|
||||||
|
// return actual namespaces list since "allowedNamespaces" updating every 30s in cluster and thus might be stale
|
||||||
|
if (this.isLoaded) {
|
||||||
|
return this.items.map(namespace => namespace.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.allowedNamespaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubscribeApis() {
|
getSubscribeApis() {
|
||||||
@ -139,6 +151,11 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
|||||||
this.contextNs.replace(namespaces);
|
this.contextNs.replace(namespaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
resetContext(){
|
||||||
|
this.contextNs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
hasContext(namespaces: string | string[]) {
|
hasContext(namespaces: string | string[]) {
|
||||||
return [namespaces].flat().every(namespace => this.contextNs.has(namespace));
|
return [namespaces].flat().every(namespace => this.contextNs.has(namespace));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class NodeDetails extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
podsStore.loadSelectedNamespaces();
|
podsStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export class AddRoleBindingDialog extends React.Component<Props> {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
await Promise.all(stores.map(store => store.loadSelectedNamespaces()));
|
await Promise.all(stores.map(store => store.loadContextNamespaces()));
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ interface Props extends KubeObjectDetailsProps<CronJob> {
|
|||||||
@observer
|
@observer
|
||||||
export class CronJobDetails extends React.Component<Props> {
|
export class CronJobDetails extends React.Component<Props> {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
jobStore.loadSelectedNamespaces();
|
jobStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export class DaemonSetDetails extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
podsStore.loadSelectedNamespaces();
|
podsStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export class DeploymentDetails extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
podsStore.loadSelectedNamespaces();
|
podsStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@ -25,7 +25,7 @@ interface Props extends KubeObjectDetailsProps<Job> {
|
|||||||
@observer
|
@observer
|
||||||
export class JobDetails extends React.Component<Props> {
|
export class JobDetails extends React.Component<Props> {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
podsStore.loadSelectedNamespaces();
|
podsStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class ReplicaSetDetails extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
podsStore.loadSelectedNamespaces();
|
podsStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export class StatefulSetDetails extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
podsStore.loadSelectedNamespaces();
|
podsStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ interface Props {
|
|||||||
@observer
|
@observer
|
||||||
export class Sidebar extends React.Component<Props> {
|
export class Sidebar extends React.Component<Props> {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
crdStore.loadSelectedNamespaces();
|
crdStore.loadContextNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCustomResources() {
|
renderCustomResources() {
|
||||||
|
|||||||
@ -22,13 +22,17 @@ export abstract class ItemStore<T extends ItemObject = ItemObject> {
|
|||||||
return this.items.filter(item => this.selectedItemsIds.get(item.getId()));
|
return this.items.filter(item => this.selectedItemsIds.get(item.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getItems(): T[] {
|
||||||
|
return this.items.toJS();
|
||||||
|
}
|
||||||
|
|
||||||
getByName(name: string, ...args: any[]): T;
|
getByName(name: string, ...args: any[]): T;
|
||||||
getByName(name: string): T {
|
getByName(name: string): T {
|
||||||
return this.items.find(item => item.getName() === name);
|
return this.items.find(item => item.getName() === name);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIndex(item: T): number {
|
getIndexById(id: string): number {
|
||||||
return this.items.findIndex(i => i === item);
|
return this.items.findIndex(item => item.getId() === id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import type { Cluster } from "../main/cluster";
|
import type { Cluster } from "../main/cluster";
|
||||||
import { action, observable, reaction } from "mobx";
|
import type { NamespaceStore } from "./components/+namespaces/namespace.store";
|
||||||
|
|
||||||
|
import { action, computed, observable, reaction } from "mobx";
|
||||||
import { autobind } from "./utils";
|
import { autobind } from "./utils";
|
||||||
import { KubeObject } from "./api/kube-object";
|
import { KubeObject } from "./api/kube-object";
|
||||||
import { IKubeWatchEvent, IKubeWatchMessage, kubeWatchApi } from "./api/kube-watch-api";
|
import { IKubeWatchEvent, IKubeWatchMessage, kubeWatchApi } from "./api/kube-watch-api";
|
||||||
@ -24,6 +26,36 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
this.bindWatchEventsUpdater();
|
this.bindWatchEventsUpdater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: detach / remove circular dependency
|
||||||
|
@observable.ref private namespaceStore: NamespaceStore;
|
||||||
|
|
||||||
|
private async resolveNamespaceStore(): Promise<NamespaceStore> {
|
||||||
|
const { namespaceStore } = await import("./components/+namespaces/namespace.store");
|
||||||
|
|
||||||
|
await namespaceStore.whenReady;
|
||||||
|
this.namespaceStore = namespaceStore;
|
||||||
|
|
||||||
|
return namespaceStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: detach / inject dependency as in kube-watch-api
|
||||||
|
@observable.ref private cluster: Cluster;
|
||||||
|
|
||||||
|
private async resolveCluster(): Promise<Cluster> {
|
||||||
|
const { getHostedCluster } = await import("../common/cluster-store");
|
||||||
|
|
||||||
|
this.cluster = getHostedCluster();
|
||||||
|
|
||||||
|
return this.cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: figure out how to transparently replace with this.items
|
||||||
|
@computed get contextItems(): T[] {
|
||||||
|
const contextNamespaces = this.namespaceStore?.getContextNamespaces() ?? []; // not loaded
|
||||||
|
|
||||||
|
return this.items.filter((item: T) => !item.getNs() || contextNamespaces.includes(item.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
get query(): IKubeApiQueryParams {
|
get query(): IKubeApiQueryParams {
|
||||||
const { limit } = this;
|
const { limit } = this;
|
||||||
|
|
||||||
@ -79,12 +111,6 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async resolveCluster(): Promise<Cluster> {
|
|
||||||
const { getHostedCluster } = await import("../common/cluster-store");
|
|
||||||
|
|
||||||
return getHostedCluster();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async loadItems({ namespaces, api }: KubeObjectStoreLoadingParams): Promise<T[]> {
|
protected async loadItems({ namespaces, api }: KubeObjectStoreLoadingParams): Promise<T[]> {
|
||||||
const cluster = await this.resolveCluster();
|
const cluster = await this.resolveCluster();
|
||||||
|
|
||||||
@ -106,23 +132,19 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async loadAll(namespaces: string[] = []): Promise<void> {
|
async loadAll(namespaces: string[] = [], { replace = true } = {}): Promise<void> {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// load all available namespaces by default
|
||||||
if (!namespaces.length) {
|
if (!namespaces.length) {
|
||||||
const { namespaceStore } = await import("./components/+namespaces/namespace.store");
|
const namespaceStore = await this.resolveNamespaceStore();
|
||||||
|
|
||||||
// load all available namespaces by default
|
namespaces = namespaceStore.getContextNamespaces();
|
||||||
namespaces.push(...namespaceStore.allowedNamespaces);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = await this.loadItems({ namespaces, api: this.api });
|
let items = await this.loadItems({ namespaces, api: this.api });
|
||||||
|
this.mergeItems(items, { replace });
|
||||||
items = this.filterItemsOnLoad(items);
|
|
||||||
items = this.sortItems(items);
|
|
||||||
|
|
||||||
this.items.replace(items);
|
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Loading store items failed", { error, store: this });
|
console.error("Loading store items failed", { error, store: this });
|
||||||
@ -132,10 +154,26 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSelectedNamespaces(): Promise<void> {
|
@action
|
||||||
const { namespaceStore } = await import("./components/+namespaces/namespace.store");
|
private mergeItems(partialItems: T[], { replace = false, sort = true, filter = true } = {}): T[] {
|
||||||
|
let items = this.items.toJS();
|
||||||
|
|
||||||
return this.loadAll(namespaceStore.getContextNamespaces());
|
partialItems.forEach(item => {
|
||||||
|
const index = items.findIndex(i => i.getId() === item.getId());
|
||||||
|
|
||||||
|
if (index < 0) items.push(item); // add
|
||||||
|
else items[index] = item; // update
|
||||||
|
});
|
||||||
|
|
||||||
|
if (filter) items = this.filterItemsOnLoad(items)
|
||||||
|
if (sort) items = this.sortItems(items);
|
||||||
|
if (replace) this.items.replace(items);
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadContextNamespaces(): Promise<void> {
|
||||||
|
return this.loadAll(this.namespaceStore?.getContextNamespaces());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resetOnError(error: any) {
|
protected resetOnError(error: any) {
|
||||||
@ -224,14 +262,11 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
protected updateFromEventsBuffer() {
|
protected updateFromEventsBuffer() {
|
||||||
const eventsBuffer = this.eventsBuffer.clear();
|
const items = this.items.toJS();
|
||||||
|
|
||||||
if (!eventsBuffer.length) {
|
for (const { type, object } of this.eventsBuffer.clear()) {
|
||||||
return;
|
const index = items.findIndex(item => item.getId() === object.metadata?.uid);
|
||||||
}
|
const item = items[index];
|
||||||
|
|
||||||
for (const { type, object } of eventsBuffer) {
|
|
||||||
const item = this.getById(object.metadata?.uid);
|
|
||||||
const api = apiManager.getApiByKind(object.kind, object.apiVersion);
|
const api = apiManager.getApiByKind(object.kind, object.apiVersion);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -240,22 +275,20 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
|||||||
const newItem = new api.objectConstructor(object);
|
const newItem = new api.objectConstructor(object);
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
this.items.push(newItem);
|
items.push(newItem);
|
||||||
} else {
|
} else {
|
||||||
const index = this.getIndex(item);
|
items[index] = newItem;
|
||||||
|
|
||||||
this.items.splice(index, 1, newItem);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "DELETED":
|
case "DELETED":
|
||||||
this.items.remove(item);
|
if (item) {
|
||||||
|
items.splice(index, 1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort and limit items to store's maximum
|
// update items
|
||||||
const newItems = this.sortItems(this.items.slice(-this.bufferSize));
|
this.items.replace(this.sortItems(items.slice(-this.bufferSize)));
|
||||||
|
|
||||||
this.items.replace(newItems);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user