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
pull/61529/head
Ashley Harrison 2 years ago committed by GitHub
parent 017d4f2cbb
commit da969e7d48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 35
      public/app/features/commandPalette/CommandPalette.tsx
  2. 23
      public/app/features/commandPalette/actions/dashboardActions.ts
  3. 23
      public/app/features/commandPalette/actions/useActions.ts

@ -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<HTMLDivElement>(null);
const { overlayProps } = useOverlay(
@ -57,7 +57,7 @@ export const CommandPalette = () => {
<FocusScope contain autoFocus restoreFocus>
<div {...overlayProps} {...dialogProps}>
<KBarSearch className={styles.search} />
<RenderResults />
<RenderResults dashboardResults={dashboardResults} />
</div>
</FocusScope>
</KBarAnimator>
@ -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 (
<div className={styles.resultsContainer}>
<KBarResults
items={results}
items={items}
onRender={({ item, active }) =>
typeof item === 'string' ? (
<div className={styles.sectionHeader}>{item}</div>

@ -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<CommandPaletteAction[]> {
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<CommandPaletteAction[]>([]);
// Hit dashboards API
useEffect(() => {
if (isShowing && searchQuery.length > 0) {
debouncedDashboardSearch(searchQuery).then((resultActions) => {
setDashboardResults(resultActions);
});
}
}, [isShowing, searchQuery]);
return dashboardResults;
}

@ -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<CommandPaletteAction[]>([]);
const [dashboardResultActions, setDashboardResultActions] = useState<CommandPaletteAction[]>([]);
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;
}

Loading…
Cancel
Save