UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

110 lines (109 loc) 6.04 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; /* * Copyright 2025 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Icon } from '@iconify/react'; import { Box, Tab, Tabs, Typography } from '@mui/material'; import { isEqual } from 'lodash'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router-dom'; import { setupBackstageMessageReceiver } from '../../../helpers/backstageMessageReceiver'; import { isBackstage } from '../../../helpers/isBackstage'; import { isElectron } from '../../../helpers/isElectron'; import { useClustersConf, useClustersVersion } from '../../../lib/k8s'; import { useEventWarningList } from '../../../lib/k8s/event'; import { createRouteURL } from '../../../lib/router/createRouteURL'; import { PageGrid } from '../../common/Resource'; import SectionBox from '../../common/SectionBox'; import { useLocalStorageState } from '../../globalSearch/useLocalStorageState'; import ProjectList from '../../project/ProjectList'; import ClusterTable from './ClusterTable'; import { ENABLE_RECENT_CLUSTERS } from './config'; import { getCustomClusterNames } from './customClusterNames'; import RecentClusters from './RecentClusters'; export default function Home() { const history = useHistory(); const clusters = useClustersConf(); if (!isElectron() && clusters && Object.keys(clusters).length === 1) { history.push(createRouteURL('cluster', { cluster: Object.keys(clusters)[0] })); return null; } return (_jsx(HomeComponent, { clusters: clusters }, 'home-component-' + Object.keys(clusters || {}).join(''))); } function useWarningSettingsPerCluster(clusterNames) { const warningsMap = useEventWarningList(clusterNames); const [warningLabels, setWarningLabels] = React.useState({}); const maxWarnings = 50; function renderWarningsText(warnings, clusterName) { const numWarnings = (!!warnings[clusterName]?.error && -1) || (warnings[clusterName]?.warnings?.length ?? -1); if (numWarnings === -1) { return '⋯'; } if (numWarnings >= maxWarnings) { return `${maxWarnings}+`; } return numWarnings.toString(); } React.useEffect(() => { setWarningLabels(currentWarningLabels => { const newWarningLabels = {}; for (const cluster of clusterNames) { newWarningLabels[cluster] = renderWarningsText(warningsMap, cluster); } if (!isEqual(newWarningLabels, currentWarningLabels)) { return newWarningLabels; } return currentWarningLabels; }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [warningsMap]); return warningLabels; } function HomeComponent(props) { const [view, setView] = useLocalStorageState('home-tab-view', 'clusters'); const { clusters } = props; const [customNameClusters, setCustomNameClusters] = React.useState(getCustomClusterNames(clusters)); const { t } = useTranslation(['translation', 'glossary']); const [versions, errors] = useClustersVersion(Object.values(clusters || {})); const warningLabels = useWarningSettingsPerCluster(Object.values(customNameClusters).map(c => c.name)); React.useEffect(() => { if (isBackstage()) { window.parent.postMessage({ type: 'HEADLAMP_READY' }, '*'); setupBackstageMessageReceiver(); } }, []); React.useEffect(() => { setCustomNameClusters(currentNames => { if (isEqual(currentNames, getCustomClusterNames(clusters))) { return currentNames; } return getCustomClusterNames(clusters); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [customNameClusters]); const memoizedComponent = React.useMemo(() => (_jsxs(_Fragment, { children: [ENABLE_RECENT_CLUSTERS && (_jsx(RecentClusters, { clusters: Object.values(customNameClusters), onButtonClick: () => { } })), _jsx(ClusterTable, { customNameClusters: customNameClusters, versions: versions, errors: errors, warningLabels: warningLabels, clusters: clusters })] })), // eslint-disable-next-line react-hooks/exhaustive-deps [customNameClusters, errors, versions, warningLabels]); return (_jsx(PageGrid, { children: _jsxs(SectionBox, { title: "Home", headerProps: { headerStyle: 'main' }, children: [_jsx(Box, { sx: { borderBottom: 1, borderColor: 'divider', mb: 2 }, children: _jsxs(Tabs, { value: view, onChange: (_, newView) => setView(() => newView), children: [_jsx(Tab, { value: "clusters", label: _jsxs(_Fragment, { children: [_jsx(Icon, { icon: "mdi:hexagon-multiple-outline" }), _jsx(Typography, { children: t('All Clusters') })] }), sx: { flexDirection: 'row', gap: 1, fontSize: '1.25rem', } }), _jsx(Tab, { value: "projects", label: _jsxs(_Fragment, { children: [_jsx(Icon, { icon: "mdi:folder-multiple" }), _jsx(Typography, { children: t('Projects') })] }), sx: { flexDirection: 'row', gap: 1, fontSize: '1.25rem', } })] }) }), view === 'clusters' && memoizedComponent, view === 'projects' && _jsx(ProjectList, {})] }) })); }