mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Search: Store only search value in state, not the whole selectable value (#62228)
* Search: Store only search value in state, not the whole selectable value * type sort to undefined-able
This commit is contained in:
parent
6292a41b24
commit
70f109526a
@ -4585,8 +4585,7 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||||
],
|
],
|
||||||
"public/app/features/search/utils.ts:5381": [
|
"public/app/features/search/utils.ts:5381": [
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
|
||||||
],
|
],
|
||||||
"public/app/features/serviceaccounts/ServiceAccountPage.test.tsx:5381": [
|
"public/app/features/serviceaccounts/ServiceAccountPage.test.tsx:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
|
@ -20,7 +20,7 @@ if (config.featureToggles.dashboardPreviews) {
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onLayoutChange: (layout: SearchLayout) => void;
|
onLayoutChange: (layout: SearchLayout) => void;
|
||||||
onSortChange: (value: SelectableValue) => void;
|
onSortChange: (value?: string) => void;
|
||||||
onStarredFilterChange?: (event: FormEvent<HTMLInputElement>) => void;
|
onStarredFilterChange?: (event: FormEvent<HTMLInputElement>) => void;
|
||||||
onTagFilterChange: (tags: string[]) => void;
|
onTagFilterChange: (tags: string[]) => void;
|
||||||
getTagOptions: () => Promise<TermCount[]>;
|
getTagOptions: () => Promise<TermCount[]>;
|
||||||
@ -106,8 +106,8 @@ export const ActionRow: FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<SortPicker
|
<SortPicker
|
||||||
onChange={onSortChange}
|
onChange={(change) => onSortChange(change.value)}
|
||||||
value={state.sort?.value}
|
value={state.sort}
|
||||||
getSortOptions={getSortOptions}
|
getSortOptions={getSortOptions}
|
||||||
placeholder={sortPlaceholder}
|
placeholder={sortPlaceholder}
|
||||||
isClearable
|
isClearable
|
||||||
|
@ -6,7 +6,7 @@ import { EventTrackingNamespace, SearchLayout } from '../types';
|
|||||||
interface QueryProps {
|
interface QueryProps {
|
||||||
layout: SearchLayout;
|
layout: SearchLayout;
|
||||||
starred: boolean;
|
starred: boolean;
|
||||||
sortValue: string;
|
sortValue?: string;
|
||||||
query: string;
|
query: string;
|
||||||
tagCount: number;
|
tagCount: number;
|
||||||
includePanels?: boolean;
|
includePanels?: boolean;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { FormEvent } from 'react';
|
import { FormEvent } from 'react';
|
||||||
|
|
||||||
import { SelectableValue } from '@grafana/data';
|
|
||||||
import { locationService } from '@grafana/runtime';
|
import { locationService } from '@grafana/runtime';
|
||||||
import { TermCount } from 'app/core/components/TagFilter/TagFilter';
|
import { TermCount } from 'app/core/components/TagFilter/TagFilter';
|
||||||
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
||||||
@ -21,10 +20,10 @@ import { parseRouteParams } from '../utils';
|
|||||||
export const initialState: SearchState = {
|
export const initialState: SearchState = {
|
||||||
query: '',
|
query: '',
|
||||||
tag: [],
|
tag: [],
|
||||||
sort: null,
|
|
||||||
starred: false,
|
starred: false,
|
||||||
layout: SearchLayout.Folders,
|
layout: SearchLayout.Folders,
|
||||||
prevSort: null,
|
sort: undefined,
|
||||||
|
prevSort: undefined,
|
||||||
eventTrackingNamespace: 'dashboard_search',
|
eventTrackingNamespace: 'dashboard_search',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
this.setStateAndDoSearch({ starred: false });
|
this.setStateAndDoSearch({ starred: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
onSortChange = (sort: SelectableValue | null) => {
|
onSortChange = (sort: string | undefined) => {
|
||||||
if (this.state.layout === SearchLayout.Folders) {
|
if (this.state.layout === SearchLayout.Folders) {
|
||||||
this.setStateAndDoSearch({ sort, layout: SearchLayout.List });
|
this.setStateAndDoSearch({ sort, layout: SearchLayout.List });
|
||||||
} else {
|
} else {
|
||||||
@ -125,7 +124,7 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
localStorage.setItem(SEARCH_SELECTED_LAYOUT, layout);
|
localStorage.setItem(SEARCH_SELECTED_LAYOUT, layout);
|
||||||
|
|
||||||
if (this.state.sort && layout === SearchLayout.Folders) {
|
if (this.state.sort && layout === SearchLayout.Folders) {
|
||||||
this.setStateAndDoSearch({ layout, prevSort: this.state.sort, sort: null });
|
this.setStateAndDoSearch({ layout, prevSort: this.state.sort, sort: undefined });
|
||||||
} else {
|
} else {
|
||||||
this.setStateAndDoSearch({ layout, sort: this.state.prevSort });
|
this.setStateAndDoSearch({ layout, sort: this.state.prevSort });
|
||||||
}
|
}
|
||||||
@ -146,7 +145,7 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
tags: this.state.tag as string[],
|
tags: this.state.tag as string[],
|
||||||
ds_uid: this.state.datasource as string,
|
ds_uid: this.state.datasource as string,
|
||||||
location: this.state.folderUid, // This will scope all results to the prefix
|
location: this.state.folderUid, // This will scope all results to the prefix
|
||||||
sort: this.state.sort?.value,
|
sort: this.state.sort,
|
||||||
explain: this.state.explain,
|
explain: this.state.explain,
|
||||||
withAllowedActions: this.state.explain, // allowedActions are currently not used for anything on the UI and added only in `explain` mode
|
withAllowedActions: this.state.explain, // allowedActions are currently not used for anything on the UI and added only in `explain` mode
|
||||||
starred: this.state.starred,
|
starred: this.state.starred,
|
||||||
@ -179,7 +178,7 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
const trackingInfo = {
|
const trackingInfo = {
|
||||||
layout: this.state.layout,
|
layout: this.state.layout,
|
||||||
starred: this.state.starred,
|
starred: this.state.starred,
|
||||||
sortValue: this.state.sort?.value,
|
sortValue: this.state.sort,
|
||||||
query: this.state.query,
|
query: this.state.query,
|
||||||
tagCount: this.state.tag?.length,
|
tagCount: this.state.tag?.length,
|
||||||
includePanels: this.state.includePanels,
|
includePanels: this.state.includePanels,
|
||||||
@ -227,13 +226,13 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
onSearchItemClicked = (e: React.MouseEvent<HTMLElement>) => {
|
onSearchItemClicked = (e: React.MouseEvent<HTMLElement>) => {
|
||||||
// Clear some filters only if we're not opening a search item in a new tab
|
// Clear some filters only if we're not opening a search item in a new tab
|
||||||
if (!e.altKey && !e.ctrlKey && !e.metaKey) {
|
if (!e.altKey && !e.ctrlKey && !e.metaKey) {
|
||||||
this.setState({ tag: [], starred: false, sort: null, query: '', folderUid: undefined });
|
this.setState({ tag: [], starred: false, sort: undefined, query: '', folderUid: undefined });
|
||||||
}
|
}
|
||||||
|
|
||||||
reportSearchResultInteraction(this.state.eventTrackingNamespace, {
|
reportSearchResultInteraction(this.state.eventTrackingNamespace, {
|
||||||
layout: this.state.layout,
|
layout: this.state.layout,
|
||||||
starred: this.state.starred,
|
starred: this.state.starred,
|
||||||
sortValue: this.state.sort?.value,
|
sortValue: this.state.sort,
|
||||||
query: this.state.query,
|
query: this.state.query,
|
||||||
tagCount: this.state.tag?.length,
|
tagCount: this.state.tag?.length,
|
||||||
includePanels: this.state.includePanels,
|
includePanels: this.state.includePanels,
|
||||||
@ -247,7 +246,7 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
|
|||||||
reportDashboardListViewed(this.state.eventTrackingNamespace, {
|
reportDashboardListViewed(this.state.eventTrackingNamespace, {
|
||||||
layout: this.state.layout,
|
layout: this.state.layout,
|
||||||
starred: this.state.starred,
|
starred: this.state.starred,
|
||||||
sortValue: this.state.sort?.value,
|
sortValue: this.state.sort,
|
||||||
query: this.state.query,
|
query: this.state.query,
|
||||||
tagCount: this.state.tag?.length,
|
tagCount: this.state.tag?.length,
|
||||||
includePanels: this.state.includePanels,
|
includePanels: this.state.includePanels,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Action } from 'redux';
|
import { Action } from 'redux';
|
||||||
|
|
||||||
import { SelectableValue, WithAccessControlMetadata } from '@grafana/data';
|
import { WithAccessControlMetadata } from '@grafana/data';
|
||||||
|
|
||||||
import { QueryResponse } from './service';
|
import { QueryResponse } from './service';
|
||||||
|
|
||||||
@ -78,9 +78,8 @@ export interface SearchState {
|
|||||||
starred: boolean;
|
starred: boolean;
|
||||||
explain?: boolean; // adds debug info
|
explain?: boolean; // adds debug info
|
||||||
datasource?: string;
|
datasource?: string;
|
||||||
sort: SelectableValue | null;
|
sort?: string;
|
||||||
// Save sorting data between layouts
|
prevSort?: string; // Save sorting data between layouts
|
||||||
prevSort: SelectableValue | null;
|
|
||||||
layout: SearchLayout;
|
layout: SearchLayout;
|
||||||
result?: QueryResponse;
|
result?: QueryResponse;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
|
@ -12,7 +12,6 @@ describe('Search utils', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return tag as array, if present', () => {
|
it('should return tag as array, if present', () => {
|
||||||
//@ts-ignore
|
|
||||||
const params = { sort: undefined, tag: 'test', query: 'test' };
|
const params = { sort: undefined, tag: 'test', query: 'test' };
|
||||||
expect(parseRouteParams(params)).toEqual({
|
expect(parseRouteParams(params)).toEqual({
|
||||||
query: 'test',
|
query: 'test',
|
||||||
@ -26,14 +25,6 @@ describe('Search utils', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return sort as a SelectableValue', () => {
|
|
||||||
const params: Partial<SearchQueryParams> = { sort: 'test' };
|
|
||||||
|
|
||||||
expect(parseRouteParams(params)).toEqual({
|
|
||||||
sort: { value: 'test' },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should prepend folder:{folder} to the query if folder is present', () => {
|
it('should prepend folder:{folder} to the query if folder is present', () => {
|
||||||
expect(parseRouteParams({ folder: 'current' })).toEqual({
|
expect(parseRouteParams({ folder: 'current' })).toEqual({
|
||||||
folder: 'current',
|
folder: 'current',
|
||||||
|
@ -28,16 +28,15 @@ export const getSectionStorageKey = (title = 'General') => {
|
|||||||
* @param folder
|
* @param folder
|
||||||
*/
|
*/
|
||||||
export const parseRouteParams = (params: UrlQueryMap) => {
|
export const parseRouteParams = (params: UrlQueryMap) => {
|
||||||
const cleanedParams = Object.entries(params).reduce((obj, [key, val]) => {
|
const cleanedParams = Object.entries(params).reduce<Partial<SearchState>>((obj, [key, val]) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
return obj;
|
return obj;
|
||||||
} else if (key === 'tag' && !Array.isArray(val)) {
|
} else if (key === 'tag' && !Array.isArray(val)) {
|
||||||
return { ...obj, tag: [val] as string[] };
|
return { ...obj, tag: [val] as string[] };
|
||||||
} else if (key === 'sort') {
|
|
||||||
return { ...obj, sort: { value: val } };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...obj, [key]: val };
|
return { ...obj, [key]: val };
|
||||||
}, {} as Partial<SearchState>);
|
}, {});
|
||||||
|
|
||||||
if (params.folder) {
|
if (params.folder) {
|
||||||
const folderStr = `folder:${params.folder}`;
|
const folderStr = `folder:${params.folder}`;
|
||||||
|
Loading…
Reference in New Issue
Block a user