diff --git a/ui/components/DashboardComponent.js b/ui/components/DashboardComponent.js index 8e542909daa..969bc7c2647 100644 --- a/ui/components/DashboardComponent.js +++ b/ui/components/DashboardComponent.js @@ -1,21 +1,23 @@ + import { - Button, Card, CardContent, CardHeader, Chip, + Button,Chip, MenuItem, NoSsr, Paper, Select, TableCell, TableSortLabel, Tooltip, Typography } from "@material-ui/core"; // import {Table, TableBody, TableContainer, TableHead, TableRow,} from "@material-ui/core" import blue from "@material-ui/core/colors/blue"; +import { makeStyles } from "@material-ui/core/styles"; import Grid from "@material-ui/core/Grid"; -import { withStyles, MuiThemeProvider } from "@material-ui/core/styles"; +import { MuiThemeProvider } from "@material-ui/core/styles"; import AddIcon from "@material-ui/icons/AddCircleOutline"; -import { withRouter } from "next/router"; +import { useRouter } from "next/router"; import PropTypes from "prop-types"; -import React from "react"; +import React,{ useEffect, useState, useRef } from "react"; import { connect } from "react-redux"; import { bindActionCreators } from "redux"; import dataFetch from "../lib/data-fetch"; import { updateGrafanaConfig, updateProgress, updatePrometheusConfig, updateTelemetryUrls } from "../lib/store"; import { getK8sClusterIdsFromCtxId, getK8sClusterNamesFromCtxId } from "../utils/multi-ctx"; -import { versionMapper } from "../utils/nameMapper"; +// import { versionMapper } from "../utils/nameMapper"; import { submitGrafanaConfigure } from "./telemetry/grafana/GrafanaComponent"; import fetchAvailableAddons from "./graphql/queries/AddonsStatusQuery"; import fetchControlPlanes from "./graphql/queries/ControlPlanesQuery"; @@ -33,10 +35,12 @@ import { configurationTableTheme, configurationTableThemeDark } from '../themes/ import DashboardMeshModelGraph from './Dashboard/DashboardMeshModelGraph' import ConnectionStatsChart from "./Dashboard/ConnectionCharts.js"; import { EVENT_TYPES } from "../lib/event-types"; -import { withNotify } from "../utils/hooks/useNotification"; +import { useNotification } from "../utils/hooks/useNotification"; -const styles = (theme) => ({ - rootClass : { backgroundColor : theme.palette.secondary.elevatedComponents2, }, +const useStyles = makeStyles((theme) => ({ + rootClass : { + backgroundColor : theme.palette.secondary.elevatedComponents2, + }, datatable : { boxShadow : "none", }, @@ -56,24 +60,42 @@ const styles = (theme) => ({ cursor : "pointer", textDecoration : "none" }, - metricsButton : { width : "240px", }, - alreadyConfigured : { textAlign : "center", }, - margin : { margin : theme.spacing(1), }, + metricsButton : { + width : "240px", + }, + alreadyConfigured : { + textAlign : "center", + }, + margin : { + margin : theme.spacing(1), + }, colorSwitchBase : { color : blue[300], "&$colorChecked" : { color : blue[500], - "& + $colorBar" : { backgroundColor : blue[500], }, + "& + $colorBar" : { + backgroundColor : blue[500], + }, }, }, colorBar : {}, colorChecked : {}, - fileLabel : { width : "100%", }, + fileLabel : { + width : "100%", + }, fileLabelText : {}, - inClusterLabel : { paddingRight : theme.spacing(2), }, - alignCenter : { textAlign : "center", }, - icon : { width : theme.spacing(2.5), }, - istioIcon : { width : theme.spacing(1.5), }, + inClusterLabel : { + paddingRight : theme.spacing(2), + }, + alignCenter : { + textAlign : "center", + }, + icon : { + width : theme.spacing(2.5), + }, + istioIcon : { + width : theme.spacing(1.5), + }, settingsIcon : { width : theme.spacing(2.5), paddingRight : theme.spacing(0.5), @@ -82,12 +104,16 @@ const styles = (theme) => ({ width : theme.spacing(2.5), paddingRight : theme.spacing(0.5), }, - cardHeader : { fontSize : theme.spacing(2), }, + cardHeader : { + fontSize : theme.spacing(2), + }, card : { height : "100%", marginTop : theme.spacing(2), }, - cardContent : { height : "100%", }, + cardContent : { + height : "100%", + }, redirectButton : { marginLeft : "-.5em", color : "#000", @@ -99,293 +125,280 @@ const styles = (theme) => ({ height : "100%", marginBottom : theme.spacing(2), }, -}); -class DashboardComponent extends React.Component { - constructor(props) { - super(props); - const { - meshAdapters, grafana, prometheus - } = props; - this._isMounted = false; - this.state = { - meshAdapters, - contextsFromFile : [], - availableAdapters : [], - mts : new Date(), - meshLocationURLError : false, - - grafanaUrl : grafana.grafanaURL, - prometheusUrl : prometheus.prometheusURL, - k8sfileError : false, - kts : new Date(), - - grafana, - prometheus, - - urlError : false, - grafanaConfigSuccess : props.grafana.grafanaURL !== "", - grafanaBoardSearch : "", - grafanaURL : props.grafana.grafanaURL, - grafanaAPIKey : props.grafana.grafanaAPIKey, - grafanaBoards : props.grafana.grafanaBoards, - selectedBoardsConfigs : props.grafana.selectedBoardsConfigs, - ts : props.grafana.ts, - - meshScan : [], - activeMeshScanNamespace : {}, - meshScanNamespaces : {}, - - isMetricsConfigured : grafana.grafanaURL !== '' && prometheus.prometheusURL !== '', - controlPlaneState : "", - dataPlaneState : "", - clusterResources : [], - namespaceList : [], - selectedNamespace : "default", - - // subscriptions disposable - dataPlaneSubscription : null, - controlPlaneSubscription : null, - clusterResourcesSubscription : null, - clusterResourcesQuery : null, - namespaceQuery : null, - telemetryQuery : null - }; - } - - static getDerivedStateFromProps(props, state) { - const { - meshAdapters, meshAdaptersts, grafana, prometheus - } = props; - const st = {}; - if (meshAdaptersts > state.mts) { - st.meshAdapters = meshAdapters; - st.mts = meshAdaptersts; +})); + +const DashboardComponent=(props) => { + + const router = useRouter(); + const classes = useStyles(); + const { notify } = useNotification(); + + const _isMounted = useRef(false); + // const [meshAdapters, setMeshAdapters] = useState(props.meshAdapters); + // const [contextsFromFile, setContextsFromFile] = useState([]); + // const [availableAdapters, setAvailableAdapters] = useState([]); + const [mts, setMts] = useState(new Date()); + // const [meshLocationURLError, setMeshLocationURLError] = useState(false); + // const [grafanaUrl, setGrafanaUrl] = useState(props.grafana.grafanaURL); + const [prometheusURL, setPrometheusURL] = useState(props.prometheus.prometheusURL); + // const [k8sfileError, setK8sfileError] = useState(false); + // const [kts, setKts] = useState(new Date()); + const [grafana, setGrafana] = useState(props.grafana); + const [prometheus, setPrometheus] = useState(props.prometheus); + // const [urlError, setUrlError] = useState(false); + // const [grafanaConfigSuccess, setGrafanaConfigSuccess] = useState(props.grafana.grafanaURL !== ""); + // const [grafanaBoardSearch, setGrafanaBoardSearch] = useState(""); + const [grafanaURL, setGrafanaURL] = useState(props.grafana.grafanaURL); + // const [grafanaAPIKey, setGrafanaAPIKey] = useState(props.grafana.grafanaAPIKey); + // const [grafanaBoards, setGrafanaBoards] = useState(props.grafana.grafanaBoards); + // const [selectedBoardsConfigs, setSelectedBoardsConfigs] = useState(props.grafana.selectedBoardsConfigs); + // const [ts, setTs] = useState(props.grafana.ts); + const [meshScan, setMeshScan] = useState([]); + // const [activeMeshScanNamespace, setActiveMeshScanNamespace] = useState({}); + // const [meshScanNamespaces, setMeshScanNamespaces] = useState({}); + // const [isMetricsConfigured, setIsMetricsConfigured] = useState(grafana.grafanaURL !== '' && prometheus.prometheusURL !== ''); + const [controlPlaneState, setControlPlaneState] = useState(""); + const [dataPlaneState, setDataPlaneState] = useState(""); + const [clusterResources, setClusterResources] = useState([]); + const [namespaceList, setNamespaceList] = useState([]); + const [selectedNamespace, setSelectedNamespace] = useState("default"); + const [dataPlaneSubscription, setDataPlaneSubscription] = useState(null); + const [controlPlaneSubscription, setControlPlaneSubscription] = useState(null); + const [clusterResourcesSubscription, setClusterResourcesSubscription] = useState(null); + const [clusterResourcesQuery, setClusterResourcesQuery] = useState(null); + const [namespaceQuery, setNamespaceQuery] = useState(null); + const [telemetryQuery, setTelemetryQuery] = useState(null); + const prevControlPlaneState = useRef(); + const prevDataPlaneState = useRef(); + const prevSelectedNamespace = useRef(); + const prevProps = useRef(props); + const isMetricsConfigured = grafana.grafanaURL !== "" && prometheus.prometheusURL !== ""; + + useEffect(() => { + if (props.meshAdaptersts > mts) { + // setMeshAdapters(props.meshAdapters); + setMts(props.meshAdaptersts); } - st.grafana = grafana; - st.prometheus = prometheus; - st.k8sconfig = props.k8sconfig - return st; - } - - disposeWorkloadWidgetSubscription = () => { - this.state.namespaceQuery && this.state.namespaceQuery.unsubscribe(); - this.state.clusterResourcesQuery && this.state.clusterResourcesQuery.unsubscribe() - this.state.clusterResourcesSubscription && this.state.clusterResourcesSubscription.dispose(); - } + setGrafana(props.grafana); + setPrometheus(props.prometheus); + // setK8sconfig(props.k8sconfig); + }, [props.meshAdaptersts, props.meshAdapters, props.grafana, props.prometheus, props.k8sconfig, mts]); + + const disposeWorkloadWidgetSubscription = () => { + namespaceQuery && namespaceQuery.unsubscribe(); + clusterResourcesQuery && clusterResourcesQuery.unsubscribe(); + clusterResourcesSubscription && clusterResourcesSubscription.dispose(); + }; - disposeSubscriptions = () => { - if (this.state.dataPlaneSubscription) { - this.state.dataPlaneSubscription.unsubscribe() + const disposeSubscriptions = () => { + if (dataPlaneSubscription) { + dataPlaneSubscription.unsubscribe(); } - if (this.state.controlPlaneSubscription) { - this.state.controlPlaneSubscription.unsubscribe() + if (controlPlaneSubscription) { + controlPlaneSubscription.unsubscribe(); } - if (this.state.telemetryQuery) { - this.state.telemetryQuery.unsubscribe(); + if (telemetryQuery) { + telemetryQuery.unsubscribe(); } - this.disposeWorkloadWidgetSubscription(); - } - - initMeshSyncControlPlaneSubscription = () => { - /** - * ALL_MESH indicates that we are interested in control plane - * component of all of the service meshes supported by meshsync v2 - */ - const self = this; - const ALL_MESH = { type : "ALL_MESH", k8sClusterIDs : self.getK8sClusterIds() }; + disposeWorkloadWidgetSubscription(); + }; + const initMeshSyncControlPlaneSubscription = () => { + const ALL_MESH = { type : "ALL_MESH", k8sClusterIDs : getK8sClusterIds() }; - if (self._isMounted) { + if (_isMounted.current) { const controlPlaneSubscription = fetchControlPlanes(ALL_MESH).subscribe({ next : (controlPlaneRes) => { - this.setState({ controlPlaneState : controlPlaneRes }) + setControlPlaneState(controlPlaneRes); }, error : (err) => console.error(err), }); const dataPlaneSubscription = fetchDataPlanes(ALL_MESH).subscribe({ next : (dataPlaneRes) => { - this.setState({ dataPlaneState : dataPlaneRes }) + setDataPlaneState(dataPlaneRes); }, error : (err) => console.error(err), }); - this.setState({ controlPlaneSubscription, dataPlaneSubscription }); + setDataPlaneSubscription(dataPlaneSubscription); + setControlPlaneSubscription(controlPlaneSubscription); } - } - - initNamespaceQuery = () => { - const self = this; + }; - const namespaceQuery = fetchAvailableNamespaces({ k8sClusterIDs : self.getK8sClusterIds() }) + const initNamespaceQuery = () => { + const namespaceQuery = fetchAvailableNamespaces({ k8sClusterIDs : getK8sClusterIds() }) .subscribe({ next : res => { - let namespaces = [] + let namespaces = []; res?.namespaces?.map(ns => { - namespaces.push(ns?.namespace) - }) - namespaces.sort((a, b) => ( - a > b ? 1 : -1 - )) - self.setState({ namespaceList : namespaces }) + namespaces.push(ns?.namespace); + }); + namespaces.sort((a, b) => (a > b ? 1 : -1)); + setNamespaceList(namespaces); }, - error : (err) => console.log("error at namespace fetch: " + err), - }) + error : err => console.log("error at namespace fetch: " + err), + }); - this.setState({ namespaceQuery }) - } + setNamespaceQuery(namespaceQuery); + }; - initDashboardClusterResourcesQuery = () => { - const self = this; - let k8s = self.getK8sClusterIds(); - let namespace = self.state.selectedNamespace; + const initDashboardClusterResourcesQuery = () => { + let k8s = getK8sClusterIds(); - if (self._isMounted) { - // @ts-ignore - const clusterResourcesQuery = fetchClusterResources(k8s, namespace).subscribe({ - next : (res) => { - this.setState({ clusterResources : res?.clusterResources }) + if (_isMounted.current) { + const clusterResourcesQuery = fetchClusterResources(k8s, selectedNamespace).subscribe({ + next : res => { + setClusterResources(res?.clusterResources); }, - error : (err) => console.log(err), - }) + error : err => console.log(err), + }); - this.setState({ clusterResourcesQuery }); + setClusterResourcesQuery(clusterResourcesQuery); } } - initDashboardClusterResourcesSubscription = () => { - const self = this; - let k8s = self.getK8sClusterIds(); - let namespace = self.state.selectedNamespace; - if (self._isMounted) { - // @ts-ignore + const initDashboardClusterResourcesSubscription = () => { + let k8s = getK8sClusterIds(); + + if (_isMounted.current) { const clusterResourcesSubscription = subscribeClusterResources((res) => { - this.setState({ clusterResources : res?.clusterResources }) + setClusterResources(res?.clusterResources); }, { k8scontextIDs : k8s, - namespace : namespace + namespace : selectedNamespace }); - this.setState({ clusterResourcesSubscription }); - } - } - initTelemetryComponentQuery = () => { - const self = this; - const contextIDs = self.getK8sClusterIds(); - const telemetryQuery = fetchTelemetryCompsQuery({ - contexts : contextIDs - }).subscribe({ - next : (components) => { - let prometheusURLs = []; - let grafanaURLs = []; - components.telemetryComps?.forEach((component) => { - const data = { spec : JSON.parse(component.spec), status : JSON.parse(component.status) }; - if (component.name === "grafana") { - grafanaURLs = grafanaURLs.concat(extractURLFromScanData(data)); - } else { - prometheusURLs = prometheusURLs.concat(extractURLFromScanData(data)); - } - }) + setClusterResourcesSubscription(clusterResourcesSubscription); + } + }; - this.props.updateTelemetryUrls({ telemetryURLs : { "grafana" : grafanaURLs, "prometheus" : prometheusURLs } }); - } - }) - this.setState({ telemetryQuery }); - } - componentWillUnmount = () => { - this._isMounted = false - this.disposeSubscriptions() - } + const initTelemetryComponentQuery = () => { + const contextIDs = getK8sClusterIds(); + + if (_isMounted.current) { + const query = fetchTelemetryCompsQuery({ contexts : contextIDs }).subscribe({ + next : (components) => { + let prometheusURLs = []; + let grafanaURLs = []; + components.telemetryComps?.forEach((component) => { + const data = { spec : JSON.parse(component.spec), status : JSON.parse(component.status) }; + if (component.name === "grafana") { + grafanaURLs = grafanaURLs.concat(extractURLFromScanData(data)); + } else { + prometheusURLs = prometheusURLs.concat(extractURLFromScanData(data)); + } + }); + updateTelemetryUrls({ telemetryURLs : { "grafana" : grafanaURLs, "prometheus" : prometheusURLs } }); + }, + error : (err) => console.error(err), + }); + setTelemetryQuery(query); + } + }; + useEffect(() => { + return () => { + _isMounted.current = false; + disposeSubscriptions(); + }; + }, []); - componentDidMount = () => { - this._isMounted = true - this.fetchAvailableAdapters(); + useEffect(() => { + fetchAvailableAdapters(); - if (this.state.isMetricsConfigured) { - this.fetchMetricComponents(); + if (isMetricsConfigured) { + fetchMetricComponents(); } - if (this._isMounted) { - this.initMeshSyncControlPlaneSubscription(); - this.initDashboardClusterResourcesQuery(); - this.initDashboardClusterResourcesSubscription(); - this.initNamespaceQuery(); - this.initTelemetryComponentQuery(); - } - }; + initMeshSyncControlPlaneSubscription(); + initDashboardClusterResourcesQuery(); + initDashboardClusterResourcesSubscription(); + initNamespaceQuery(); + initTelemetryComponentQuery(); + }, []); - componentDidUpdate(prevProps, prevState) { + useEffect(() => { let updateControlPlane = false; let updateDataPlane = false; - // deep compare very limited, order of object fields is important - if (JSON.stringify(prevState.controlPlaneState) !== JSON.stringify(this.state.controlPlaneState)) { + if (JSON.stringify(prevControlPlaneState.current) !== JSON.stringify(controlPlaneState)) { updateControlPlane = true; } - if (JSON.stringify(prevState.dataPlaneState) !== JSON.stringify(this.state.dataPlaneState)) { + if (JSON.stringify(prevDataPlaneState.current) !== JSON.stringify(dataPlaneState)) { updateDataPlane = true; } if (updateDataPlane || updateControlPlane) { - this.setMeshScanData( - updateControlPlane ? this.state.controlPlaneState : prevState.controlPlaneState, - updateDataPlane ? this.state.dataPlaneState : prevState.dataPlaneState - ) + setMeshScanData( + updateControlPlane ? controlPlaneState : prevControlPlaneState.current, + updateDataPlane ? dataPlaneState : prevDataPlaneState.current + ); } - // handle subscriptions update on switching K8s Contexts - if (prevProps?.selectedK8sContexts !== this.props?.selectedK8sContexts - || prevProps.k8sconfig !== this.props.k8sconfig) { - this.disposeSubscriptions(); - this.initMeshSyncControlPlaneSubscription(); - this.initDashboardClusterResourcesQuery(); - this.initDashboardClusterResourcesSubscription(); - this.initNamespaceQuery(); - this.initTelemetryComponentQuery(); + // Update the refs with the current state + prevControlPlaneState.current = controlPlaneState; + prevDataPlaneState.current = dataPlaneState; + }, [controlPlaneState, dataPlaneState]); + + useEffect(() => { + if (prevProps.current.selectedK8sContexts !== props.selectedK8sContexts + || prevProps.current.k8sconfig !== props.k8sconfig) { + disposeSubscriptions(); + initMeshSyncControlPlaneSubscription(); + initDashboardClusterResourcesQuery(); + initDashboardClusterResourcesSubscription(); + initNamespaceQuery(); + initTelemetryComponentQuery(); } - if (prevState?.selectedNamespace !== this.state?.selectedNamespace) { - this.disposeWorkloadWidgetSubscription(); - this.initDashboardClusterResourcesSubscription(); - this.initDashboardClusterResourcesQuery(); - this.initNamespaceQuery(); + // Update the ref with the current props + prevProps.current = props; + }, [props]); + + useEffect(() => { + if (prevSelectedNamespace.current !== selectedNamespace) { + disposeWorkloadWidgetSubscription(); + initDashboardClusterResourcesSubscription(); + initDashboardClusterResourcesQuery(); + initNamespaceQuery(); } - } + // Update the ref with the current state + prevSelectedNamespace.current = selectedNamespace; + }, [selectedNamespace]); - getK8sClusterIds = () => { - const self = this; - return getK8sClusterIdsFromCtxId(self.props?.selectedK8sContexts, self.props.k8sconfig) - } - fetchMetricComponents = () => { - const self = this; - let selector = { type : "ALL_MESH", k8sClusterIDs : this.getK8sClusterIds() }; + const getK8sClusterIds = () => { + return getK8sClusterIdsFromCtxId(props.selectedK8sContexts, props.k8sconfig); + }; + + const fetchMetricComponents = () => { + let selector = { type : "ALL_MESH", k8sClusterIDs : getK8sClusterIds() }; dataFetch( "/api/telemetry/metrics/config", { method : "GET", credentials : "include", - headers : { "Content-Type" : "application/x-www-form-urlencoded;charset=UTF-8", }, + headers : { "Content-Type" : "application/x-www-form-urlencoded;charset=UTF-8" }, }, (result) => { - self.props.updateProgress({ showProgress : false }); - if (typeof result !== "undefined" && result?.prometheusURL && result?.prometheusURL != "") { + props.updateProgress({ showProgress : false }); + if (result?.prometheusURL && result?.prometheusURL !== "") { fetchAvailableAddons(selector).subscribe({ next : (res) => { res?.addonsState?.forEach((addon) => { - if (addon.name === "prometheus" && (self.state.prometheusURL === "" || self.state.prometheusURL == undefined)) { - self.setState({ prometheusURL : "http://" + addon.endpoint }) - submitPrometheusConfigure(self, () => console.log("Prometheus added")); + if (addon.name === "prometheus" && (!prometheusURL || prometheusURL === "")) { + setPrometheusURL("http://" + addon.endpoint); + submitPrometheusConfigure(() => console.log("Prometheus added")); } }); }, - error : (err) => console.log("error registering prometheus: " + err), + error : (err) => console.error("error registering prometheus:", err), }); } }, - self.handleError("Error getting prometheus config") + handleError("Error getting prometheus config") ); dataFetch( @@ -393,53 +406,51 @@ class DashboardComponent extends React.Component { { method : "GET", credentials : "include", - headers : { "Content-Type" : "application/x-www-form-urlencoded;charset=UTF-8", }, + headers : { "Content-Type" : "application/x-www-form-urlencoded;charset=UTF-8" }, }, (result) => { - self.props.updateProgress({ showProgress : false }); - if (typeof result !== "undefined" && result?.grafanaURL && result?.grafanaURL != "") { + props.updateProgress({ showProgress : false }); + if (result?.grafanaURL && result?.grafanaURL !== "") { fetchAvailableAddons(selector).subscribe({ next : (res) => { res?.addonsState?.forEach((addon) => { - if (addon.name === "grafana" && (self.state.grafanaURL === "" || self.state.grafanaURL == undefined)) { - self.setState({ grafanaURL : "http://" + addon.endpoint }) - submitGrafanaConfigure(self, () => { - self.state.selectedBoardsConfigs.push(self.state.boardConfigs); + if (addon.name === "grafana" && (!grafanaURL || grafanaURL === "")) { + setGrafanaURL("http://" + addon.endpoint); + submitGrafanaConfigure(() => { + // setSelectedBoardsConfigs((prevConfigs) => [...prevConfigs, boardConfigs]); console.info("Grafana added"); }); } }); }, - error : (err) => console.log("error registering grafana: " + err), + error : (err) => console.error("error registering grafana:", err), }); } }, - self.handleError("There was an error communicating with grafana config") + handleError("There was an error communicating with grafana config") ); - fetchAvailableAddons(selector).subscribe({ next : (res) => { res?.addonsState?.forEach((addon) => { - if (addon.name === "prometheus" && (self.state.prometheusURL === "" || self.state.prometheusURL == undefined)) { - self.setState({ prometheusURL : "http://" + addon.endpoint }) - submitPrometheusConfigure(self, () => console.log("Prometheus connected")); - } else if (addon.name === "grafana" && (self.state.grafanaURL === "" || self.state.grafanaURL == undefined)) { - self.setState({ grafanaURL : "http://" + addon.endpoint }) - submitGrafanaConfigure(self, () => { - self.state.selectedBoardsConfigs.push(self.state.boardConfigs); + if (addon.name === "prometheus" && (!prometheusURL || prometheusURL === "")) { + setPrometheusURL("http://" + addon.endpoint); + submitPrometheusConfigure(() => console.log("Prometheus connected")); + } else if (addon.name === "grafana" && (!grafanaURL || grafanaURL === "")) { + setGrafanaURL("http://" + addon.endpoint); + submitGrafanaConfigure(() => { + // setSelectedBoardsConfigs((prevConfigs) => [...prevConfigs, boardConfigs]); console.log("Grafana added"); }); } }); }, - error : (err) => console.log("error registering addons: " + err), + error : (err) => console.error("error registering addons:", err), }); }; + const fetchAvailableAdapters = () => { - fetchAvailableAdapters = () => { - const self = this; - this.props.updateProgress({ showProgress : true }); + props.updateProgress({ showProgress : true }); dataFetch( "/api/system/adapters", { @@ -447,34 +458,41 @@ class DashboardComponent extends React.Component { credentials : "include", }, (result) => { - this.props.updateProgress({ showProgress : false }); + props.updateProgress({ showProgress : false }); if (typeof result !== "undefined") { + /* eslint-disable no-unused-vars */ const options = result.map((res) => ({ value : res.adapter_location, label : res.adapter_location, })); - this.setState({ availableAdapters : options }); + + + + + // this.setState({ availableAdapters : options }); + // setAvailableAdapters(options); } }, - self.handleError("Unable to fetch list of adapters.") + handleError("Unable to fetch list of adapters.") ); }; + const setMeshScanData = (controlPlanesData, dataPlanesData) => { - setMeshScanData = (controlPlanesData, dataPlanesData) => { - const self = this; const namespaces = {}; const activeNamespaces = {}; + const processedControlPlanesData = controlPlanesData?.controlPlanesState?.map((mesh) => { if (!mesh?.members?.length) { return; } - let proxies = [] + let proxies = []; if (Array.isArray(dataPlanesData?.dataPlanesState)) { - const dataplane = dataPlanesData.dataPlanesState.find(mesh_ => mesh_.name === mesh.name) + const dataplane = dataPlanesData.dataPlanesState.find(mesh_ => mesh_.name === mesh.name); - if (Array.isArray(dataplane?.proxies)) proxies = dataplane.proxies + if (Array.isArray(dataplane?.proxies)) proxies = dataplane.proxies; } + const processedMember = mesh?.members?.map((member) => { if (namespaces[mesh.name]) { namespaces[mesh.name].add(member.namespace); @@ -482,32 +500,33 @@ class DashboardComponent extends React.Component { namespaces[mesh.name] = new Set([member.namespace]); } - // retrieve data planes according to mesh name if (proxies.length > 0) { - const controlPlaneMemberProxies = proxies.filter(proxy => proxy.controlPlaneMemberName === member.name) + const controlPlaneMemberProxies = proxies.filter(proxy => proxy.controlPlaneMemberName === member.name); if (controlPlaneMemberProxies.length > 0) { member = { ...member, data_planes : controlPlaneMemberProxies - } + }; } } - return member + return member; }); + namespaces[mesh.name] = [...namespaces[mesh.name]]; activeNamespaces[mesh.name] = namespaces[mesh.name][0] || ""; return { ...mesh, members : processedMember - } + }; }); - self.setState({ meshScan : processedControlPlanesData?.filter(data => !!data).filter((data) => data.members?.length > 0) }); - self.setState({ meshScanNamespaces : namespaces, activeMeshScanNamespace : activeNamespaces }); - }; + setMeshScan(processedControlPlanesData?.filter(data => !!data).filter((data) => data.members?.length > 0)); + // setMeshScanNamespaces(namespaces); + // setActiveMeshScanNamespace(activeNamespaces); + }; /** * generateMeshScanPodName takes in the podname and the hash * and returns the trimmed pod name @@ -516,15 +535,13 @@ class DashboardComponent extends React.Component { * @param {string | undefined} custom * @returns {{full, trimmed}} */ - generateMeshScanPodName = (podname, hash, custom) => { - const str = custom || podname; - return { - full : podname, - trimmed : str.substring(0, (hash ? str.indexOf(hash) - : str.length) - 1), - }; - }; - + // const generateMeshScanPodName = (podname, hash, custom) => { + // const str = custom || podname; + // return { + // full : podname, + // trimmed : str.substring(0, (hash ? str.indexOf(hash) : str.length) - 1), + // }; + // }; /** * generateMeshScanVersion takes in the string from which version * is to be extracted and returns the version. If the version string @@ -532,125 +549,93 @@ class DashboardComponent extends React.Component { * @param {string | undefined} versionStr is the string from which version is to be extracted * @returns {string} */ - generateMeshScanVersion = (versionStr) => { - if (typeof versionStr !== "string") return "NA"; - - const matchResult = versionStr.match(/\d+(\.\d+){2,}/g); - if (!matchResult) return "NA"; - - // Add "v" iff we have a valid match result - return `v${matchResult[0]}`; + // const generateMeshScanVersion = (versionStr) => { + // if (typeof versionStr !== "string") return "NA"; + + // const matchResult = versionStr.match(/\d+(\.\d+){2,}/g); + // if (!matchResult) return "NA"; + + // // Add "v" iff we have a valid match result + // return `v${matchResult[0]}`; + // }; + const handleError = (msg) => (error) => { + props.updateProgress({ showProgress : false }); + notify({ message : `${msg}: ${error}`, event_type : EVENT_TYPES.ERROR }); }; - - handleError = (msg) => (error) => { - this.props.updateProgress({ showProgress : false }); - const notify = this.props.notify; - notify({ message : `${msg}: ${error}`, event_type : EVENT_TYPES.ERROR }) - }; - /** * redirectErrorToConsole returns a function which redirects * ther error to the console under the group labelled by the "msg" * param * @param {string} msg */ - redirectErrorToConsole = (msg) => (error) => { - this.props.updateProgress({ showProgress : false }); - console.group(msg); - console.error(error); - console.groupEnd(); - }; - - handleAdapterPingError = (msg) => () => { - this.props.updateProgress({ showProgress : false }); - const notify = this.props.notify; - // this.props.enqueueSnackbar(`${msg}. To configure an adapter, visit`, { - // variant : "error", - // autoHideDuration : 3000, - // action : (key) => ( - // <> - // - - // self.props.closeSnackbar(key)}> - // - // - // - // ), - // }); - notify({ message : `${msg}`, event_type : EVENT_TYPES.ERROR }) - }; - - handleDelete() { - return false; - } - - handleAdapterClick = (adapterLoc) => () => { - // const { meshAdapters } = this.state; - this.props.updateProgress({ showProgress : true }); - const self = this; - const notify = this.props.notify; - dataFetch( - `/api/system/adapters?adapter=${encodeURIComponent(adapterLoc)}`, - { - credentials : "include", - }, - (result) => { - this.props.updateProgress({ showProgress : false }); - if (typeof result !== "undefined") { - notify({ message : `Meshery Adapter connected at ${adapterLoc}`, event_type : EVENT_TYPES.SUCCESS }) - } - }, - self.handleAdapterPingError("Could not connect to " + adapterLoc) - ); - }; - - handleConfigure = (val) => { - this.props.router.push(`/settings#metrics/${val}`); + // const redirectErrorToConsole = (msg) => (error) => { + // props.updateProgress({ showProgress : false }); + // console.group(msg); + // console.error(error); + // console.groupEnd(); + // }; + // const handleAdapterPingError = (msg) => () => { + // props.updateProgress({ showProgress : false }); + + + // // If you want to use the snackbar code, you might need additional logic or hooks + // // based on your functional component setup. + + // notify({ message : `${msg}`, event_type : EVENT_TYPES.ERROR }); + // }; + // function handleDelete() { + // return false; + // } + + // const handleAdapterClick = (adapterLoc) => () => { + // // const { meshAdapters } = this.state; + // props.updateProgress({ showProgress : true }); + + // dataFetch( + // `/api/system/adapters?adapter=${encodeURIComponent(adapterLoc)}`, + // { + // credentials : "include", + // }, + // (result) => { + // props.updateProgress({ showProgress : false }); + // if (typeof result !== "undefined") { + // notify({ message : `Meshery Adapter connected at ${adapterLoc}`, event_type : EVENT_TYPES.SUCCESS }) + // } + // }, + // handleAdapterPingError("Could not connect to " + adapterLoc) + // ); + // }; + + // const handleConfigure = (val) => { + // router.push(`/settings#metrics/${val}`); + // }; + const getSelectedK8sContextsNames = () => { + return getK8sClusterNamesFromCtxId(props.selectedK8sContexts, props.k8sconfig); }; - - getSelectedK8sContextsNames = () => { - return getK8sClusterNamesFromCtxId(this.props.selectedK8sContexts, this.props.k8sconfig) - } - - emptyStateMessageForServiceMeshesInfo = () => { - const clusters = this.getSelectedK8sContextsNames(); + const emptyStateMessageForServiceMeshesInfo = () => { + const clusters = getSelectedK8sContextsNames(); if (clusters.length === 0) { - return "No Cluster is selected to show the Service Mesh Information" + return "No Cluster is selected to show the Service Mesh Information"; } if (clusters.includes("all")) { - return `No service meshes detected in any of the cluster.` + return `No service meshes detected in any of the cluster.`; } - return `No service meshes detected in the ${clusters.join(", ")} cluster(s).` - } - - emptyStateMessageForClusterResources = () => { - const clusters = this.getSelectedK8sContextsNames(); + return `No service meshes detected in the ${clusters.join(", ")} cluster(s).`; + }; + const emptyStateMessageForClusterResources = () => { + const clusters = getSelectedK8sContextsNames(); if (clusters.length === 0) { - return "No Cluster is selected to show the discovered resources" + return "No Cluster is selected to show the discovered resources"; } if (clusters.includes("all")) { - return `No resources detected in any of the cluster.` + return `No resources detected in any of the cluster.`; } - return `No resources detected in the ${clusters.join(", ")} cluster(s).` - } + return `No resources detected in the ${clusters.join(", ")} cluster(s).`; + }; - handleKubernetesClick = (id) => { - this.props.updateProgress({ showProgress : true }); - const self = this; - const notify = this.props.notify; - const selectedCtx = this.props.k8sconfig?.find((ctx) => ctx.id === id); + const handleKubernetesClick = (id) => { + props.updateProgress({ showProgress : true }); + const selectedCtx = props.k8sconfig?.find((ctx) => ctx.id === id); if (!selectedCtx) return; const { server, name } = selectedCtx; @@ -660,35 +645,32 @@ class DashboardComponent extends React.Component { credentials : "include", }, (result) => { - this.props.updateProgress({ showProgress : false }); + props.updateProgress({ showProgress : false }); if (typeof result !== "undefined") { - notify({ message : `${name} is connected at ${server}`, event_type : EVENT_TYPES.SUCCESS }) + notify({ message : `${name} is connected at ${server}`, event_type : EVENT_TYPES.SUCCESS }); } }, - self.handleError("Could not connect to Kubernetes") + handleError("Could not connect to Kubernetes") ); }; - - handleGrafanaClick = () => { - this.props.updateProgress({ showProgress : true }); - const self = this; - const notify = this.props.notify; - const { grafanaURL } = this.state.grafana; - dataFetch( - "/api/telemetry/metrics/grafana/ping", - { - credentials : "include", - }, - (result) => { - this.props.updateProgress({ showProgress : false }); - if (typeof result !== "undefined") { - notify({ message : `Grafana connected at ${grafanaURL}`, event_type : EVENT_TYPES.SUCCESS }) - } - }, - self.handleError("Could not connect to Grafana") - ); - }; - + // const handleGrafanaClick = () => { + // props.updateProgress({ showProgress : true }); + // const grafanaURL = grafana.grafanaURL; // Assuming grafana is a state or prop + + // dataFetch( + // "/api/telemetry/metrics/grafana/ping", + // { + // credentials : "include", + // }, + // (result) => { + // props.updateProgress({ showProgress : false }); + // if (typeof result !== "undefined") { + // notify({ message : `Grafana connected at ${grafanaURL}`, event_type : EVENT_TYPES.SUCCESS }); + // } + // }, + // handleError("Could not connect to Grafana") + // ); + // }; /** * Meshcard takes in the mesh related data * and renders a table along with other information of @@ -696,229 +678,261 @@ class DashboardComponent extends React.Component { * @param {{name, icon, tag}} mesh * @param {{name, component, version, namespace}[]} components Array of components data */ - Meshcard = (mesh, components = []) => { - const self = this; - let componentSort = "asc"; - let versionSort = "asc"; - let proxySort = "asc"; - let tempComp = []; - const { theme } = this.props; - components - .filter((comp) => comp.namespace === self.state.activeMeshScanNamespace[mesh.name]) - .map((component) => tempComp.push(component)) - - components = tempComp; - - const switchSortOrder = (type) => { - if (type === "componentSort") { - componentSort = (componentSort === "asc") ? "desc" : "asc"; - versionSort = "asc"; - proxySort = "asc"; - } else if (type === "versionSort") { - versionSort = (versionSort === "asc") ? "desc" : "asc"; - componentSort = "asc"; - proxySort = "asc"; - } else if (type === "proxySort") { - proxySort = (proxySort === "asc") ? "desc" : "asc"; - componentSort = "asc"; - versionSort = "asc"; - } - } - - const columns = [ - { - name : "name", - label : "Component", - options : { - filter : false, - sort : true, - searchable : true, - setCellProps : () => ({ style : { textAlign : "center" } }), - customHeadRender : ({ index, ...column }, sortColumn) => { - return ( - { - sortColumn(index); switchSortOrder("componentSort"); - }}> - - {column.label} - - - - ) - } - }, - customBodyRender : (value) => { - const modifiedName = value.replace(/-[a-zA-Z0-9]*$/, ''); // Remove last hyphen and alphanumeric characters after it - return {modifiedName}; - }, - }, - { - name : "version", - label : "Version", - options : { - filter : false, - sort : true, - searchable : true, - setCellProps : () => ({ style : { textAlign : "center" } }), - customHeadRender : ({ index, ...column }, sortColumn) => { - return ( - { - sortColumn(index); switchSortOrder("versionSort"); - }}> - - {column.label} - - - - ); - }, - customBodyRender : (value) => { - return (versionMapper(value)) - }, - }, - }, - { - name : "data_planes", - label : "Proxy", - options : { - filter : false, - sort : true, - searchable : true, - setCellProps : () => ({ style : { textAlign : "center" } }), - customHeadRender : ({ index, ...column }, sortColumn) => { - return ( - { - sortColumn(index); switchSortOrder("proxySort"); - }}> - - {column.label} - - - ) - }, - customBodyRender : (value) => { - return ( - <> - 0 ? ( - value.map((cont) => { - return ( -
-

