mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fix: loading namespaces optimizations
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
cc8897e6e7
commit
31f1ebca61
@ -1,11 +1,9 @@
|
|||||||
import { debounce } from "lodash";
|
|
||||||
import { action, comparer, IReactionDisposer, IReactionOptions, observable, reaction, toJS, when } from "mobx";
|
import { action, comparer, IReactionDisposer, IReactionOptions, observable, reaction, toJS, when } from "mobx";
|
||||||
import { autobind, createStorage } from "../../utils";
|
import { autobind, createStorage } from "../../utils";
|
||||||
import { KubeObjectStore, KubeObjectStoreLoadingParams } from "../../kube-object.store";
|
import { KubeObjectStore, KubeObjectStoreLoadingParams } from "../../kube-object.store";
|
||||||
import { Namespace, namespacesApi } from "../../api/endpoints/namespaces.api";
|
import { Namespace, namespacesApi } from "../../api/endpoints/namespaces.api";
|
||||||
import { createPageParam } from "../../navigation";
|
import { createPageParam } from "../../navigation";
|
||||||
import { apiManager } from "../../api/api-manager";
|
import { apiManager } from "../../api/api-manager";
|
||||||
import { isAllowedResource } from "../../../common/rbac";
|
|
||||||
import { clusterStore, getHostedCluster } from "../../../common/cluster-store";
|
import { clusterStore, getHostedCluster } from "../../../common/cluster-store";
|
||||||
|
|
||||||
const storage = createStorage<string[]>("context_namespaces");
|
const storage = createStorage<string[]>("context_namespaces");
|
||||||
@ -50,16 +48,17 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
|||||||
await clusterStore.whenLoaded;
|
await clusterStore.whenLoaded;
|
||||||
if (!getHostedCluster()) return;
|
if (!getHostedCluster()) return;
|
||||||
await getHostedCluster().whenReady; // wait for cluster-state from main
|
await getHostedCluster().whenReady; // wait for cluster-state from main
|
||||||
this.isReady = true;
|
|
||||||
|
|
||||||
this.setContext(this.initialNamespaces);
|
this.setContext(this.initialNamespaces);
|
||||||
this.autoLoadAllowedNamespaces();
|
this.autoLoadAllowedNamespaces();
|
||||||
this.autoUpdateUrlAndLocalStorage();
|
this.autoUpdateUrlAndLocalStorage();
|
||||||
|
|
||||||
|
this.isReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onContextChange(callback: (contextNamespaces: string[]) => void, opts: IReactionOptions = {}): IReactionDisposer {
|
public onContextChange(callback: (contextNamespaces: string[]) => void, opts: IReactionOptions = {}): IReactionDisposer {
|
||||||
return reaction(() => this.contextNs.toJS(), callback, {
|
return reaction(() => this.contextNs.toJS(), callback, {
|
||||||
equals: comparer.identity,
|
equals: comparer.shallow,
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -70,14 +69,13 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
|||||||
namespaceUrlParam.set(namespaces, { replaceHistory: true }); // update url
|
namespaceUrlParam.set(namespaces, { replaceHistory: true }); // update url
|
||||||
}, {
|
}, {
|
||||||
fireImmediately: true,
|
fireImmediately: true,
|
||||||
equals: comparer.identity,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private autoLoadAllowedNamespaces(): IReactionDisposer {
|
private autoLoadAllowedNamespaces(): IReactionDisposer {
|
||||||
return reaction(() => this.allowedNamespaces, () => this.loadAll(), {
|
return reaction(() => this.allowedNamespaces, () => this.loadAll(), {
|
||||||
fireImmediately: true,
|
fireImmediately: true,
|
||||||
equals: comparer.identity,
|
equals: comparer.shallow,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,8 +104,14 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
|||||||
getContextNamespaces(): string[] {
|
getContextNamespaces(): string[] {
|
||||||
const namespaces = this.contextNs.toJS();
|
const namespaces = this.contextNs.toJS();
|
||||||
|
|
||||||
|
// show all namespaces when nothing selected
|
||||||
if (!namespaces.length) {
|
if (!namespaces.length) {
|
||||||
return [...this.allowedNamespaces]; // show all namespaces when nothing selected
|
if (this.isLoaded) {
|
||||||
|
// return actual namespaces list since "allowedNamespaces" updating every 30s in cluster and thus might be stale
|
||||||
|
return this.items.map(namespace => namespace.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.allowedNamespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespaces;
|
return namespaces;
|
||||||
@ -124,23 +128,18 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
|||||||
return super.subscribe(apis);
|
return super.subscribe(apis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent multiple loading from different sources (e.g. items-list-layout, namespace-select)
|
protected async loadItems(params: KubeObjectStoreLoadingParams) {
|
||||||
private loadAllLazy = debounce(() => {
|
const { allowedNamespaces } = this;
|
||||||
super.loadAll({
|
|
||||||
namespaces: this.allowedNamespaces,
|
|
||||||
});
|
|
||||||
}, 250);
|
|
||||||
|
|
||||||
async loadAll() {
|
let namespaces = await super.loadItems(params);
|
||||||
this.loadAllLazy();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async loadItems({ namespaces }: KubeObjectStoreLoadingParams) {
|
namespaces = namespaces.filter(namespace => allowedNamespaces.includes(namespace.getName()));
|
||||||
if (!isAllowedResource("namespaces")) {
|
|
||||||
return namespaces.map(getDummyNamespace);
|
if (!namespaces.length && allowedNamespaces.length > 0) {
|
||||||
|
return allowedNamespaces.map(getDummyNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(namespaces.map(name => this.api.get({ name })));
|
return namespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import { PageFiltersList } from "./page-filters-list";
|
|||||||
import { PageFiltersSelect } from "./page-filters-select";
|
import { PageFiltersSelect } from "./page-filters-select";
|
||||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
|
import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
|
||||||
import { themeStore } from "../../theme.store";
|
import { themeStore } from "../../theme.store";
|
||||||
import { MenuActions} from "../menu/menu-actions";
|
import { MenuActions } from "../menu/menu-actions";
|
||||||
import { MenuItem } from "../menu";
|
import { MenuItem } from "../menu";
|
||||||
import { Checkbox } from "../checkbox";
|
import { Checkbox } from "../checkbox";
|
||||||
import { userStore } from "../../../common/user-store";
|
import { userStore } from "../../../common/user-store";
|
||||||
@ -137,17 +137,13 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@computed get stores() {
|
@computed get stores() {
|
||||||
const { store, dependentStores, isClusterScoped, tableId } = this.props;
|
const { store, dependentStores, tableId } = this.props;
|
||||||
|
|
||||||
if (this.canBeConfigured) this.hiddenColumnNames = new Set(userStore.preferences?.hiddenTableColumns?.[tableId]);
|
if (this.canBeConfigured) {
|
||||||
|
this.hiddenColumnNames = new Set(userStore.preferences?.hiddenTableColumns?.[tableId]);
|
||||||
const stores = new Set([store, ...dependentStores]);
|
|
||||||
|
|
||||||
if (!isClusterScoped) {
|
|
||||||
stores.add(namespaceStore);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stores;
|
return new Set([store, ...dependentStores]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadStores() {
|
async loadStores() {
|
||||||
@ -254,7 +250,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateColumnFilter(checkboxValue: boolean, columnName: string) {
|
updateColumnFilter(checkboxValue: boolean, columnName: string) {
|
||||||
if (checkboxValue){
|
if (checkboxValue) {
|
||||||
this.hiddenColumnNames.delete(columnName);
|
this.hiddenColumnNames.delete(columnName);
|
||||||
} else {
|
} else {
|
||||||
this.hiddenColumnNames.add(columnName);
|
this.hiddenColumnNames.add(columnName);
|
||||||
@ -266,7 +262,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
columnIsVisible(index: number): boolean {
|
columnIsVisible(index: number): boolean {
|
||||||
const {renderTableHeader} = this.props;
|
const { renderTableHeader } = this.props;
|
||||||
|
|
||||||
if (!this.canBeConfigured) return true;
|
if (!this.canBeConfigured) return true;
|
||||||
|
|
||||||
@ -522,23 +518,25 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderColumnMenu() {
|
renderColumnMenu() {
|
||||||
const { renderTableHeader} = this.props;
|
const { renderTableHeader } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuActions
|
<MenuActions
|
||||||
toolbar = {false}
|
toolbar={false}
|
||||||
autoCloseOnSelect = {false}
|
autoCloseOnSelect={false}
|
||||||
className={cssNames("KubeObjectMenu")}
|
className={cssNames("KubeObjectMenu")}
|
||||||
>
|
>
|
||||||
{renderTableHeader.map((cellProps, index) => (
|
{renderTableHeader.map((cellProps, index) => (
|
||||||
!cellProps.showWithColumn &&
|
!cellProps.showWithColumn && (
|
||||||
<MenuItem key={index} className="input">
|
<MenuItem key={index} className="input">
|
||||||
<Checkbox label = {cellProps.title ?? `<${cellProps.className}>`}
|
<Checkbox
|
||||||
className = "MenuCheckbox"
|
label={cellProps.title ?? `<${cellProps.className}>`}
|
||||||
value ={!this.hiddenColumnNames.has(cellProps.className)}
|
className="MenuCheckbox"
|
||||||
onChange = {(v) => this.updateColumnFilter(v, cellProps.className)}
|
value={!this.hiddenColumnNames.has(cellProps.className)}
|
||||||
|
onChange={(v) => this.updateColumnFilter(v, cellProps.className)}
|
||||||
/>
|
/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
)
|
||||||
))}
|
))}
|
||||||
</MenuActions>
|
</MenuActions>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user