diff --git a/public/app/features/dashboard-scene/scene/PanelSearchLayout.tsx b/public/app/features/dashboard-scene/scene/PanelSearchLayout.tsx
index 06d2e65d0b8..679bca8cb59 100644
--- a/public/app/features/dashboard-scene/scene/PanelSearchLayout.tsx
+++ b/public/app/features/dashboard-scene/scene/PanelSearchLayout.tsx
@@ -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,26 +34,33 @@ 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 (
+
}
+ >
+ {filteredPanels.map((panel) => (
+
+ ))}
+
+ );
+ }
+
return (
- }
- >
- {filteredPanels.map((panel) => (
-
- ))}
-
+
+ No matches found
+
);
}
@@ -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;
+}
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index b03939b26b6..63d9bb626dc 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -1924,6 +1924,7 @@
}
},
"panel-search": {
+ "no-matches": "No matches found",
"unsupported-layout": "Unsupported layout"
},
"playlist-edit": {
diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json
index 820267b08dc..fabb719f921 100644
--- a/public/locales/pseudo-LOCALE/grafana.json
+++ b/public/locales/pseudo-LOCALE/grafana.json
@@ -1924,6 +1924,7 @@
}
},
"panel-search": {
+ "no-matches": "Ńő mäŧčĥęş ƒőūʼnđ",
"unsupported-layout": "Ůʼnşūppőřŧęđ ľäyőūŧ"
},
"playlist-edit": {