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

allow to quick select/deselect all namespaces in NamespaceSelect

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-02-03 01:12:08 +02:00
parent 068ab855c1
commit d8acc4487d
3 changed files with 72 additions and 34 deletions

View File

@ -13,17 +13,12 @@ import { kubeWatchApi } from "../../api/kube-watch-api";
interface Props extends SelectProps { interface Props extends SelectProps {
showIcons?: boolean; showIcons?: boolean;
showClusterOption?: boolean; // show cluster option on the top (default: false) customizeOptions?(options: SelectOption[]): SelectOption[];
clusterOptionLabel?: React.ReactNode; // label for cluster option (default: "Cluster")
customizeOptions?(nsOptions: SelectOption[]): SelectOption[];
} }
const defaultProps: Partial<Props> = { const defaultProps: Partial<Props> = {
showIcons: true, showIcons: true,
showClusterOption: false, showClusterOption: false,
get clusterOptionLabel() {
return `Cluster`;
},
}; };
@observer @observer
@ -39,13 +34,11 @@ export class NamespaceSelect extends React.Component<Props> {
} }
@computed get options(): SelectOption[] { @computed get options(): SelectOption[] {
const { customizeOptions, showClusterOption, clusterOptionLabel } = this.props; const { customizeOptions } = this.props;
let options: SelectOption[] = namespaceStore.items.map(ns => ({ value: ns.getName() })); let options: SelectOption[] = namespaceStore.items.map(ns => ({ value: ns.getName() }));
options = customizeOptions ? customizeOptions(options) : options; if (customizeOptions) {
options = customizeOptions(options);
if (showClusterOption) {
options.unshift({ value: null, label: clusterOptionLabel });
} }
return options; return options;
@ -80,32 +73,61 @@ export class NamespaceSelect extends React.Component<Props> {
@observer @observer
export class NamespaceSelectFilter extends React.Component { export class NamespaceSelectFilter extends React.Component {
@computed get placeholder(): React.ReactNode {
const namespaces = namespaceStore.getContextNamespaces();
switch (namespaces.length) {
case 1:
return <>Namespace: {namespaces[0]}</>;
case 2:
return <>Namespaces: {namespaces.join(", ")}</>;
default:
return "All Namespaces";
}
}
formatOptionLabel = ({ value: namespace, label }: SelectOption) => {
if (namespace) {
const isSelected = namespaceStore.hasContext(namespace);
return (
<div className="flex gaps align-center">
<FilterIcon type={FilterType.NAMESPACE}/>
<span>{namespace}</span>
{isSelected && <Icon small material="check" className="box right"/>}
</div>
);
}
return label;
};
customizeOptions = (options: SelectOption[]): SelectOption[] => {
return [
{ value: "", label: "All Namespaces" },
...options
];
};
onChange = ([{ value: namespace }]: SelectOption[]) => {
if (namespace) {
namespaceStore.toggleContext(namespace);
} else {
namespaceStore.toggleAll(); // "All namespaces" option clicked
}
};
render() { render() {
const { contextNs, hasContext, toggleContext } = namespaceStore;
let placeholder = <>All namespaces</>;
if (contextNs.length == 1) placeholder = <>Namespace: {contextNs[0]}</>;
if (contextNs.length >= 2) placeholder = <>Namespaces: {contextNs.join(", ")}</>;
return ( return (
<NamespaceSelect <NamespaceSelect
placeholder={placeholder} isMulti={true}
placeholder={this.placeholder}
closeMenuOnSelect={false} closeMenuOnSelect={false}
isOptionSelected={() => false} isOptionSelected={() => false}
controlShouldRenderValue={false} controlShouldRenderValue={false}
isMulti onChange={this.onChange}
onChange={([{ value }]: SelectOption[]) => toggleContext(value)} formatOptionLabel={this.formatOptionLabel}
formatOptionLabel={({ value: namespace }: SelectOption) => { customizeOptions={this.customizeOptions}
const isSelected = hasContext(namespace);
return (
<div className="flex gaps align-center">
<FilterIcon type={FilterType.NAMESPACE}/>
<span>{namespace}</span>
{isSelected && <Icon small material="check" className="box right"/>}
</div>
);
}}
/> />
); );
} }

View File

@ -1,4 +1,4 @@
import { action, comparer, IReactionDisposer, IReactionOptions, observable, reaction, toJS, when } from "mobx"; import { action, comparer, computed, 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";
@ -79,10 +79,11 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
}); });
} }
get allowedNamespaces(): string[] { @computed get allowedNamespaces(): string[] {
return toJS(getHostedCluster().allowedNamespaces); return toJS(getHostedCluster().allowedNamespaces);
} }
@computed
private get initialNamespaces(): string[] { private get initialNamespaces(): string[] {
const allowed = new Set(this.allowedNamespaces); const allowed = new Set(this.allowedNamespaces);
const prevSelected = storage.get(); const prevSelected = storage.get();
@ -159,6 +160,21 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
else this.contextNs.push(namespace); else this.contextNs.push(namespace);
} }
@action
toggleAll(showAll?: boolean) {
if (typeof showAll === "boolean") {
if (showAll) {
this.contextNs.replace(this.initialNamespaces);
} else {
this.contextNs.clear();
}
} else {
const showAll = this.contextNs.length < this.initialNamespaces.length;
this.toggleAll(showAll);
}
}
@action @action
async remove(item: Namespace) { async remove(item: Namespace) {
await super.remove(item); await super.remove(item);

View File

@ -30,7 +30,7 @@ export class PageFiltersStore {
protected syncWithContextNamespace() { protected syncWithContextNamespace() {
const disposers = [ const disposers = [
reaction(() => this.getValues(FilterType.NAMESPACE), filteredNs => { reaction(() => this.getValues(FilterType.NAMESPACE), filteredNs => {
if (filteredNs.length !== namespaceStore.contextNs.length) { if (filteredNs.length !== namespaceStore.getContextNamespaces().length) {
namespaceStore.setContext(filteredNs); namespaceStore.setContext(filteredNs);
} }
}), }),