/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import "./cluster-view.scss"; import React from "react"; import type { IComputedValue } from "mobx"; import { computed, makeObservable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { ClusterStatus } from "./cluster-status"; import type { ClusterFrameHandler } from "./cluster-frame-handler"; import type { Cluster } from "../../../common/cluster/cluster"; import { requestClusterActivation } from "../../ipc"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { NavigateToCatalog } from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; import clusterViewRouteParametersInjectable from "./cluster-view-route-parameters.injectable"; import clusterFrameHandlerInjectable from "./cluster-frame-handler.injectable"; import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry"; import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable"; import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable"; import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable"; interface Dependencies { clusterId: IComputedValue; clusterFrames: ClusterFrameHandler; navigateToCatalog: NavigateToCatalog; entityRegistry: CatalogEntityRegistry; getClusterById: GetClusterById; } @observer class NonInjectedClusterView extends React.Component { constructor(props: Dependencies) { super(props); makeObservable(this); } get clusterId() { return this.props.clusterId.get(); } @computed get cluster(): Cluster | undefined { return this.props.getClusterById(this.clusterId); } private readonly isViewLoaded = computed(() => this.props.clusterFrames.hasLoadedView(this.clusterId), { keepAlive: true, requiresReaction: true, }); @computed get isReady(): boolean { const { cluster } = this; return (cluster?.ready && cluster?.available && this.isViewLoaded.get()) ?? false; } componentDidMount() { this.bindEvents(); } componentWillUnmount() { this.props.clusterFrames.clearVisibleCluster(); this.props.entityRegistry.activeEntity = undefined; } bindEvents() { disposeOnUnmount(this, [ reaction(() => this.clusterId, async (clusterId) => { // TODO: replace with better handling if (clusterId && !this.props.entityRegistry.getById(clusterId)) { return this.props.navigateToCatalog(); // redirect to catalog when the clusterId does not correspond to an entity } this.props.clusterFrames.setVisibleCluster(clusterId); this.props.clusterFrames.initView(clusterId); requestClusterActivation(clusterId, false); // activate and fetch cluster's state from main this.props.entityRegistry.activeEntity = clusterId; }, { fireImmediately: true, }), reaction(() => [this.cluster?.ready, this.cluster?.disconnected], ([, disconnected]) => { if (this.isViewLoaded.get() && disconnected) { this.props.navigateToCatalog(); // redirect to catalog when active cluster get disconnected/not available } }), ]); } renderStatus(): React.ReactNode { const { cluster, isReady } = this; if (cluster && !isReady) { return ; } return null; } render() { return (
{this.renderStatus()}
); } } export const ClusterView = withInjectables(NonInjectedClusterView, { getProps: (di) => ({ ...di.inject(clusterViewRouteParametersInjectable), navigateToCatalog: di.inject(navigateToCatalogInjectable), clusterFrames: di.inject(clusterFrameHandlerInjectable), entityRegistry: di.inject(catalogEntityRegistryInjectable), getClusterById: di.inject(getClusterByIdInjectable), }), });