mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SearchV2: Add minor UX improvements to Search pages (#52833)
* Search: display dash for panel and folder when sort type is view or error * Search: Disabled panel checkbox in folrder view
This commit is contained in:
@@ -101,8 +101,14 @@ export const ActionRow: FC<Props> = ({
|
||||
Datasource: {query.datasource}
|
||||
</Button>
|
||||
)}
|
||||
{layout !== SearchLayout.Folders && config.featureToggles.panelTitleSearch && (
|
||||
<Checkbox value={includePanels} onChange={() => setIncludePanels(!includePanels)} label="Include panels" />
|
||||
{config.featureToggles.panelTitleSearch && (
|
||||
<Checkbox
|
||||
data-testid="include-panels"
|
||||
disabled={layout === SearchLayout.Folders}
|
||||
value={includePanels}
|
||||
onChange={() => setIncludePanels(!includePanels)}
|
||||
label="Include panels"
|
||||
/>
|
||||
)}
|
||||
|
||||
<TagFilter isClearable tags={query.tag} tagOptions={getTagOptions} onChange={onTagFilterChange} />
|
||||
|
||||
@@ -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(<SearchView {...baseProps} />);
|
||||
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(<SearchView {...baseProps} />);
|
||||
|
||||
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(<SearchView {...baseProps} />);
|
||||
|
||||
await waitFor(() => expect(screen.getByLabelText(/include panels/i)).toBeInTheDocument());
|
||||
expect(screen.getByTestId('include-panels')).toBeDisabled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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: () => <div className={styles.sortedHeader}>{getFieldDisplayName(sortField)}</div>,
|
||||
Cell: (p) => {
|
||||
return (
|
||||
<div {...p.cellProps} className={styles.sortedItems}>
|
||||
{formattedValueToString(disp(sortField.values.get(p.row.index)))}
|
||||
{getDisplayValue({
|
||||
sortField,
|
||||
getDisplay: disp,
|
||||
index: p.row.index,
|
||||
kind: access.kind,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user