Name: {cont?.containerName ? cont.containerName : 'Unspecified'}

-

Status: {cont?.status?.ready ? 'ready' : 'not ready'}

- {!cont?.status?.ready && ( - typeof cont?.status?.lastState === 'object' && cont?.status?.lastState !== null && Object.keys(cont.status.lastState).length > 0 && ( -
-

Last state: {Object.keys(cont?.status?.lastState)[0]}
Error: {Object.values(cont?.status?.lastState)[0]?.exitCode}
Finished at: {Object.values(cont?.status?.lastState)[0]?.finishedAt}

-
- ) - )} - {typeof cont?.status?.state === 'object' && cont?.status?.state !== null && Object.keys(cont.status.state).length > 0 && ( -

State: {Object.keys(cont.status.state)[0]}

- )} - {cont?.status?.restartCount && ( -

Restart count: {cont?.status.restartCount}

- )} -

Image: {cont.image}

-

Ports:
{cont?.ports && cont.ports.map(port => `[ ${port?.name ? port.name : 'Unknown'}, ${port?.containerPort ? port.containerPort : 'Unknown'}, ${port?.protocol ? port.protocol : 'Unknown'} ]`).join(', ')}

- {cont?.resources && ( -
- Resources used:
- -
- {cont?.resources?.limits && ( -
-

Limits:
- CPU: {cont?.resources?.limits?.cpu} - Memory: {cont?.resources?.limits?.memory}

-
- )} - {cont?.resources?.requests && ( -
-

Requests:
- CPU: {cont?.resources?.requests?.cpu} - Memory: {cont?.resources?.requests?.memory}

-
- )} -
-
- )} -
- ) - }) - ) : "No proxy attached"} - > - {value?.length || 0} -
- - ); - } - }, - }, - ] - - const options = { - filter : false, - selectableRows : "none", - responsive : "standard", - print : false, - download : false, - viewColumns : false, - pagination : false, - fixedHeader : true, - customToolbar : () => { - return ( - <> - {self.state.activeMeshScanNamespace[mesh.name] && ( - - )} - - ) - }, - } - - if (Array.isArray(components) && components.length) - return ( - - - - -
- - {mesh.tag} -
- - } - data={components} - options={options} - columns={columns} - /> -
-
- ); - - return null; - }; - + // const MeshCard = (mesh, components = []) => { + // let componentSort = "asc"; + // let versionSort = "asc"; + // let proxySort = "asc"; + // let tempComp = []; + // const { theme } = props; + + // components + // .filter(comp => comp.namespace === props.activeMeshScanNamespace[mesh.name]) + // .map(component => tempComp.push(component)); + + // components = tempComp; + + // const switchSortOrder = type => { + // if (type === "componentSort") { + // componentSort = componentSort === "asc" ? "desc" : "asc"; + // versionSort = "asc"; + // proxySort = "asc"; + // } else if (type === "versionSort") { + // versionSort = versionSort === "asc" ? "desc" : "asc"; + // componentSort = "asc"; + // proxySort = "asc"; + // } else if (type === "proxySort") { + // proxySort = proxySort === "asc" ? "desc" : "asc"; + // componentSort = "asc"; + // versionSort = "asc"; + // } + // }; + + // const columns = [ + // { + // name : "name", + // label : "Component", + // options : { + // filter : false, + // sort : true, + // searchable : true, + // setCellProps : () => ({ style : { textAlign : "center" } }), + // customHeadRender : ({ index, ...column }, sortColumn) => { + // return ( + // { + // sortColumn(index); switchSortOrder("componentSort"); + // }}> + // + // {column.label} + // + // + + // ) + // } + // }, + // customBodyRender : (value) => { + // const modifiedName = value.replace(/-[a-zA-Z0-9]*$/, ''); // Remove last hyphen and alphanumeric characters after it + // return {modifiedName}; + // }, + // }, + // { + // name : "version", + // label : "Version", + // options : { + // filter : false, + // sort : true, + // searchable : true, + // setCellProps : () => ({ style : { textAlign : "center" } }), + // customHeadRender : ({ index, ...column }, sortColumn) => { + // return ( + // { + // sortColumn(index); switchSortOrder("versionSort"); + // }}> + // + // {column.label} + // + // + + // ); + // }, + // customBodyRender : (value) => { + // return (versionMapper(value)) + // }, + // }, + // }, + // { + // name : "data_planes", + // label : "Proxy", + // options : { + // filter : false, + // sort : true, + // searchable : true, + // setCellProps : () => ({ style : { textAlign : "center" } }), + // customHeadRender : ({ index, ...column }, sortColumn) => { + // return ( + // { + // sortColumn(index); switchSortOrder("proxySort"); + // }}> + // + // {column.label} + // + // + // ) + // }, + // customBodyRender : (value) => { + // return ( + // <> + // 0 ? ( + // value.map((cont) => { + // return ( + //
+ //

