mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PanelSearch: Add support for rows & repeats (#94243)
* PanelSearch: Add support for rows & repeats * Show message if there are no matches
This commit is contained in:
@@ -3,7 +3,7 @@ import classNames from 'classnames';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { VizPanel, sceneGraph } from '@grafana/scenes';
|
||||
import { SceneGridRow, VizPanel, sceneGraph } from '@grafana/scenes';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
|
||||
@@ -34,17 +34,17 @@ export function PanelSearchLayout({ dashboard, panelSearch = '', panelsPerRow }:
|
||||
|
||||
for (const gridItem of bodyGrid.state.children) {
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
const panels = gridItem.state.repeatedPanels ?? [gridItem.state.body];
|
||||
for (const panel of panels) {
|
||||
const interpolatedTitle = panel.interpolate(panel.state.title, undefined, 'text').toLowerCase();
|
||||
const interpolatedSearchString = sceneGraph.interpolate(dashboard, panelSearch).toLowerCase();
|
||||
if (interpolatedTitle.includes(interpolatedSearchString)) {
|
||||
filteredPanels.push(panel);
|
||||
filterPanels(gridItem, dashboard, panelSearch, filteredPanels);
|
||||
} else if (gridItem instanceof SceneGridRow) {
|
||||
for (const rowItem of gridItem.state.children) {
|
||||
if (rowItem instanceof DashboardGridItem) {
|
||||
filterPanels(rowItem, dashboard, panelSearch, filteredPanels);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredPanels.length > 0) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.grid, { [styles.perRow]: panelsPerRow !== undefined })}
|
||||
@@ -57,6 +57,13 @@ export function PanelSearchLayout({ dashboard, panelSearch = '', panelsPerRow }:
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<p className={styles.noHits}>
|
||||
<Trans i18nKey="panel-search.no-matches">No matches found</Trans>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
function PanelSearchHit({ panel }: { panel: VizPanel }) {
|
||||
useEffect(() => activateInActiveParents(panel), [panel]);
|
||||
|
||||
@@ -74,5 +81,37 @@ function getStyles(theme: GrafanaTheme2) {
|
||||
perRow: css({
|
||||
gridTemplateColumns: `repeat(var(${panelsPerRowCSSVar}, 3), 1fr)`,
|
||||
}),
|
||||
noHits: css({
|
||||
display: 'grid',
|
||||
placeItems: 'center',
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function filterPanels(
|
||||
gridItem: DashboardGridItem,
|
||||
dashboard: DashboardScene,
|
||||
searchString: string,
|
||||
filteredPanels: VizPanel[]
|
||||
) {
|
||||
const interpolatedSearchString = sceneGraph.interpolate(dashboard, searchString).toLowerCase();
|
||||
|
||||
// activate inactive repeat panel if one of its children will be matched
|
||||
if (gridItem.state.variableName && !gridItem.isActive) {
|
||||
const panel = gridItem.state.body;
|
||||
const interpolatedTitle = panel.interpolate(panel.state.title, undefined, 'text').toLowerCase();
|
||||
if (interpolatedTitle.includes(interpolatedSearchString)) {
|
||||
gridItem.activate();
|
||||
}
|
||||
}
|
||||
|
||||
const panels = gridItem.state.repeatedPanels ?? [gridItem.state.body];
|
||||
for (const panel of panels) {
|
||||
const interpolatedTitle = panel.interpolate(panel.state.title, undefined, 'text').toLowerCase();
|
||||
if (interpolatedTitle.includes(interpolatedSearchString)) {
|
||||
filteredPanels.push(panel);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredPanels;
|
||||
}
|
||||
|
||||
@@ -1924,6 +1924,7 @@
|
||||
}
|
||||
},
|
||||
"panel-search": {
|
||||
"no-matches": "No matches found",
|
||||
"unsupported-layout": "Unsupported layout"
|
||||
},
|
||||
"playlist-edit": {
|
||||
|
||||
@@ -1924,6 +1924,7 @@
|
||||
}
|
||||
},
|
||||
"panel-search": {
|
||||
"no-matches": "Ńő mäŧčĥęş ƒőūʼnđ",
|
||||
"unsupported-layout": "Ůʼnşūppőřŧęđ ľäyőūŧ"
|
||||
},
|
||||
"playlist-edit": {
|
||||
|
||||
Reference in New Issue
Block a user