import { css } from '@emotion/css'; import { debounce } from 'lodash'; import { useEffect, useMemo, useState } from 'react'; import Skeleton from 'react-loading-skeleton'; import { GrafanaTheme2 } from '@grafana/data'; import { Checkbox, FilterInput, Icon, RadioButtonDot, useStyles2 } from '@grafana/ui'; import { t, Trans } from 'app/core/internationalization'; import { NodesMap, TreeScope } from './types'; export interface ScopesTreeLevelProps { nodes: NodesMap; nodePath: string[]; loadingNodeName: string | undefined; scopes: TreeScope[]; onNodeUpdate: (path: string[], isExpanded: boolean, query: string) => void; onNodeSelectToggle: (path: string[]) => void; } export function ScopesTreeLevel({ nodes, nodePath, loadingNodeName, scopes, onNodeUpdate, onNodeSelectToggle, }: ScopesTreeLevelProps) { const styles = useStyles2(getStyles); const nodeId = nodePath[nodePath.length - 1]; const node = nodes[nodeId]; const childNodes = node.nodes; const childNodesArr = Object.values(childNodes); const isNodeLoading = loadingNodeName === nodeId; const scopeNames = scopes.map(({ scopeName }) => scopeName); const anyChildExpanded = childNodesArr.some(({ isExpanded }) => isExpanded); const [queryValue, setQueryValue] = useState(node.query); useEffect(() => { setQueryValue(node.query); }, [node.query]); const onQueryUpdate = useMemo(() => debounce(onNodeUpdate, 500), [onNodeUpdate]); return ( <> {!anyChildExpanded && ( { setQueryValue(value); onQueryUpdate(nodePath, true, value); }} /> )} {!anyChildExpanded && !node.query && (
Recommended
)}
{isNodeLoading && } {!isNodeLoading && childNodesArr.map((childNode) => { const isSelected = childNode.isSelectable && scopeNames.includes(childNode.linkId!); if (anyChildExpanded && !childNode.isExpanded && !isSelected) { return null; } const childNodePath = [...nodePath, childNode.name]; const radioName = childNodePath.join('.'); return (
{childNode.isSelectable && !childNode.isExpanded ? ( node.disableMultiSelect ? ( { onNodeSelectToggle(childNodePath); }} /> ) : ( { onNodeSelectToggle(childNodePath); }} /> ) ) : null} {childNode.isExpandable ? ( ) : ( {childNode.title} )}
{childNode.isExpanded && ( )}
); })}
); } const getStyles = (theme: GrafanaTheme2) => { return { searchInput: css({ margin: theme.spacing(1, 0), }), headline: css({ color: theme.colors.text.secondary, margin: theme.spacing(1, 0), }), loader: css({ margin: theme.spacing(0.5, 0), }), itemTitle: css({ alignItems: 'center', display: 'flex', gap: theme.spacing(1), fontSize: theme.typography.pxToRem(14), lineHeight: theme.typography.pxToRem(22), padding: theme.spacing(0.5, 0), '& > label': css({ gap: 0, }), }), itemExpand: css({ alignItems: 'center', background: 'none', border: 0, display: 'flex', gap: theme.spacing(1), margin: 0, padding: 0, }), itemChildren: css({ paddingLeft: theme.spacing(4), }), }; };