Name: {cont?.containerName ? cont.containerName : 'Unspecified'}

+ //

Status: {cont?.status?.ready ? 'ready' : 'not ready'}

+ // {!cont?.status?.ready && ( + // typeof cont?.status?.lastState === 'object' && cont?.status?.lastState !== null && Object.keys(cont.status.lastState).length > 0 && ( + //
+ //

Last state: {Object.keys(cont?.status?.lastState)[0]}
Error: {Object.values(cont?.status?.lastState)[0]?.exitCode}
Finished at: {Object.values(cont?.status?.lastState)[0]?.finishedAt}

+ //
+ // ) + // )} + // {typeof cont?.status?.state === 'object' && cont?.status?.state !== null && Object.keys(cont.status.state).length > 0 && ( + //

State: {Object.keys(cont.status.state)[0]}

+ // )} + // {cont?.status?.restartCount && ( + //

Restart count: {cont?.status.restartCount}

+ // )} + //

Image: {cont.image}

+ //

Ports:
{cont?.ports && cont.ports.map(port => `[ ${port?.name ? port.name : 'Unknown'}, ${port?.containerPort ? port.containerPort : 'Unknown'}, ${port?.protocol ? port.protocol : 'Unknown'} ]`).join(', ')}

+ // {cont?.resources && ( + //
+ // Resources used:
+ + //
+ // {cont?.resources?.limits && ( + //
+ //

