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:
parent
068ab855c1
commit
d8acc4487d
@ -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>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user