diff --git a/public/app/features/search/page/components/ActionRow.tsx b/public/app/features/search/page/components/ActionRow.tsx index cd7399e4c0c..462bdae98b4 100644 --- a/public/app/features/search/page/components/ActionRow.tsx +++ b/public/app/features/search/page/components/ActionRow.tsx @@ -101,8 +101,14 @@ export const ActionRow: FC = ({ Datasource: {query.datasource} )} - {layout !== SearchLayout.Folders && config.featureToggles.panelTitleSearch && ( - setIncludePanels(!includePanels)} label="Include panels" /> + {config.featureToggles.panelTitleSearch && ( + setIncludePanels(!includePanels)} + label="Include panels" + /> )} diff --git a/public/app/features/search/page/components/SearchView.test.tsx b/public/app/features/search/page/components/SearchView.test.tsx index 0fefcbae7ba..885d1ec6118 100644 --- a/public/app/features/search/page/components/SearchView.test.tsx +++ b/public/app/features/search/page/components/SearchView.test.tsx @@ -6,16 +6,37 @@ import configureMockStore from 'redux-mock-store'; import { Observable } from 'rxjs'; import { ArrayVector, DataFrame, DataFrameView, FieldType } from '@grafana/data'; +import { config } from '@grafana/runtime'; +import { defaultQuery } from '../../reducers/searchQueryReducer'; import { DashboardQueryResult, getGrafanaSearcher, QueryResponse } from '../../service'; -import { DashboardSearchItemType } from '../../types'; +import { DashboardSearchItemType, SearchLayout } from '../../types'; import { SearchView, SearchViewProps } from './SearchView'; -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - reportInteraction: jest.fn(), -})); +jest.mock('@grafana/runtime', () => { + const originalModule = jest.requireActual('@grafana/runtime'); + return { + ...originalModule, + reportInteraction: jest.fn(), + config: { + ...originalModule.config, + featureToggles: { + panelTitleSearch: false, + }, + }, + }; +}); + +jest.mock('../../reducers/searchQueryReducer', () => { + const originalModule = jest.requireActual('../../reducers/searchQueryReducer'); + return { + ...originalModule, + defaultQuery: { + ...originalModule.defaultQuery, + }, + }; +}); describe('SearchView', () => { const folderData: DataFrame = { @@ -52,6 +73,11 @@ describe('SearchView', () => { jest.spyOn(getGrafanaSearcher(), 'search').mockResolvedValue(mockSearchResult); }); + beforeEach(() => { + config.featureToggles.panelTitleSearch = false; + defaultQuery.layout = SearchLayout.Folders; + }); + it('does not show checkboxes or manage actions if showManage is false', async () => { render(); await waitFor(() => expect(screen.queryAllByRole('checkbox')).toHaveLength(0)); @@ -88,4 +114,22 @@ describe('SearchView', () => { await waitFor(() => expect(screen.queryByText('No results found for your query.')).toBeInTheDocument()); expect(screen.getByRole('button', { name: 'Remove search constraints' })).toBeInTheDocument(); }); + + describe('include panels', () => { + it('should be enabled when layout is list', async () => { + config.featureToggles.panelTitleSearch = true; + defaultQuery.layout = SearchLayout.List; + render(); + + await waitFor(() => expect(screen.getByLabelText(/include panels/i)).toBeInTheDocument()); + expect(screen.getByTestId('include-panels')).toBeEnabled(); + }); + it('should be disabled when layout is folder', async () => { + config.featureToggles.panelTitleSearch = true; + render(); + + await waitFor(() => expect(screen.getByLabelText(/include panels/i)).toBeInTheDocument()); + expect(screen.getByTestId('include-panels')).toBeDisabled(); + }); + }); }); diff --git a/public/app/features/search/page/components/columns.tsx b/public/app/features/search/page/components/columns.tsx index 9381df6b15b..d99e0df6308 100644 --- a/public/app/features/search/page/components/columns.tsx +++ b/public/app/features/search/page/components/columns.tsx @@ -2,7 +2,14 @@ import { cx } from '@emotion/css'; import React from 'react'; import SVG from 'react-inlinesvg'; -import { Field, FieldType, formattedValueToString, getDisplayProcessor, getFieldDisplayName } from '@grafana/data'; +import { + DisplayProcessor, + Field, + FieldType, + formattedValueToString, + getDisplayProcessor, + getFieldDisplayName, +} from '@grafana/data'; import { config, getDataSourceSrv } from '@grafana/runtime'; import { Checkbox, Icon, IconButton, IconName, TagList } from '@grafana/ui'; import appEvents from 'app/core/app_events'; @@ -189,12 +196,18 @@ export const generateColumns = ( if (sortField && sortFieldWith) { const disp = sortField.display ?? getDisplayProcessor({ field: sortField, theme: config.theme2 }); + columns.push({ Header: () =>
{getFieldDisplayName(sortField)}
, Cell: (p) => { return (
- {formattedValueToString(disp(sortField.values.get(p.row.index)))} + {getDisplayValue({ + sortField, + getDisplay: disp, + index: p.row.index, + kind: access.kind, + })}
); }, @@ -392,3 +405,21 @@ function makeTagsColumn( width, }; } + +function getDisplayValue({ + kind, + sortField, + index, + getDisplay, +}: { + kind: Field; + sortField: Field; + index: number; + getDisplay: DisplayProcessor; +}) { + const value = sortField.values.get(index); + if (['folder', 'panel'].includes(kind.values.get(index)) && value === 0) { + return '-'; + } + return formattedValueToString(getDisplay(value)); +}