UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

174 lines (173 loc) 7.72 kB
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } 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 from '@mui/material/Box'; import Button from '@mui/material/Button'; import Typography from '@mui/material/Typography'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { ResourceClasses, useSelectedClusters } from '../../../lib/k8s'; import { localeDate } from '../../../lib/util'; import { NameValueTable } from '../../common/SimpleTable'; import Link from '../Link'; import { LightTooltip } from '../Tooltip'; export const metadataStyles = (theme) => ({ color: theme.palette.text.primary, backgroundColor: theme.palette.metadataBgColor, fontSize: theme.typography.pxToRem(16), wordBreak: 'break-word', paddingLeft: theme.spacing(1), paddingRight: theme.spacing(1), marginRight: theme.spacing(1), overflow: 'hidden', whiteSpace: 'nowrap', overflowWrap: 'anywhere', textOverflow: 'ellipsis', }); export function MetadataDisplay(props) { const { resource, extraRows } = props; const { t } = useTranslation(); const shouldShowCluster = useSelectedClusters().length > 1; let makeExtraRows; function makeOwnerReferences(ownerReferences) { if (!resource || ownerReferences === undefined) { return undefined; } const numItems = ownerReferences.length; if (numItems === 0) { return undefined; } return ownerReferences .map((ownerRef, i) => { if (ownerRef.kind in ResourceClasses) { let routeName; try { routeName = ResourceClasses[ownerRef.kind].detailsRoute; } catch (e) { console.error(`Error getting routeName for {ownerRef.kind}`, e); return null; } return (_jsxs(_Fragment, { children: [_jsxs(Link, { routeName: routeName, activeCluster: resource.cluster, params: { name: ownerRef.name, namespace: resource.metadata.namespace }, children: [ownerRef.kind, ": ", ownerRef.name] }), i < numItems - 1 && _jsx("br", {})] })); } return (_jsxs(_Fragment, { children: [`${ownerRef.kind}: ${ownerRef.name}`, i < numItems - 1 && _jsx("br", {})] })); }) .filter(element => element !== null); } if (typeof extraRows === 'function') { makeExtraRows = extraRows; } else if (!extraRows) { makeExtraRows = () => null; } else { makeExtraRows = () => extraRows; } const mainRows = [ { name: t('translation|Name'), value: resource.metadata.name, }, { name: t('glossary|Namespace'), value: resource.metadata.namespace && (_jsx(Link, { routeName: 'namespace', params: { name: resource.metadata.namespace }, activeCluster: resource.cluster, children: resource.metadata.namespace })), hide: !resource.metadata.namespace, }, shouldShowCluster && { name: t('glossary|Cluster'), value: resource.cluster, }, { name: t('Creation'), value: localeDate(resource.metadata.creationTimestamp), }, { name: t('Labels'), value: resource.metadata.labels && _jsx(MetadataDictGrid, { dict: resource.metadata.labels }), hide: !resource.metadata.labels, }, { name: t('Annotations'), value: resource.metadata.annotations && (_jsx(MetadataDictGrid, { dict: resource.metadata.annotations })), hide: !resource.metadata.annotations, }, { name: resource.metadata.ownerReferences && resource.metadata.ownerReferences.length > 1 ? t('Owner refs') : t('Controlled by'), value: makeOwnerReferences(resource.metadata.ownerReferences || []), hide: !resource.metadata.ownerReferences || resource.metadata.ownerReferences.length === 0, }, ].filter(Boolean).concat(makeExtraRows(resource) || []); return (_jsx(Box, { children: _jsx(NameValueTable, { rows: mainRows }) })); } export function MetadataDictGrid(props) { const { dict, showKeys = true, gridProps } = props; const { t } = useTranslation(); const [expanded, setExpanded] = React.useState(false); const defaultNumShown = 20; const keys = Object.keys(dict || []); const MetadataEntry = React.forwardRef((props, ref) => { return (_jsx(Typography, { ...props, sx: theme => ({ color: theme.palette.text.primary, borderRadius: theme.shape.borderRadius + 'px', backgroundColor: theme.palette.background.muted, border: '1px solid', borderColor: theme.palette.divider, fontSize: theme.typography.pxToRem(14), wordBreak: 'break-word', paddingTop: 0.5, paddingBottom: 0.5, paddingLeft: 1, paddingRight: 1, marginRight: theme.spacing(1), overflow: 'hidden', whiteSpace: 'nowrap', overflowWrap: 'anywhere', textOverflow: 'ellipsis', }), ref: ref })); }); function makeLabel(key) { let fullText = dict[key]; if (showKeys) { fullText = key + ': ' + fullText; } let shortText = fullText; // Shorten the label manually because relying on the ellipsing methods // was not working (it would correctly ellipse the text, but the width of it // would still extend the area/section where the text is contained). if (fullText.length > 50) { shortText = fullText.substr(0, 50) + '…'; } let labelComponent = _jsx(MetadataEntry, { children: shortText }); // If the full label is not being shown, use a tooltip to show the full text // to the user (so they select it, etc.). if (fullText.length !== shortText.length) { labelComponent = _jsx(LightTooltip, { title: fullText, children: labelComponent, interactive: true }); } return labelComponent; } return (_jsxs(Box, { children: [_jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 0.5, }, ...gridProps, children: keys.slice(0, expanded ? keys.length : defaultNumShown).map(key => (_jsx(React.Fragment, { children: makeLabel(key) }, key))) }), keys.length > defaultNumShown && (_jsx(Button, { onClick: () => setExpanded(!expanded), size: "small", startIcon: _jsx(Icon, { icon: expanded ? 'mdi:menu-up' : 'mdi:menu-down' }), sx: { mt: 1, mb: 1 }, children: !expanded ? t('translation|Show all labels (+{{count}} more)', { count: keys.length - defaultNumShown, }) : t('translation|Show fewer') }))] })); }