From 4dfab0b7d5f23323b74167b8c945f24f933fc2e7 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 1 Jun 2022 09:05:53 -0700 Subject: [PATCH] SearchV2: optionally exclude panels from search results (#49971) --- .../search/components/DashboardSearch.tsx | 17 ++++++++++++++--- .../search/components/ManageDashboardsNew.tsx | 13 +++++++++++-- public/app/features/search/constants.ts | 1 + .../search/page/components/ActionRow.tsx | 8 ++++++++ .../search/page/components/SearchView.tsx | 19 +++++++++++++++++-- 5 files changed, 51 insertions(+), 7 deletions(-) diff --git a/public/app/features/search/components/DashboardSearch.tsx b/public/app/features/search/components/DashboardSearch.tsx index 813f4329f63..51eb5316a47 100644 --- a/public/app/features/search/components/DashboardSearch.tsx +++ b/public/app/features/search/components/DashboardSearch.tsx @@ -1,11 +1,12 @@ import { css } from '@emotion/css'; import React, { FC, memo, useState } from 'react'; -import { useDebounce } from 'react-use'; +import { useDebounce, useLocalStorage } from 'react-use'; import { GrafanaTheme2 } from '@grafana/data'; import { config } from '@grafana/runtime'; import { CustomScrollbar, IconButton, stylesFactory, useStyles2, useTheme2 } from '@grafana/ui'; +import { SEARCH_PANELS_LOCAL_STORAGE_KEY } from '../constants'; import { useDashboardSearch } from '../hooks/useDashboardSearch'; import { useSearchQuery } from '../hooks/useSearchQuery'; import { SearchView } from '../page/components/SearchView'; @@ -31,6 +32,11 @@ function DashboardSearchNew({ onCloseSearch }: Props) { const styles = useStyles2(getStyles); const { query, onQueryChange } = useSearchQuery({}); + let [includePanels, setIncludePanels] = useLocalStorage(SEARCH_PANELS_LOCAL_STORAGE_KEY, true); + if (!config.featureToggles.panelTitleSearch) { + includePanels = false; + } + const [inputValue, setInputValue] = useState(query.query ?? ''); const onSearchQueryChange = (e: React.ChangeEvent) => { e.preventDefault(); @@ -45,7 +51,7 @@ function DashboardSearchNew({ onCloseSearch }: Props) {
- +
diff --git a/public/app/features/search/components/ManageDashboardsNew.tsx b/public/app/features/search/components/ManageDashboardsNew.tsx index 22468b9fc1f..5e591176c99 100644 --- a/public/app/features/search/components/ManageDashboardsNew.tsx +++ b/public/app/features/search/components/ManageDashboardsNew.tsx @@ -1,12 +1,14 @@ import { css, cx } from '@emotion/css'; import React, { useState } from 'react'; -import { useDebounce } from 'react-use'; +import { useDebounce, useLocalStorage } from 'react-use'; import { GrafanaTheme2 } from '@grafana/data'; +import { config } from '@grafana/runtime'; import { Input, useStyles2, Spinner } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; import { FolderDTO } from 'app/types'; +import { SEARCH_PANELS_LOCAL_STORAGE_KEY } from '../constants'; import { useSearchQuery } from '../hooks/useSearchQuery'; import { SearchView } from '../page/components/SearchView'; @@ -27,6 +29,11 @@ export const ManageDashboardsNew = React.memo(({ folder }: Props) => { const canSave = folder?.canSave; const hasEditPermissionInFolders = folder ? canSave : contextSrv.hasEditPermissionInFolders; + let [includePanels, setIncludePanels] = useLocalStorage(SEARCH_PANELS_LOCAL_STORAGE_KEY, true); + if (!config.featureToggles.panelTitleSearch) { + includePanels = false; + } + const { isEditor } = contextSrv; const [inputValue, setInputValue] = useState(query.query ?? ''); @@ -45,7 +52,7 @@ export const ManageDashboardsNew = React.memo(({ folder }: Props) => { onChange={onSearchQueryChange} autoFocus spellCheck={false} - placeholder="Search for dashboards and panels" + placeholder={includePanels ? 'Search for dashboards and panels' : 'Search for dashboards'} className={styles.searchInput} suffix={false ? : null} /> @@ -58,6 +65,8 @@ export const ManageDashboardsNew = React.memo(({ folder }: Props) => { folderDTO={folder} queryText={query.query} hidePseudoFolders={true} + includePanels={includePanels!} + setIncludePanels={setIncludePanels} /> ); diff --git a/public/app/features/search/constants.ts b/public/app/features/search/constants.ts index 1ae5fcc8254..1ba8a9056aa 100644 --- a/public/app/features/search/constants.ts +++ b/public/app/features/search/constants.ts @@ -8,3 +8,4 @@ export const GENERAL_FOLDER_ID = 0; export const GENERAL_FOLDER_UID = 'general'; export const GENERAL_FOLDER_TITLE = 'General'; export const PREVIEWS_LOCAL_STORAGE_KEY = 'grafana.dashboard.previews'; +export const SEARCH_PANELS_LOCAL_STORAGE_KEY = 'grafana.search.include.panels'; diff --git a/public/app/features/search/page/components/ActionRow.tsx b/public/app/features/search/page/components/ActionRow.tsx index 091a057d2a2..6d974bc1747 100644 --- a/public/app/features/search/page/components/ActionRow.tsx +++ b/public/app/features/search/page/components/ActionRow.tsx @@ -26,6 +26,8 @@ interface Props { getTagOptions: () => Promise; getSortOptions: () => Promise; onDatasourceChange: (ds?: string) => void; + includePanels: boolean; + setIncludePanels: (v: boolean) => void; query: DashboardQuery; showStarredFilter?: boolean; hideLayout?: boolean; @@ -58,6 +60,8 @@ export const ActionRow: FC = ({ query, showStarredFilter, hideLayout, + includePanels, + setIncludePanels, }) => { const styles = useStyles2(getStyles); const layout = getValidQueryLayout(query); @@ -91,6 +95,10 @@ export const ActionRow: FC = ({ Datasource: {query.datasource} )} + {layout !== SearchLayout.Folders && ( + setIncludePanels(!includePanels)} label="Include panels" /> + )} + diff --git a/public/app/features/search/page/components/SearchView.tsx b/public/app/features/search/page/components/SearchView.tsx index 45e0ac95f3a..78344228c11 100644 --- a/public/app/features/search/page/components/SearchView.tsx +++ b/public/app/features/search/page/components/SearchView.tsx @@ -27,9 +27,18 @@ type SearchViewProps = { showManage: boolean; folderDTO?: FolderDTO; hidePseudoFolders?: boolean; // Recent + starred + includePanels: boolean; + setIncludePanels: (v: boolean) => void; }; -export const SearchView = ({ showManage, folderDTO, queryText, hidePseudoFolders }: SearchViewProps) => { +export const SearchView = ({ + showManage, + folderDTO, + queryText, + hidePseudoFolders, + includePanels, + setIncludePanels, +}: SearchViewProps) => { const styles = useStyles2(getStyles); const { query, onQueryChange, onTagFilterChange, onTagAdd, onDatasourceChange, onSortChange, onLayoutChange } = @@ -61,11 +70,15 @@ export const SearchView = ({ showManage, folderDTO, queryText, hidePseudoFolders } } + if (!includePanels && !q.kind) { + q.kind = ['dashboard', 'folder']; // skip panels + } + if (q.query === '*' && !q.sort?.length) { q.sort = 'name_sort'; } return q; - }, [query, queryText, folderDTO]); + }, [query, queryText, folderDTO, includePanels]); const results = useAsync(() => { return getGrafanaSearcher().search(searchQuery); @@ -208,6 +221,8 @@ export const SearchView = ({ showManage, folderDTO, queryText, hidePseudoFolders getSortOptions={getGrafanaSearcher().getSortOptions} onDatasourceChange={onDatasourceChange} query={query} + includePanels={includePanels!} + setIncludePanels={setIncludePanels} /> )}