From c0ef006cb8e0b6c6a810c17738db0f33ba05dcb5 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Thu, 11 Feb 2021 10:32:57 +0300 Subject: [PATCH] Fix: preventing namespace filter jumping scroll (#2104) * fix lint Signed-off-by: Roman * fixes & refactoring Signed-off-by: Roman * fix lint, micro-refactoring Signed-off-by: Roman * more refactoring, clean up, responding to comments Signed-off-by: Roman * fix: remove extra check for cluster.allowedApi from processing buffered watch-api events Signed-off-by: Roman * refactoring, detaching NamespaceStore from KubeObjectStore Signed-off-by: Roman * fix: wait for contextReady in NamespaceStore Signed-off-by: Roman * refactoring & fixes Signed-off-by: Roman * fix lint Signed-off-by: Roman * fixes: reloading context stores on NamespaceSelect-change Signed-off-by: Roman * optimize loading all resources when "all namespaces" selected -> single request per resource (when have rights) Signed-off-by: Roman * use native k8s api watches Signed-off-by: Jari Kolehmainen * retry watch when it makes sense Signed-off-by: Jari Kolehmainen * workaround for browser connection limits Signed-off-by: Jari Kolehmainen * cleanup Signed-off-by: Jari Kolehmainen * cleanup Signed-off-by: Jari Kolehmainen * use always random subdomain for getResponse Signed-off-by: Jari Kolehmainen * resubscribe stores on contextNamespace change Signed-off-by: Jari Kolehmainen * fix Signed-off-by: Jari Kolehmainen * modify watch event before calling callback Signed-off-by: Jari Kolehmainen * Replace placeholder component in NamespaceSelectFilter Signed-off-by: Alex Andreev Co-authored-by: Roman Co-authored-by: Jari Kolehmainen --- .../+namespaces/namespace-select-filter.tsx | 77 +++++++++++++++++++ .../+namespaces/namespace-select.tsx | 60 +-------------- .../+workloads-overview/overview-statuses.tsx | 2 +- .../item-object-list/item-list-layout.tsx | 2 +- 4 files changed, 80 insertions(+), 61 deletions(-) create mode 100644 src/renderer/components/+namespaces/namespace-select-filter.tsx diff --git a/src/renderer/components/+namespaces/namespace-select-filter.tsx b/src/renderer/components/+namespaces/namespace-select-filter.tsx new file mode 100644 index 0000000000..453849e534 --- /dev/null +++ b/src/renderer/components/+namespaces/namespace-select-filter.tsx @@ -0,0 +1,77 @@ +import "./namespace-select.scss"; + +import React from "react"; +import { observer } from "mobx-react"; +import { components, PlaceholderProps } from "react-select"; + +import { Icon } from "../icon"; +import { FilterIcon } from "../item-object-list/filter-icon"; +import { FilterType } from "../item-object-list/page-filters.store"; +import { SelectOption } from "../select"; +import { NamespaceSelect } from "./namespace-select"; +import { namespaceStore } from "./namespace.store"; + +const Placeholder = observer((props: PlaceholderProps) => { + const getPlaceholder = (): React.ReactNode => { + const namespaces = namespaceStore.contextNamespaces; + + switch (namespaces.length) { + case 0: + case namespaceStore.allowedNamespaces.length: + return <>All namespaces; + case 1: + return <>Namespace: {namespaces[0]}; + default: + return <>Namespaces: {namespaces.join(", ")}; + } + }; + + return ( + + {getPlaceholder()} + + ); +}); + + +@observer +export class NamespaceSelectFilter extends React.Component { + formatOptionLabel({ value: namespace, label }: SelectOption) { + if (namespace) { + const isSelected = namespaceStore.hasContext(namespace); + + return ( +
+ + {namespace} + {isSelected && } +
+ ); + } + + return label; + } + + onChange([{ value: namespace }]: SelectOption[]) { + if (namespace) { + namespaceStore.toggleContext(namespace); + } else { + namespaceStore.resetContext(); // "All namespaces" clicked, empty list considered as "all" + } + } + + render() { + return ( + + ); + } +} diff --git a/src/renderer/components/+namespaces/namespace-select.tsx b/src/renderer/components/+namespaces/namespace-select.tsx index 27fbb8a311..207a274d2c 100644 --- a/src/renderer/components/+namespaces/namespace-select.tsx +++ b/src/renderer/components/+namespaces/namespace-select.tsx @@ -7,8 +7,6 @@ import { Select, SelectOption, SelectProps } from "../select"; import { cssNames } from "../../utils"; import { Icon } from "../icon"; import { namespaceStore } from "./namespace.store"; -import { FilterIcon } from "../item-object-list/filter-icon"; -import { FilterType } from "../item-object-list/page-filters.store"; import { kubeWatchApi } from "../../api/kube-watch-api"; interface Props extends SelectProps { @@ -35,7 +33,7 @@ export class NamespaceSelect extends React.Component { ]); } - @computed get options(): SelectOption[] { + @computed.struct get options(): SelectOption[] { const { customizeOptions, showClusterOption, showAllNamespacesOption } = this.props; let options: SelectOption[] = namespaceStore.items.map(ns => ({ value: ns.getName() })); @@ -78,59 +76,3 @@ export class NamespaceSelect extends React.Component { ); } } - -@observer -export class NamespaceSelectFilter extends React.Component { - @computed get placeholder(): React.ReactNode { - const namespaces = namespaceStore.contextNamespaces; - - switch (namespaces.length) { - case 0: - case namespaceStore.allowedNamespaces.length: - return <>All namespaces; - case 1: - return <>Namespace: {namespaces[0]}; - default: - return <>Namespaces: {namespaces.join(", ")}; - } - } - - formatOptionLabel = ({ value: namespace, label }: SelectOption) => { - if (namespace) { - const isSelected = namespaceStore.hasContext(namespace); - - return ( -
- - {namespace} - {isSelected && } -
- ); - } - - return label; - }; - - onChange = ([{ value: namespace }]: SelectOption[]) => { - if (namespace) { - namespaceStore.toggleContext(namespace); - } else { - namespaceStore.resetContext(); // "All namespaces" clicked, empty list considered as "all" - } - }; - - render() { - return ( - false} - controlShouldRenderValue={false} - placeholder={this.placeholder} - onChange={this.onChange} - formatOptionLabel={this.formatOptionLabel} - /> - ); - } -} diff --git a/src/renderer/components/+workloads-overview/overview-statuses.tsx b/src/renderer/components/+workloads-overview/overview-statuses.tsx index 1441115ed8..bc0484dadc 100644 --- a/src/renderer/components/+workloads-overview/overview-statuses.tsx +++ b/src/renderer/components/+workloads-overview/overview-statuses.tsx @@ -6,7 +6,7 @@ import { OverviewWorkloadStatus } from "./overview-workload-status"; import { Link } from "react-router-dom"; import { workloadURL, workloadStores } from "../+workloads"; import { namespaceStore } from "../+namespaces/namespace.store"; -import { NamespaceSelectFilter } from "../+namespaces/namespace-select"; +import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; import { isAllowedResource, KubeResource } from "../../../common/rbac"; import { ResourceNames } from "../../utils/rbac"; import { autobind } from "../../utils"; diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index 5eeb7b2f11..dc0604017f 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -15,7 +15,7 @@ import { SearchInputUrl } from "../input"; import { Filter, FilterType, pageFilters } from "./page-filters.store"; import { PageFiltersList } from "./page-filters-list"; import { PageFiltersSelect } from "./page-filters-select"; -import { NamespaceSelectFilter } from "../+namespaces/namespace-select"; +import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; import { themeStore } from "../../theme.store"; import { MenuActions } from "../menu/menu-actions"; import { MenuItem } from "../menu";