From da969e7d485c3d28b4a87d3d4693e870d1f760bf Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Fri, 13 Jan 2023 11:41:23 +0000 Subject: [PATCH] Command Palette: don't register dashboards as actions in the command palette (#61271) * don't register dashboards as actions in the command palette * create ActionImpls in RenderResults, memoize some array creation * extract dashboard results out into separate hook * remove unnecessary memoization from useActions * move useDashboardResults into dashboardActions --- .../commandPalette/CommandPalette.tsx | 35 +++++++++++++------ .../actions/dashboardActions.ts | 23 +++++++++--- .../commandPalette/actions/useActions.ts | 23 +++--------- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/public/app/features/commandPalette/CommandPalette.tsx b/public/app/features/commandPalette/CommandPalette.tsx index fd3808eee06..91b16bf54a0 100644 --- a/public/app/features/commandPalette/CommandPalette.tsx +++ b/public/app/features/commandPalette/CommandPalette.tsx @@ -12,20 +12,19 @@ import { VisualState, useRegisterActions, useKBar, + ActionImpl, } from 'kbar'; -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useMemo, useRef } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; +import { t } from 'app/core/internationalization'; import { ResultItem } from './ResultItem'; +import { useDashboardResults } from './actions/dashboardActions'; import useActions from './actions/useActions'; - -/** - * Wrap all the components from KBar here. - * @constructor - */ +import { CommandPaletteAction } from './types'; export const CommandPalette = () => { const styles = useStyles2(getSearchStyles); @@ -35,8 +34,9 @@ export const CommandPalette = () => { searchQuery: state.searchQuery, })); - const actions = useActions(searchQuery, showing); + const actions = useActions(); useRegisterActions(actions, [actions]); + const dashboardResults = useDashboardResults(searchQuery, showing); const ref = useRef(null); const { overlayProps } = useOverlay( @@ -57,7 +57,7 @@ export const CommandPalette = () => {
- +
@@ -66,14 +66,29 @@ export const CommandPalette = () => { ) : null; }; -const RenderResults = () => { +interface RenderResultsProps { + dashboardResults: CommandPaletteAction[]; +} + +const RenderResults = ({ dashboardResults }: RenderResultsProps) => { const { results, rootActionId } = useMatches(); const styles = useStyles2(getSearchStyles); + const dashboardsSectionTitle = t('command-palette.section.dashboard-search-results', 'Dashboards'); + // because dashboard search results aren't registered as actions, we need to manually + // convert them to ActionImpls before passing them as items to KBarResults + const dashboardResultItems = useMemo( + () => dashboardResults.map((dashboard) => new ActionImpl(dashboard, { store: {} })), + [dashboardResults] + ); + const items = useMemo( + () => (dashboardResultItems.length > 0 ? [...results, dashboardsSectionTitle, ...dashboardResultItems] : results), + [results, dashboardsSectionTitle, dashboardResultItems] + ); return (
typeof item === 'string' ? (
{item}
diff --git a/public/app/features/commandPalette/actions/dashboardActions.ts b/public/app/features/commandPalette/actions/dashboardActions.ts index 0fc75cb6e00..e230a2730cd 100644 --- a/public/app/features/commandPalette/actions/dashboardActions.ts +++ b/public/app/features/commandPalette/actions/dashboardActions.ts @@ -1,3 +1,6 @@ +import debounce from 'debounce-promise'; +import { useEffect, useState } from 'react'; + import { locationUtil } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { t } from 'app/core/internationalization'; @@ -10,6 +13,8 @@ import { RECENT_DASHBOARDS_PRORITY, SEARCH_RESULTS_PRORITY } from '../values'; const MAX_SEARCH_RESULTS = 100; const MAX_RECENT_DASHBOARDS = 5; +const debouncedDashboardSearch = debounce(getDashboardSearchResultActions, 200); + export async function getRecentDashboardActions(): Promise { const recentUids = (await impressionSrv.getDashboardOpened()).slice(0, MAX_RECENT_DASHBOARDS); const resultsDataFrame = await getGrafanaSearcher().search({ @@ -70,7 +75,17 @@ export async function getDashboardSearchResultActions(searchQuery: string): Prom return goToDashboardActions; } -// export default async (parentId: string) => { -// const dashboardNav = await getDashboardNav(parentId); -// return dashboardNav; -// }; +export function useDashboardResults(searchQuery: string, isShowing: boolean) { + const [dashboardResults, setDashboardResults] = useState([]); + + // Hit dashboards API + useEffect(() => { + if (isShowing && searchQuery.length > 0) { + debouncedDashboardSearch(searchQuery).then((resultActions) => { + setDashboardResults(resultActions); + }); + } + }, [isShowing, searchQuery]); + + return dashboardResults; +} diff --git a/public/app/features/commandPalette/actions/useActions.ts b/public/app/features/commandPalette/actions/useActions.ts index 8b5a88e7c97..7dc92ff601d 100644 --- a/public/app/features/commandPalette/actions/useActions.ts +++ b/public/app/features/commandPalette/actions/useActions.ts @@ -1,18 +1,14 @@ -import debounce from 'debounce-promise'; -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import { useSelector } from 'app/types'; import { CommandPaletteAction } from '../types'; -import { getDashboardSearchResultActions, getRecentDashboardActions } from './dashboardActions'; +import { getRecentDashboardActions } from './dashboardActions'; import getStaticActions from './staticActions'; -const debouncedDashboardSearch = debounce(getDashboardSearchResultActions, 200); - -export default function useActions(searchQuery: string, isShowing: boolean) { +export default function useActions() { const [staticActions, setStaticActions] = useState([]); - const [dashboardResultActions, setDashboardResultActions] = useState([]); const { navBarTree } = useSelector((state) => { return { @@ -35,16 +31,5 @@ export default function useActions(searchQuery: string, isShowing: boolean) { }); }, []); - // Hit dashboards API - useEffect(() => { - if (isShowing && searchQuery.length > 0) { - debouncedDashboardSearch(searchQuery).then((resultActions) => { - setDashboardResultActions(resultActions); - }); - } - }, [isShowing, searchQuery]); - - const actions = useMemo(() => [...staticActions, ...dashboardResultActions], [staticActions, dashboardResultActions]); - - return actions; + return staticActions; }