Limits:
+ // CPU: {cont?.resources?.limits?.cpu} - Memory: {cont?.resources?.limits?.memory}

+ //
+ // )} + // {cont?.resources?.requests && ( + //
+ //

Requests:
+ // CPU: {cont?.resources?.requests?.cpu} - Memory: {cont?.resources?.requests?.memory}

+ //
+ // )} + //
+ //
+ // )} + //
+ // ) + // }) + // ) : "No proxy attached"} + // > + // {value?.length || 0} + //
+ // + // ); + // } + // }, + // }, + // ] + + // const options = { + // filter : false, + // selectableRows : "none", + // responsive : "standard", + // print : false, + // download : false, + // viewColumns : false, + // pagination : false, + // fixedHeader : true, + // customToolbar : () => { + // return ( + // <> + // {activeMeshScanNamespace[mesh.name] && ( + // + // )} + // + // ) + // }, + // } + + // if (Array.isArray(components) && components.length) + // return ( + // + // + // + //
+ // + // {mesh.tag} + //
+ // + // } + // data={components} + // options={options} + // columns={columns} + // /> + //
+ //
+ // ); + + // return null; + // }; + // const handlePrometheusClick = () => { + // props.updateProgress({ showProgress : true }); + // const prometheusURL = prometheusURL; // Assuming you have prometheusURL in state + + // dataFetch( + // "/api/telemetry/metrics/ping", + // { credentials : "include" }, + // result => { + // props.updateProgress({ showProgress : false }); + // if (typeof result !== "undefined") { + // notify({ message : `Prometheus connected at ${prometheusURL}`, event_type : EVENT_TYPES.SUCCESS }); + // } + // }, + // handleError("Could not connect to Prometheus") + // ); + // }; + // const showCard=(title, content) => { + + // return ( + // + // + // {content} + // + // ); + // } /** - * ClusterResourcesCard takes in the cluster related data - * and renders a table with cluster resources information of - * the selected cluster and namespace - * @param {{kind, number}[]} resources - */ - ClusterResourcesCard = (resources = []) => { - const self = this; + * ClusterResourcesCard takes in the cluster related data + * and renders a table with cluster resources information of + * the selected cluster and namespace + * @param {{kind, number}[]} resources + */ + const ClusterResourcesCard = (resources = []) => { + let kindSort = "asc"; let countSort = "asc"; const { theme } = this.props; @@ -972,9 +986,8 @@ class DashboardComponent extends React.Component { {column.label} - ) - } + }, }, }, ] @@ -982,7 +995,7 @@ class DashboardComponent extends React.Component { const options = { filter : false, selectableRows : "none", - responsive : "standard", + responsive : "standard",namespaceList, print : false, download : false, viewColumns : false, @@ -991,14 +1004,16 @@ class DashboardComponent extends React.Component { customToolbar : () => { return ( <> - {self.state.namespaceList && ( + {namespaceList && ( )} @@ -1014,7 +1029,7 @@ class DashboardComponent extends React.Component { title={ <>
- + All Workloads
@@ -1029,54 +1044,17 @@ class DashboardComponent extends React.Component { return null; }; + const configureTemplate = () => { - handlePrometheusClick = () => { - this.props.updateProgress({ showProgress : true }); - const self = this; - const notify = this.props.notify; - const { prometheusURL } = this.state.prometheus; - dataFetch( - "/api/telemetry/metrics/ping", - { - credentials : "include", - }, - (result) => { - this.props.updateProgress({ showProgress : false }); - if (typeof result !== "undefined") { - notify({ message : `Prometheus connected at ${prometheusURL}`, event_type : EVENT_TYPES.SUCCESS }) - } - }, - self.handleError("Could not connect to Prometheus") - ); - }; - - showCard(title, content) { - const { classes } = this.props; - return ( - - - {content} - - ); - } - - configureTemplate = () => { - const { classes, k8sconfig } = this.props; - const self = this; let showConfigured = "Not connected to Kubernetes."; let chp = (
- {k8sconfig?.map(ctx => ( + {props.k8sconfig?.map(ctx => ( self.handleKubernetesClick(ctx.connection_id)} + onClick={() => handleKubernetesClick(ctx.connection_id)} icon={} variant="outlined" data-cy="chipContextName" @@ -1086,7 +1064,7 @@ class DashboardComponent extends React.Component {
); - if (!k8sconfig?.length) { + if (!props.k8sconfig?.length) { chp = showConfigured; } @@ -1094,10 +1072,10 @@ class DashboardComponent extends React.Component { const showServiceMesh =( <> - {self?.state?.meshScan && Object.keys(self?.state?.meshScan).length + {meshScan && Object.keys(meshScan).length ? ( <> - {self.state.meshScan.map((mesh) => { + {meshScan.map((mesh) => { let tag = ""; mesh.name .split("_") @@ -1122,17 +1100,17 @@ class DashboardComponent extends React.Component { }} > - {this.emptyStateMessageForServiceMeshesInfo()} + {emptyStateMessageForServiceMeshesInfo()} )} @@ -1140,9 +1118,9 @@ class DashboardComponent extends React.Component { ); const showClusterResources = ( <> - {self?.state?.clusterResources && Object.keys(self?.state?.clusterResources) && self?.state?.clusterResources?.resources?.length > 0 + {clusterResources && Object.keys(clusterResources) && clusterResources?.resources?.length > 0 ? ( - self.ClusterResourcesCard(self?.state?.clusterResources?.resources) + ClusterResourcesCard(clusterResources?.resources) ) : (
- {this.emptyStateMessageForClusterResources()} + {emptyStateMessageForClusterResources()}
)} @@ -1183,7 +1161,7 @@ class DashboardComponent extends React.Component {
- Workloads + Workloads {showClusterResources}
@@ -1197,7 +1175,7 @@ class DashboardComponent extends React.Component {
- Service Mesh + Service Mesh {showServiceMesh}
@@ -1210,14 +1188,12 @@ class DashboardComponent extends React.Component { ); }; - render() { - // console.info("Rerendering Dashboard") - return this.configureTemplate(); - } -} - -DashboardComponent.propTypes = { classes : PropTypes.object.isRequired, }; + return configureTemplate(); +} +DashboardComponent.propTypes = { + classes : PropTypes.object.isRequired, +}; const mapDispatchToProps = (dispatch) => ({ updateProgress : bindActionCreators(updateProgress, dispatch), updateGrafanaConfig : bindActionCreators(updateGrafanaConfig, dispatch), @@ -1243,6 +1219,4 @@ const mapStateToProps = (state) => { }; }; -export default withStyles(styles, { withTheme : true })( - connect(mapStateToProps, mapDispatchToProps)(withRouter(withNotify(DashboardComponent))) -); \ No newline at end of file +export default connect(mapStateToProps, mapDispatchToProps)((DashboardComponent));