mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Search: Fixes searching by current folder when opened by clicking dashboard folder name (#57716)
* Search: Read from url on mount no on app boot * Fixed tests * Remove unused type
This commit is contained in:
parent
1f7c84f125
commit
3991be4c1d
@ -349,7 +349,7 @@ export const DashNav = React.memo<Props>((props) => {
|
||||
// this ensures the component rerenders when the location changes
|
||||
const location = useLocation();
|
||||
const titleHref = locationUtil.getUrlForPartial(location, { search: 'open' });
|
||||
const parentHref = locationUtil.getUrlForPartial(location, { search: 'open', folder: 'current' });
|
||||
const parentHref = locationUtil.getUrlForPartial(location, { search: 'open', query: 'folder:current' });
|
||||
const onGoBack = isFullscreen ? onClose : undefined;
|
||||
|
||||
if (config.featureToggles.topnav) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { debounce } from 'lodash';
|
||||
import { FormEvent } from 'react';
|
||||
import { FormEvent, useEffect } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
@ -16,6 +16,7 @@ import {
|
||||
clearFilters,
|
||||
toggleSort,
|
||||
layoutChange,
|
||||
initStateFromUrl,
|
||||
} from '../reducers/searchQueryReducer';
|
||||
import { DashboardQuery, SearchLayout } from '../types';
|
||||
import { hasFilters } from '../utils';
|
||||
@ -26,6 +27,10 @@ export const useSearchQuery = (defaults: Partial<DashboardQuery>) => {
|
||||
const query = useSelector((state) => state.searchQuery);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(initStateFromUrl(locationService.getSearchObject()));
|
||||
}, [dispatch]);
|
||||
|
||||
const onQueryChange = (query: string) => {
|
||||
dispatch(queryChange(query));
|
||||
updateLocation({ query });
|
||||
|
@ -7,11 +7,10 @@ import { Observable } from 'rxjs';
|
||||
|
||||
import { ArrayVector, DataFrame, DataFrameView, FieldType } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { StoreState } from 'app/types';
|
||||
|
||||
import { defaultQuery } from '../../reducers/searchQueryReducer';
|
||||
import { initialState } from '../../reducers/searchQueryReducer';
|
||||
import { DashboardQueryResult, getGrafanaSearcher, QueryResponse } from '../../service';
|
||||
import { DashboardSearchItemType, SearchLayout } from '../../types';
|
||||
import { DashboardQuery, DashboardSearchItemType, SearchLayout } from '../../types';
|
||||
|
||||
import { SearchView, SearchViewProps } from './SearchView';
|
||||
|
||||
@ -29,7 +28,7 @@ jest.mock('@grafana/runtime', () => {
|
||||
};
|
||||
});
|
||||
|
||||
const setup = (propOverrides?: Partial<SearchViewProps>, storeOverrides?: Partial<StoreState>) => {
|
||||
const setup = (propOverrides?: Partial<SearchViewProps>, storeOverrides?: Partial<DashboardQuery>) => {
|
||||
const props: SearchViewProps = {
|
||||
showManage: false,
|
||||
includePanels: false,
|
||||
@ -39,7 +38,7 @@ const setup = (propOverrides?: Partial<SearchViewProps>, storeOverrides?: Partia
|
||||
};
|
||||
|
||||
const mockStore = configureMockStore();
|
||||
const store = mockStore({ searchQuery: defaultQuery, ...storeOverrides });
|
||||
const store = mockStore({ searchQuery: { ...initialState, ...storeOverrides } });
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<SearchView {...props} />
|
||||
@ -75,22 +74,21 @@ describe('SearchView', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
config.featureToggles.panelTitleSearch = false;
|
||||
defaultQuery.layout = SearchLayout.Folders;
|
||||
});
|
||||
|
||||
it('does not show checkboxes or manage actions if showManage is false', async () => {
|
||||
setup();
|
||||
setup({}, { layout: SearchLayout.Folders });
|
||||
await waitFor(() => expect(screen.queryAllByRole('checkbox')).toHaveLength(0));
|
||||
expect(screen.queryByTestId('manage-actions')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows checkboxes if showManage is true', async () => {
|
||||
setup({ showManage: true });
|
||||
setup({ showManage: true }, { layout: SearchLayout.Folders });
|
||||
await waitFor(() => expect(screen.queryAllByRole('checkbox')).toHaveLength(2));
|
||||
});
|
||||
|
||||
it('shows the manage actions if show manage is true and the user clicked a checkbox', async () => {
|
||||
setup({ showManage: true });
|
||||
setup({ showManage: true }, { layout: SearchLayout.Folders });
|
||||
await waitFor(() => userEvent.click(screen.getAllByRole('checkbox')[0]));
|
||||
|
||||
expect(screen.queryByTestId('manage-actions')).toBeInTheDocument();
|
||||
@ -103,10 +101,8 @@ describe('SearchView', () => {
|
||||
view: new DataFrameView<DashboardQueryResult>({ fields: [], length: 0 }),
|
||||
});
|
||||
setup(undefined, {
|
||||
searchQuery: {
|
||||
...defaultQuery,
|
||||
query: 'asdfasdfasdf',
|
||||
},
|
||||
query: 'asdfasdfasdf',
|
||||
layout: SearchLayout.Folders,
|
||||
});
|
||||
await waitFor(() => expect(screen.queryByText('No results found for your query.')).toBeInTheDocument());
|
||||
expect(screen.getByRole('button', { name: 'Clear search and filters' })).toBeInTheDocument();
|
||||
@ -115,15 +111,15 @@ describe('SearchView', () => {
|
||||
describe('include panels', () => {
|
||||
it('should be enabled when layout is list', async () => {
|
||||
config.featureToggles.panelTitleSearch = true;
|
||||
defaultQuery.layout = SearchLayout.List;
|
||||
setup();
|
||||
setup({}, { layout: SearchLayout.List });
|
||||
|
||||
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;
|
||||
setup();
|
||||
setup({}, { layout: SearchLayout.Folders });
|
||||
|
||||
await waitFor(() => expect(screen.getByLabelText(/include panels/i)).toBeInTheDocument());
|
||||
expect(screen.getByTestId('include-panels')).toBeDisabled();
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { SelectableValue, UrlQueryMap } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
|
||||
import { SEARCH_SELECTED_LAYOUT } from '../constants';
|
||||
import { DashboardQuery, SearchQueryParams, SearchLayout } from '../types';
|
||||
import { DashboardQuery, SearchLayout, SearchQueryParams } from '../types';
|
||||
import { parseRouteParams } from '../utils';
|
||||
|
||||
export const defaultQuery: DashboardQuery = {
|
||||
export const initialState: DashboardQuery = {
|
||||
query: '',
|
||||
tag: [],
|
||||
starred: false,
|
||||
sort: null,
|
||||
starred: false,
|
||||
layout: SearchLayout.Folders,
|
||||
prevSort: null,
|
||||
};
|
||||
@ -25,8 +25,8 @@ export const defaultQueryParams: SearchQueryParams = {
|
||||
};
|
||||
|
||||
const queryParams = parseRouteParams(locationService.getSearchObject());
|
||||
const initialState = { ...defaultQuery, ...queryParams };
|
||||
const selectedLayout = localStorage.getItem(SEARCH_SELECTED_LAYOUT) as SearchLayout;
|
||||
|
||||
if (!queryParams.layout?.length && selectedLayout?.length) {
|
||||
initialState.layout = selectedLayout;
|
||||
}
|
||||
@ -35,6 +35,10 @@ const searchQuerySlice = createSlice({
|
||||
name: 'searchQuery',
|
||||
initialState,
|
||||
reducers: {
|
||||
initStateFromUrl(state, action: PayloadAction<UrlQueryMap>) {
|
||||
const queryParams = parseRouteParams(action.payload);
|
||||
Object.assign(state, queryParams);
|
||||
},
|
||||
queryChange: (state, action: PayloadAction<string>) => {
|
||||
state.query = action.payload;
|
||||
},
|
||||
@ -99,6 +103,7 @@ export const {
|
||||
clearFilters,
|
||||
toggleSort,
|
||||
layoutChange,
|
||||
initStateFromUrl,
|
||||
} = searchQuerySlice.actions;
|
||||
export const searchQueryReducer = searchQuerySlice.reducer;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user