From 70f109526a3697ca9b71d99ed2f15d71cc3f49ac Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Fri, 27 Jan 2023 10:50:48 +0000 Subject: [PATCH] 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 --- .betterer.results | 3 +-- .../search/page/components/ActionRow.tsx | 6 +++--- public/app/features/search/page/reporting.ts | 2 +- .../search/state/SearchStateManager.ts | 19 +++++++++---------- public/app/features/search/types.ts | 7 +++---- public/app/features/search/utils.test.ts | 9 --------- public/app/features/search/utils.ts | 7 +++---- 7 files changed, 20 insertions(+), 33 deletions(-) diff --git a/.betterer.results b/.betterer.results index 19cfd61c989..2a789546b7a 100644 --- a/.betterer.results +++ b/.betterer.results @@ -4585,8 +4585,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "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.", "1"] + [0, 0, 0, "Do not use any type assertions.", "0"] ], "public/app/features/serviceaccounts/ServiceAccountPage.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], diff --git a/public/app/features/search/page/components/ActionRow.tsx b/public/app/features/search/page/components/ActionRow.tsx index 415941bdbb0..27fe51c9ab5 100644 --- a/public/app/features/search/page/components/ActionRow.tsx +++ b/public/app/features/search/page/components/ActionRow.tsx @@ -20,7 +20,7 @@ if (config.featureToggles.dashboardPreviews) { interface Props { onLayoutChange: (layout: SearchLayout) => void; - onSortChange: (value: SelectableValue) => void; + onSortChange: (value?: string) => void; onStarredFilterChange?: (event: FormEvent) => void; onTagFilterChange: (tags: string[]) => void; getTagOptions: () => Promise; @@ -106,8 +106,8 @@ export const ActionRow: FC = ({ /> )} onSortChange(change.value)} + value={state.sort} getSortOptions={getSortOptions} placeholder={sortPlaceholder} isClearable diff --git a/public/app/features/search/page/reporting.ts b/public/app/features/search/page/reporting.ts index 083a340b49e..9c708ac069f 100644 --- a/public/app/features/search/page/reporting.ts +++ b/public/app/features/search/page/reporting.ts @@ -6,7 +6,7 @@ import { EventTrackingNamespace, SearchLayout } from '../types'; interface QueryProps { layout: SearchLayout; starred: boolean; - sortValue: string; + sortValue?: string; query: string; tagCount: number; includePanels?: boolean; diff --git a/public/app/features/search/state/SearchStateManager.ts b/public/app/features/search/state/SearchStateManager.ts index e04ae3106c7..f376021bc61 100644 --- a/public/app/features/search/state/SearchStateManager.ts +++ b/public/app/features/search/state/SearchStateManager.ts @@ -1,7 +1,6 @@ import { debounce } from 'lodash'; import { FormEvent } from 'react'; -import { SelectableValue } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { TermCount } from 'app/core/components/TagFilter/TagFilter'; import { StateManagerBase } from 'app/core/services/StateManagerBase'; @@ -21,10 +20,10 @@ import { parseRouteParams } from '../utils'; export const initialState: SearchState = { query: '', tag: [], - sort: null, starred: false, layout: SearchLayout.Folders, - prevSort: null, + sort: undefined, + prevSort: undefined, eventTrackingNamespace: 'dashboard_search', }; @@ -113,7 +112,7 @@ export class SearchStateManager extends StateManagerBase { this.setStateAndDoSearch({ starred: false }); }; - onSortChange = (sort: SelectableValue | null) => { + onSortChange = (sort: string | undefined) => { if (this.state.layout === SearchLayout.Folders) { this.setStateAndDoSearch({ sort, layout: SearchLayout.List }); } else { @@ -125,7 +124,7 @@ export class SearchStateManager extends StateManagerBase { localStorage.setItem(SEARCH_SELECTED_LAYOUT, layout); 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 { this.setStateAndDoSearch({ layout, sort: this.state.prevSort }); } @@ -146,7 +145,7 @@ export class SearchStateManager extends StateManagerBase { tags: this.state.tag as string[], ds_uid: this.state.datasource as string, 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, withAllowedActions: this.state.explain, // allowedActions are currently not used for anything on the UI and added only in `explain` mode starred: this.state.starred, @@ -179,7 +178,7 @@ export class SearchStateManager extends StateManagerBase { const trackingInfo = { layout: this.state.layout, starred: this.state.starred, - sortValue: this.state.sort?.value, + sortValue: this.state.sort, query: this.state.query, tagCount: this.state.tag?.length, includePanels: this.state.includePanels, @@ -227,13 +226,13 @@ export class SearchStateManager extends StateManagerBase { onSearchItemClicked = (e: React.MouseEvent) => { // Clear some filters only if we're not opening a search item in a new tab 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, { layout: this.state.layout, starred: this.state.starred, - sortValue: this.state.sort?.value, + sortValue: this.state.sort, query: this.state.query, tagCount: this.state.tag?.length, includePanels: this.state.includePanels, @@ -247,7 +246,7 @@ export class SearchStateManager extends StateManagerBase { reportDashboardListViewed(this.state.eventTrackingNamespace, { layout: this.state.layout, starred: this.state.starred, - sortValue: this.state.sort?.value, + sortValue: this.state.sort, query: this.state.query, tagCount: this.state.tag?.length, includePanels: this.state.includePanels, diff --git a/public/app/features/search/types.ts b/public/app/features/search/types.ts index a63ef7960a5..ac8f930f094 100644 --- a/public/app/features/search/types.ts +++ b/public/app/features/search/types.ts @@ -1,6 +1,6 @@ import { Action } from 'redux'; -import { SelectableValue, WithAccessControlMetadata } from '@grafana/data'; +import { WithAccessControlMetadata } from '@grafana/data'; import { QueryResponse } from './service'; @@ -78,9 +78,8 @@ export interface SearchState { starred: boolean; explain?: boolean; // adds debug info datasource?: string; - sort: SelectableValue | null; - // Save sorting data between layouts - prevSort: SelectableValue | null; + sort?: string; + prevSort?: string; // Save sorting data between layouts layout: SearchLayout; result?: QueryResponse; loading?: boolean; diff --git a/public/app/features/search/utils.test.ts b/public/app/features/search/utils.test.ts index 209c9450855..152d5647956 100644 --- a/public/app/features/search/utils.test.ts +++ b/public/app/features/search/utils.test.ts @@ -12,7 +12,6 @@ describe('Search utils', () => { }); it('should return tag as array, if present', () => { - //@ts-ignore const params = { sort: undefined, tag: 'test', query: 'test' }; expect(parseRouteParams(params)).toEqual({ query: 'test', @@ -26,14 +25,6 @@ describe('Search utils', () => { }); }); - it('should return sort as a SelectableValue', () => { - const params: Partial = { sort: 'test' }; - - expect(parseRouteParams(params)).toEqual({ - sort: { value: 'test' }, - }); - }); - it('should prepend folder:{folder} to the query if folder is present', () => { expect(parseRouteParams({ folder: 'current' })).toEqual({ folder: 'current', diff --git a/public/app/features/search/utils.ts b/public/app/features/search/utils.ts index ea5ed3ea274..7c942ec1174 100644 --- a/public/app/features/search/utils.ts +++ b/public/app/features/search/utils.ts @@ -28,16 +28,15 @@ export const getSectionStorageKey = (title = 'General') => { * @param folder */ export const parseRouteParams = (params: UrlQueryMap) => { - const cleanedParams = Object.entries(params).reduce((obj, [key, val]) => { + const cleanedParams = Object.entries(params).reduce>((obj, [key, val]) => { if (!val) { return obj; } else if (key === 'tag' && !Array.isArray(val)) { return { ...obj, tag: [val] as string[] }; - } else if (key === 'sort') { - return { ...obj, sort: { value: val } }; } + return { ...obj, [key]: val }; - }, {} as Partial); + }, {}); if (params.folder) { const folderStr = `folder:${params.folder}`;