CommanPalette: Add Assistant integration for empty state (#112601)
* CommanPalette: Add Assistant integration for empty state * Update assistant package and use new onClick pop * i18n * Update public/locales/en-US/grafana.json Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com> * Update public/app/features/commandPalette/CommandPalette.tsx Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com> * Update test --------- Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com>
This commit is contained in:
co-authored by
Sven Grossmann
parent
9a8d17a209
commit
1830e2ce9d
+1
-1
@@ -278,7 +278,7 @@
|
||||
"@glideapps/glide-data-grid": "^6.0.0",
|
||||
"@grafana/alerting": "workspace:*",
|
||||
"@grafana/api-clients": "workspace:*",
|
||||
"@grafana/assistant": "0.1.0",
|
||||
"@grafana/assistant": "0.1.1",
|
||||
"@grafana/aws-sdk": "0.7.1",
|
||||
"@grafana/azure-sdk": "0.0.8",
|
||||
"@grafana/data": "workspace:*",
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"typescript": "5.9.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@grafana/assistant": "^0.1.0",
|
||||
"@grafana/assistant": "^0.1.1",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { KBarProvider } from 'kbar';
|
||||
import { render, screen } from 'test/test-utils';
|
||||
|
||||
import { useAssistant } from '@grafana/assistant';
|
||||
import { setPluginLinksHook } from '@grafana/runtime';
|
||||
import { setGetObservablePluginLinks } from '@grafana/runtime/internal';
|
||||
|
||||
import { getObservablePluginLinks } from '../plugins/extensions/getPluginExtensions';
|
||||
|
||||
import { CommandPalette } from './CommandPalette';
|
||||
|
||||
setPluginLinksHook(() => ({
|
||||
links: [],
|
||||
isLoading: false,
|
||||
}));
|
||||
setGetObservablePluginLinks(getObservablePluginLinks);
|
||||
|
||||
jest.mock('@grafana/assistant', () => ({
|
||||
...jest.requireActual('@grafana/assistant'),
|
||||
useAssistant: jest.fn(),
|
||||
OpenAssistantButton: jest.fn().mockImplementation(({ title }) => <button>{title}</button>),
|
||||
}));
|
||||
|
||||
jest.mock('kbar', () => ({
|
||||
...jest.requireActual('kbar'),
|
||||
KBarPortal: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
|
||||
KBarAnimator: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
|
||||
}));
|
||||
|
||||
const setup = () => {
|
||||
return render(
|
||||
<KBarProvider>
|
||||
<CommandPalette />
|
||||
</KBarProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('CommandPalette', () => {
|
||||
it('should render empty state with AI Assistant button when no results and assistant is available', async () => {
|
||||
// Mock assistant being available
|
||||
(useAssistant as jest.Mock).mockReturnValue({ isAvailable: true });
|
||||
setup();
|
||||
|
||||
// Check if empty state message is rendered
|
||||
expect(await screen.findByText('No results found')).toBeInTheDocument();
|
||||
// Check if AI Assistant button is rendered with correct props
|
||||
expect(screen.getByRole('button', { name: 'Try searching with Grafana Assistant' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render empty state without AI Assistant button when assistant is not available', async () => {
|
||||
// Mock assistant being unavailable
|
||||
(useAssistant as jest.Mock).mockReturnValue({ isAvailable: false });
|
||||
setup();
|
||||
|
||||
// Check if empty state message is rendered
|
||||
expect(await screen.findByText('No results found')).toBeInTheDocument();
|
||||
// Check that AI Assistant button is not rendered
|
||||
expect(screen.queryByRole('button', { name: 'Try searching with Grafana Assistant' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import { useOverlay } from '@react-aria/overlays';
|
||||
import { KBarAnimator, KBarPortal, KBarPositioner, VisualState, useKBar, ActionImpl } from 'kbar';
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import { OpenAssistantButton, useAssistant } from '@grafana/assistant';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { t } from '@grafana/i18n';
|
||||
@@ -88,7 +89,11 @@ function CommandPaletteContents() {
|
||||
</div>
|
||||
{scopesRow ? <div className={styles.searchContainer}>{scopesRow}</div> : null}
|
||||
<div className={styles.resultsContainer}>
|
||||
<RenderResults isFetchingSearchResults={isFetchingSearchResults} searchResults={searchResults} />
|
||||
<RenderResults
|
||||
isFetchingSearchResults={isFetchingSearchResults}
|
||||
searchResults={searchResults}
|
||||
searchQuery={searchQuery}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</FocusScope>
|
||||
@@ -131,10 +136,13 @@ function AncestorBreadcrumbs() {
|
||||
interface RenderResultsProps {
|
||||
isFetchingSearchResults: boolean;
|
||||
searchResults: CommandPaletteAction[];
|
||||
searchQuery: string;
|
||||
}
|
||||
|
||||
const RenderResults = ({ isFetchingSearchResults, searchResults }: RenderResultsProps) => {
|
||||
const RenderResults = ({ isFetchingSearchResults, searchResults, searchQuery }: RenderResultsProps) => {
|
||||
const { results: kbarResults, rootActionId } = useMatches();
|
||||
const { query } = useKBar();
|
||||
const { isAvailable: isAssistantAvailable } = useAssistant();
|
||||
const lateralSpace = getCommandPalettePosition();
|
||||
const styles = useStyles2(getSearchStyles, lateralSpace);
|
||||
|
||||
@@ -176,11 +184,16 @@ const RenderResults = ({ isFetchingSearchResults, searchResults }: RenderResults
|
||||
}, [showEmptyState]);
|
||||
|
||||
return showEmptyState ? (
|
||||
<EmptyState
|
||||
variant="not-found"
|
||||
role="alert"
|
||||
message={t('command-palette.empty-state.message', 'No results found')}
|
||||
/>
|
||||
<EmptyState variant="not-found" role="alert" message={t('command-palette.empty-state.message', 'No results found')}>
|
||||
{isAssistantAvailable && (
|
||||
<OpenAssistantButton
|
||||
origin="grafana/command-palette-empty-state"
|
||||
prompt={`Search for ${searchQuery}`}
|
||||
title={t('command-palette.empty-state.button-title', 'Try searching with Grafana Assistant')}
|
||||
onClick={query.toggle}
|
||||
/>
|
||||
)}
|
||||
</EmptyState>
|
||||
) : (
|
||||
<KBarResults
|
||||
items={items}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"webpack": "5.101.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@grafana/assistant": "^0.1.0",
|
||||
"@grafana/assistant": "^0.1.1",
|
||||
"@grafana/runtime": "*"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -4130,6 +4130,7 @@
|
||||
"scopes": "Scopes"
|
||||
},
|
||||
"empty-state": {
|
||||
"button-title": "Try searching with Grafana Assistant",
|
||||
"message": "No results found"
|
||||
},
|
||||
"scopes": {
|
||||
|
||||
@@ -2543,7 +2543,7 @@ __metadata:
|
||||
typescript: "npm:5.9.2"
|
||||
webpack: "npm:5.101.0"
|
||||
peerDependencies:
|
||||
"@grafana/assistant": ^0.1.0
|
||||
"@grafana/assistant": ^0.1.1
|
||||
"@grafana/runtime": "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
@@ -3017,9 +3017,9 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@grafana/assistant@npm:0.1.0":
|
||||
version: 0.1.0
|
||||
resolution: "@grafana/assistant@npm:0.1.0"
|
||||
"@grafana/assistant@npm:0.1.1":
|
||||
version: 0.1.1
|
||||
resolution: "@grafana/assistant@npm:0.1.1"
|
||||
peerDependencies:
|
||||
"@grafana/data": ">=12.1.0"
|
||||
"@grafana/runtime": ">=12.1.0"
|
||||
@@ -3027,7 +3027,7 @@ __metadata:
|
||||
"@grafana/ui": ">=12.1.0"
|
||||
react: ">=18.0.0"
|
||||
rxjs: ">=7.0.0"
|
||||
checksum: 10/90cfee9860bc128190ec1357e554685892b3ddd080d914457da311f1d45294dfcc15a427be36c381463eefe39268b5abbc39e6b541ad402e78264cc6d038c23f
|
||||
checksum: 10/33e5b3f59b3b7a747a736f36183c77014214fa6e8048faac7a680dbba64833b1827dd7ef2e8c1ddf566a31829347449579ef6255811586b39914ca0510bb34a5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3248,7 +3248,7 @@ __metadata:
|
||||
tslib: "npm:2.8.1"
|
||||
typescript: "npm:5.9.2"
|
||||
peerDependencies:
|
||||
"@grafana/assistant": ^0.1.0
|
||||
"@grafana/assistant": ^0.1.1
|
||||
react: ^18.0.0
|
||||
react-dom: ^18.0.0
|
||||
languageName: unknown
|
||||
@@ -18844,7 +18844,7 @@ __metadata:
|
||||
"@glideapps/glide-data-grid": "npm:^6.0.0"
|
||||
"@grafana/alerting": "workspace:*"
|
||||
"@grafana/api-clients": "workspace:*"
|
||||
"@grafana/assistant": "npm:0.1.0"
|
||||
"@grafana/assistant": "npm:0.1.1"
|
||||
"@grafana/aws-sdk": "npm:0.7.1"
|
||||
"@grafana/azure-sdk": "npm:0.0.8"
|
||||
"@grafana/data": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user