Mirror of https://github.com/roostorg/osprey
github.com/roostorg/osprey
1import { History, Location } from 'history';
2import { matchPath } from 'react-router-dom';
3
4import { saveQueryToHistory } from '../actions/QueryActions';
5import {
6 BaseQuery,
7 DefaultIntervals,
8 QueryState,
9 CustomSummaryFeatures,
10 ScanQueryOrder,
11 MomentRangeValues,
12 TopNTable,
13 Chart,
14} from '../types/QueryTypes';
15import { getQueryDateRange, isEmptyDateRange } from './QueryUtils';
16
17import { Routes } from '../Constants';
18
19type QueryStoreState = QueryState & {
20 customSummaryFeatures: CustomSummaryFeatures;
21 entityFeatureFilters: Set<string>;
22};
23
24export function extractQueryStateFromSearchParams(location: Location): QueryStoreState {
25 const isEntityView = matchPath(location.pathname, { path: Routes.ENTITY }) != null;
26 const queryString = new URLSearchParams(location.search);
27
28 const topNTables: Map<string, TopNTable> = new Map();
29 queryString.getAll('topn').map((data) => {
30 const table: TopNTable = TopNTable.fromQueryParam(data);
31 topNTables.set(table.dimension, table);
32 });
33
34 const charts: Array<Chart> = queryString.getAll('chart').map(Chart.fromQueryParam);
35
36 const customSummaryFeatures = queryString.getAll('customSummaryFeatures');
37
38 const queryState = {
39 executedQuery: {
40 queryFilter: queryString.get('queryFilter') || '',
41 start: queryString.get('start') || '',
42 end: queryString.get('end') || '',
43 interval:
44 queryString.get('interval') != null && queryString.get('interval') !== ''
45 ? (queryString.get('interval') as DefaultIntervals)
46 : 'day',
47 },
48 // Parse a `ScanQueryOrder` from the query string, defaulting to `descending` if the order isn't understood or
49 // not provided.
50 sortOrder:
51 queryString.get('order') === ScanQueryOrder.ASCENDING ? ScanQueryOrder.ASCENDING : ScanQueryOrder.DESCENDING,
52 topNTables,
53 charts,
54 entityFeatureFilters: new Set(queryString.getAll('entityFeatureFilters')),
55 customSummaryFeatures: customSummaryFeatures.length === 0 ? null : customSummaryFeatures,
56 };
57
58 const { start, end } = queryState.executedQuery;
59
60 // Do not save queries from the entity view yet
61 if (!isEntityView && !isEmptyDateRange(start, end)) {
62 saveQueryToHistory(queryState);
63 }
64
65 return queryState;
66}
67
68export function getSearchParamsForExecutedQuery(query: BaseQuery, location?: Location): URLSearchParams {
69 const queryString = new URLSearchParams(location?.search ?? '');
70
71 Object.entries(query).forEach(([key, value]) => {
72 if (value != null) {
73 queryString.set(key, String(value));
74 }
75 });
76
77 return queryString;
78}
79
80const ENTITY_VIEW_DEFAULT_SEARCH_PARAMS: Array<[string, string]> = [
81 ['queryFilter', ''],
82 ['topn', 'ActionName'],
83];
84const ENTITY_VIEW_DEFAULT_INTERVAL: MomentRangeValues = 'twoWeeks';
85
86export function setSearchParamsForEntityView(history: History) {
87 // Check that we are acting on the correct route.
88 const entityViewMatch = matchPath(history.location.pathname, { path: Routes.ENTITY });
89 if (entityViewMatch == null) {
90 return;
91 }
92
93 const locationSearchParams = new URLSearchParams(history.location.search);
94
95 // If not all location based params are set, choose a default of last two weeks.
96 if (!['start', 'end', 'interval'].every((param) => locationSearchParams.has(param))) {
97 const { start, end } = getQueryDateRange(ENTITY_VIEW_DEFAULT_INTERVAL);
98 locationSearchParams.set('start', start);
99 locationSearchParams.set('end', end);
100 locationSearchParams.set('interval', ENTITY_VIEW_DEFAULT_INTERVAL);
101 }
102
103 // Ensure all defaults are set.
104 for (const [key, value] of ENTITY_VIEW_DEFAULT_SEARCH_PARAMS) {
105 if (!locationSearchParams.has(key)) {
106 locationSearchParams.set(key, value);
107 }
108 }
109
110 history.replace({ pathname: history.location.pathname, search: `?${locationSearchParams}` });
111}