useSearchQuery.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { debounce } from 'lodash';
  2. import { FormEvent, useCallback, useReducer } from 'react';
  3. import { SelectableValue } from '@grafana/data';
  4. import { locationService } from '@grafana/runtime';
  5. import { SEARCH_SELECTED_LAYOUT } from '../constants';
  6. import {
  7. ADD_TAG,
  8. CLEAR_FILTERS,
  9. LAYOUT_CHANGE,
  10. QUERY_CHANGE,
  11. SET_TAGS,
  12. TOGGLE_SORT,
  13. TOGGLE_STARRED,
  14. DATASOURCE_CHANGE,
  15. } from '../reducers/actionTypes';
  16. import { defaultQuery, defaultQueryParams, queryReducer } from '../reducers/searchQueryReducer';
  17. import { DashboardQuery, SearchLayout } from '../types';
  18. import { hasFilters, parseRouteParams } from '../utils';
  19. const updateLocation = debounce((query) => locationService.partial(query), 300);
  20. export const useSearchQuery = (defaults: Partial<DashboardQuery>) => {
  21. const queryParams = parseRouteParams(locationService.getSearchObject());
  22. const initialState = { ...defaultQuery, ...defaults, ...queryParams };
  23. const selectedLayout = localStorage.getItem(SEARCH_SELECTED_LAYOUT) as SearchLayout;
  24. if (!queryParams.layout?.length && selectedLayout?.length) {
  25. initialState.layout = selectedLayout;
  26. }
  27. const [query, dispatch] = useReducer(queryReducer, initialState);
  28. const onQueryChange = useCallback((query: string) => {
  29. dispatch({ type: QUERY_CHANGE, payload: query });
  30. updateLocation({ query });
  31. }, []);
  32. const onTagFilterChange = useCallback((tags: string[]) => {
  33. dispatch({ type: SET_TAGS, payload: tags });
  34. updateLocation({ tag: tags });
  35. }, []);
  36. const onDatasourceChange = useCallback((datasource?: string) => {
  37. dispatch({ type: DATASOURCE_CHANGE, payload: datasource });
  38. updateLocation({ datasource });
  39. }, []);
  40. const onTagAdd = useCallback(
  41. (tag: string) => {
  42. dispatch({ type: ADD_TAG, payload: tag });
  43. updateLocation({ tag: [...query.tag, tag] });
  44. },
  45. [query.tag]
  46. );
  47. const onClearFilters = useCallback(() => {
  48. dispatch({ type: CLEAR_FILTERS });
  49. updateLocation(defaultQueryParams);
  50. }, []);
  51. const onStarredFilterChange = useCallback((e: FormEvent<HTMLInputElement>) => {
  52. const starred = (e.target as HTMLInputElement).checked;
  53. dispatch({ type: TOGGLE_STARRED, payload: starred });
  54. updateLocation({ starred: starred || null });
  55. }, []);
  56. const onSortChange = useCallback((sort: SelectableValue | null) => {
  57. dispatch({ type: TOGGLE_SORT, payload: sort });
  58. updateLocation({ sort: sort?.value, layout: SearchLayout.List });
  59. }, []);
  60. const onLayoutChange = useCallback((layout: SearchLayout) => {
  61. dispatch({ type: LAYOUT_CHANGE, payload: layout });
  62. if (layout === SearchLayout.Folders) {
  63. updateLocation({ layout, sort: null });
  64. return;
  65. }
  66. updateLocation({ layout });
  67. }, []);
  68. return {
  69. query,
  70. hasFilters: hasFilters(query),
  71. onQueryChange,
  72. onClearFilters,
  73. onTagFilterChange,
  74. onStarredFilterChange,
  75. onTagAdd,
  76. onSortChange,
  77. onLayoutChange,
  78. onDatasourceChange,
  79. };
  80. };