mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix detail views not watching child components (#4345)
* Fix detail views not watching child components - Add subscribeStores calls to all relavent details - Add support for tracking overlapping subscribes as an optimization Signed-off-by: Sebastian Malton <sebastian@malton.name> * Resolve PR comments Signed-off-by: Sebastian Malton <sebastian@malton.name> * Detect the adding of a namespace when selected namespaces change Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update debug log Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
8ff7c03993
commit
0286faf387
25 files changed
+338
-252
No files matched your search
@@ -42,11 +42,11 @@ import whatInput from "what-input";
|
||||
import { clusterSetFrameIdHandler } from "../common/cluster-ipc";
|
||||
import { ClusterPageMenuRegistration, ClusterPageMenuRegistry } from "../extensions/registries";
|
||||
import { StatefulSetScaleDialog } from "./components/+workloads-statefulsets/statefulset-scale-dialog";
|
||||
import { kubeWatchApi } from "../common/k8s-api/kube-watch-api";
|
||||
import { KubeWatchApi, kubeWatchApi } from "../common/k8s-api/kube-watch-api";
|
||||
import { ReplicaSetScaleDialog } from "./components/+workloads-replicasets/replicaset-scale-dialog";
|
||||
import { CommandContainer } from "./components/command-palette/command-container";
|
||||
import { KubeObjectStore } from "../common/k8s-api/kube-object.store";
|
||||
import { clusterContext } from "./components/context";
|
||||
import { FrameContext } from "./components/context";
|
||||
import * as routes from "../common/routes";
|
||||
import { TabLayout, TabLayoutRoute } from "./components/layout/tab-layout";
|
||||
import { ErrorBoundary } from "./components/error-boundary";
|
||||
@@ -73,6 +73,8 @@ import { watchHistoryState } from "./remote-helpers/history-updater";
|
||||
import { unmountComponentAtNode } from "react-dom";
|
||||
import { PortForwardDialog } from "./port-forward";
|
||||
import { DeleteClusterDialog } from "./components/delete-cluster-dialog";
|
||||
import { WorkloadsOverview } from "./components/+workloads-overview/overview";
|
||||
import { KubeObjectListLayout } from "./components/kube-object-list-layout";
|
||||
|
||||
@observer
|
||||
export class ClusterFrame extends React.Component {
|
||||
@@ -91,10 +93,12 @@ export class ClusterFrame extends React.Component {
|
||||
|
||||
ClusterFrame.clusterId = getHostedClusterId();
|
||||
|
||||
const cluster = ClusterStore.getInstance().getById(ClusterFrame.clusterId);
|
||||
|
||||
logger.info(`${ClusterFrame.logPrefix} Init dashboard, clusterId=${ClusterFrame.clusterId}, frameId=${frameId}`);
|
||||
await Terminal.preloadFonts();
|
||||
await requestMain(clusterSetFrameIdHandler, ClusterFrame.clusterId);
|
||||
await ClusterStore.getInstance().getById(ClusterFrame.clusterId).whenReady; // cluster.activate() is done at this point
|
||||
await cluster.whenReady; // cluster.activate() is done at this point
|
||||
|
||||
catalogEntityRegistry.activeEntity = ClusterFrame.clusterId;
|
||||
|
||||
@@ -120,16 +124,21 @@ export class ClusterFrame extends React.Component {
|
||||
|
||||
whatInput.ask(); // Start to monitor user input device
|
||||
|
||||
const clusterContext = new FrameContext(cluster);
|
||||
|
||||
// Setup hosted cluster context
|
||||
KubeObjectStore.defaultContext.set(clusterContext);
|
||||
kubeWatchApi.context = clusterContext;
|
||||
WorkloadsOverview.clusterContext
|
||||
= KubeObjectListLayout.clusterContext
|
||||
= KubeWatchApi.context
|
||||
= clusterContext;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([namespaceStore], {
|
||||
preload: true,
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
namespaceStore,
|
||||
]),
|
||||
|
||||
watchHistoryState(),
|
||||
]);
|
||||
|
||||
@@ -55,9 +55,11 @@ export class ClusterOverview extends React.Component {
|
||||
this.metricPoller.start(true);
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([podsStore, eventStore, nodesStore], {
|
||||
preload: true,
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
eventStore,
|
||||
nodesStore,
|
||||
]),
|
||||
reaction(
|
||||
() => clusterOverviewStore.metricNodeRole, // Toggle Master/Worker node switcher
|
||||
() => this.metricPoller.restart(true),
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
import "./kube-event-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { cssNames } from "../../utils";
|
||||
import { LocaleDate } from "../locale-date";
|
||||
import { eventStore } from "./event.store";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
export interface KubeEventDetailsProps {
|
||||
object: KubeObject;
|
||||
@@ -36,8 +37,12 @@ export interface KubeEventDetailsProps {
|
||||
|
||||
@observer
|
||||
export class KubeEventDetails extends React.Component<KubeEventDetailsProps> {
|
||||
async componentDidMount() {
|
||||
eventStore.reloadAll();
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([
|
||||
eventStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -39,6 +39,7 @@ import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<Namespace> {
|
||||
}
|
||||
@@ -52,14 +53,16 @@ export class NamespaceDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
|
||||
componentDidMount() {
|
||||
resourceQuotaStore.reloadAll();
|
||||
limitRangeStore.reloadAll();
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
resourceQuotaStore,
|
||||
limitRangeStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@computed get quotas() {
|
||||
|
||||
@@ -23,12 +23,11 @@ import "./namespace-select.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Select, SelectOption, SelectProps } from "../select";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Icon } from "../icon";
|
||||
import { namespaceStore } from "./namespace.store";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends SelectProps {
|
||||
showIcons?: boolean;
|
||||
@@ -50,14 +49,7 @@ export class NamespaceSelect extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([namespaceStore], {
|
||||
preload: true,
|
||||
loadOnce: true, // skip reloading namespaces on every render / page visit
|
||||
}),
|
||||
]);
|
||||
}
|
||||
// No subscribe here because the subscribe is in <App /> (the cluster frame root component)
|
||||
|
||||
@computed.struct get options(): SelectOption[] {
|
||||
const { customizeOptions, showAllNamespacesOption, sort } = this.props;
|
||||
|
||||
@@ -133,7 +133,7 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
return super.subscribe();
|
||||
}
|
||||
|
||||
protected async loadItems(params: KubeObjectStoreLoadingParams<Namespace>): Promise<Namespace[]> {
|
||||
protected async loadItems(params: KubeObjectStoreLoadingParams): Promise<Namespace[]> {
|
||||
const { allowedNamespaces } = this;
|
||||
|
||||
let namespaces = await super.loadItems(params).catch(() => []);
|
||||
|
||||
@@ -49,10 +49,13 @@ export class IngressDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
async loadMetrics() {
|
||||
|
||||
@@ -44,8 +44,9 @@ export class ServiceDetails extends React.Component<Props> {
|
||||
const { object: service } = this.props;
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([endpointStore], {
|
||||
preload: true,
|
||||
kubeWatchApi.subscribeStores([
|
||||
endpointStore,
|
||||
], {
|
||||
namespaces: [service.getNs()],
|
||||
}),
|
||||
portForwardStore.watch(),
|
||||
|
||||
@@ -41,6 +41,7 @@ import { NodeDetailsResources } from "./node-details-resources";
|
||||
import { DrawerTitle } from "../drawer/drawer-title";
|
||||
import { boundMethod } from "../../utils";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<Node> {
|
||||
}
|
||||
@@ -54,13 +55,15 @@ export class NodeDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object.getName(), () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
|
||||
async componentDidMount() {
|
||||
podsStore.reloadAll();
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object.getName(), () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -25,7 +25,7 @@ import React from "react";
|
||||
import startCase from "lodash/startCase";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { observer } from "mobx-react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { StorageClass } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
@@ -33,14 +33,19 @@ import { storageClassStore } from "./storage-class.store";
|
||||
import { VolumeDetailsList } from "../+storage-volumes/volume-details-list";
|
||||
import { volumesStore } from "../+storage-volumes/volumes.store";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<StorageClass> {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class StorageClassDetails extends React.Component<Props> {
|
||||
async componentDidMount() {
|
||||
volumesStore.reloadAll();
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([
|
||||
volumesStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -51,10 +51,13 @@ export class PersistentVolumeClaimDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
async loadMetrics() {
|
||||
|
||||
@@ -23,7 +23,7 @@ import "./cronjob-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import kebabCase from "lodash/kebabCase";
|
||||
import { observer } from "mobx-react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Badge } from "../badge/badge";
|
||||
import { jobStore } from "../+workloads-jobs/job.store";
|
||||
@@ -34,14 +34,19 @@ import { getDetailsUrl } from "../kube-detail-params";
|
||||
import { CronJob, Job } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<CronJob> {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class CronJobDetails extends React.Component<Props> {
|
||||
async componentDidMount() {
|
||||
jobStore.reloadAll();
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([
|
||||
jobStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -41,6 +41,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { boundMethod } from "../../utils";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<DaemonSet> {
|
||||
}
|
||||
@@ -54,13 +55,15 @@ export class DaemonSetDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
|
||||
componentDidMount() {
|
||||
podsStore.reloadAll();
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -43,6 +43,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { boundMethod } from "../../utils";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<Deployment> {
|
||||
}
|
||||
@@ -56,14 +57,16 @@ export class DeploymentDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
|
||||
componentDidMount() {
|
||||
podsStore.reloadAll();
|
||||
replicaSetStore.reloadAll();
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
replicaSetStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -23,7 +23,7 @@ import "./job-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import kebabCase from "lodash/kebabCase";
|
||||
import { observer } from "mobx-react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
|
||||
@@ -36,7 +36,7 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { getMetricsForJobs, IPodMetrics, Job } from "../../../common/k8s-api/endpoints";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { podMetricTabs, PodCharts } from "../+workloads-pods/pod-charts";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||
@@ -45,6 +45,7 @@ import { boundMethod } from "autobind-decorator";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import { apiManager } from "../../../common/k8s-api/api-manager";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<Job> {
|
||||
}
|
||||
@@ -58,8 +59,15 @@ export class JobDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
podsStore.reloadAll();
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -36,16 +36,18 @@ import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
import { WorkloadsOverviewDetailRegistry } from "../../../extensions/registries";
|
||||
import type { WorkloadsOverviewRouteParams } from "../../../common/routes";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { clusterContext } from "../context";
|
||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
|
||||
import { Icon } from "../icon";
|
||||
import { TooltipPosition } from "../tooltip";
|
||||
import type { ClusterContext } from "../../../common/k8s-api/cluster-context";
|
||||
|
||||
interface Props extends RouteComponentProps<WorkloadsOverviewRouteParams> {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class WorkloadsOverview extends React.Component<Props> {
|
||||
static clusterContext: ClusterContext;
|
||||
|
||||
@observable loadErrors: string[] = [];
|
||||
|
||||
constructor(props: Props) {
|
||||
@@ -56,12 +58,18 @@ export class WorkloadsOverview extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore, deploymentStore, daemonSetStore, statefulSetStore, replicaSetStore,
|
||||
jobStore, cronJobStore, eventStore,
|
||||
cronJobStore,
|
||||
daemonSetStore,
|
||||
deploymentStore,
|
||||
eventStore,
|
||||
jobStore,
|
||||
podsStore,
|
||||
replicaSetStore,
|
||||
statefulSetStore,
|
||||
], {
|
||||
onLoadFailure: error => this.loadErrors.push(String(error)),
|
||||
}),
|
||||
reaction(() => clusterContext.contextNamespaces.slice(), () => {
|
||||
reaction(() => WorkloadsOverview.clusterContext.contextNamespaces.slice(), () => {
|
||||
// clear load errors
|
||||
this.loadErrors.length = 0;
|
||||
}),
|
||||
|
||||
@@ -40,6 +40,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { boundMethod } from "../../utils";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<ReplicaSet> {
|
||||
}
|
||||
@@ -53,13 +54,15 @@ export class ReplicaSetDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
|
||||
async componentDidMount() {
|
||||
podsStore.reloadAll();
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -41,6 +41,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { boundMethod } from "../../utils";
|
||||
import logger from "../../../common/logger";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
|
||||
interface Props extends KubeObjectDetailsProps<StatefulSet> {
|
||||
}
|
||||
@@ -54,13 +55,15 @@ export class StatefulSetDetails extends React.Component<Props> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@disposeOnUnmount
|
||||
clean = reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
});
|
||||
|
||||
componentDidMount() {
|
||||
podsStore.reloadAll();
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
kubeWatchApi.subscribeStores([
|
||||
podsStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
@@ -19,24 +19,19 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { ClusterStore } from "../../common/cluster-store";
|
||||
import type { Cluster } from "../../main/cluster";
|
||||
import { getHostedClusterId } from "../utils";
|
||||
import { namespaceStore } from "./+namespaces/namespace.store";
|
||||
import type { ClusterContext } from "../../common/k8s-api/cluster-context";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
|
||||
export const clusterContext: ClusterContext = {
|
||||
get cluster(): Cluster | null {
|
||||
return ClusterStore.getInstance().getById(getHostedClusterId());
|
||||
},
|
||||
|
||||
get allNamespaces(): string[] {
|
||||
if (!this.cluster) {
|
||||
return [];
|
||||
}
|
||||
export class FrameContext implements ClusterContext {
|
||||
constructor(public cluster: Cluster) {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@computed get allNamespaces(): string[] {
|
||||
// user given list of namespaces
|
||||
if (this.cluster?.accessibleNamespaces.length) {
|
||||
if (this.cluster.accessibleNamespaces.length) {
|
||||
return this.cluster.accessibleNamespaces;
|
||||
}
|
||||
|
||||
@@ -47,9 +42,17 @@ export const clusterContext: ClusterContext = {
|
||||
// fallback to cluster resolved namespaces because we could not load list
|
||||
return this.cluster.allowedNamespaces || [];
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
get contextNamespaces(): string[] {
|
||||
return namespaceStore.contextNamespaces ?? [];
|
||||
},
|
||||
};
|
||||
@computed get contextNamespaces(): string[] {
|
||||
return namespaceStore.contextNamespaces;
|
||||
}
|
||||
|
||||
@computed get hasSelectedAll(): boolean {
|
||||
const namespaces = new Set(this.contextNamespaces);
|
||||
|
||||
return this.allNamespaces?.length > 1
|
||||
&& this.cluster.accessibleNamespaces.length === 0
|
||||
&& this.allNamespaces.every(ns => namespaces.has(ns));
|
||||
}
|
||||
}
|
||||
@@ -30,12 +30,12 @@ import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-li
|
||||
import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
|
||||
import { KubeObjectMenu } from "../kube-object-menu";
|
||||
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
|
||||
import { clusterContext } from "../context";
|
||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
|
||||
import { ResourceKindMap, ResourceNames } from "../../utils/rbac";
|
||||
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
|
||||
import { Icon } from "../icon";
|
||||
import { TooltipPosition } from "../tooltip";
|
||||
import type { ClusterContext } from "../../../common/k8s-api/cluster-context";
|
||||
|
||||
export interface KubeObjectListLayoutProps<K extends KubeObject> extends ItemListLayoutProps<K> {
|
||||
store: KubeObjectStore<K>;
|
||||
@@ -51,6 +51,7 @@ const defaultProps: Partial<KubeObjectListLayoutProps<KubeObject>> = {
|
||||
@observer
|
||||
export class KubeObjectListLayout<K extends KubeObject> extends React.Component<KubeObjectListLayoutProps<K>> {
|
||||
static defaultProps = defaultProps as object;
|
||||
static clusterContext: ClusterContext;
|
||||
|
||||
constructor(props: KubeObjectListLayoutProps<K>) {
|
||||
super(props);
|
||||
@@ -67,7 +68,7 @@ export class KubeObjectListLayout<K extends KubeObject> extends React.Component<
|
||||
const { store, dependentStores = [], subscribeStores } = this.props;
|
||||
const stores = Array.from(new Set([store, ...dependentStores]));
|
||||
const reactions: Disposer[] = [
|
||||
reaction(() => clusterContext.contextNamespaces.slice(), () => {
|
||||
reaction(() => KubeObjectListLayout.clusterContext.contextNamespaces.slice(), () => {
|
||||
// clear load errors
|
||||
this.loadErrors.length = 0;
|
||||
}),
|
||||
@@ -76,8 +77,6 @@ export class KubeObjectListLayout<K extends KubeObject> extends React.Component<
|
||||
if (subscribeStores) {
|
||||
reactions.push(
|
||||
kubeWatchApi.subscribeStores(stores, {
|
||||
preload: true,
|
||||
namespaces: clusterContext.contextNamespaces,
|
||||
onLoadFailure: error => this.loadErrors.push(String(error)),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -54,7 +54,9 @@ export class Sidebar extends React.Component<Props> {
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([crdStore]),
|
||||
kubeWatchApi.subscribeStores([
|
||||
crdStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user