diff --git a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx
index 156c42312..8fc9f16c5 100644
--- a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx
+++ b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx
@@ -1,68 +1,23 @@
-import React, { useEffect } from 'react';
+import React from 'react';
import FilterList from 'Shared/Filters/FilterList';
import FilterSelection from 'Shared/Filters/FilterSelection';
import SaveFilterButton from 'Shared/SaveFilterButton';
import { connect } from 'react-redux';
import { Button } from 'UI';
import { edit, addFilter } from 'Duck/search';
-import { withRouter } from 'react-router';
-import { clearSearch, fetchSessions, addFilterByKeyAndValue } from 'Duck/search';
-import { FilterKey, getFilterKeyTypeByKey } from 'Types/filter/filterType';
-
-const allowedQueryKeys = [
- 'userOs',
- 'userId',
- 'userBrowser',
- 'userDevice',
- 'userCountry',
- 'startDate',
- 'endDate',
- 'minDuration',
- 'maxDuration',
- 'referrer',
- 'sort',
- 'order',
-];
+import SessionSearchQueryParamHandler from 'Shared/SessionSearchQueryParamHandler';
interface Props {
appliedFilter: any;
edit: typeof edit;
addFilter: typeof addFilter;
saveRequestPayloads: boolean;
- location: any;
- addFilterByKeyAndValue: typeof addFilterByKeyAndValue;
}
function SessionSearch(props: Props) {
- const {
- appliedFilter,
- saveRequestPayloads = false,
- location: { search },
- } = props;
+ const { appliedFilter, saveRequestPayloads = false } = props;
const hasEvents = appliedFilter.filters.filter((i: any) => i.isEvent).size > 0;
const hasFilters = appliedFilter.filters.filter((i: any) => !i.isEvent).size > 0;
- useEffect(() => {
- const queryParams = Object.fromEntries(
- Object.entries(Object.fromEntries(new URLSearchParams(search))).filter(([key]) =>
- allowedQueryKeys.includes(key)
- )
- );
- const entires = Object.entries(queryParams);
- if (entires.length > 0) {
- entires.forEach(([key, value]) => {
- if (value !== '') {
- const filterKey = getFilterKeyTypeByKey(key);
- const valueArr = value.split('|');
- const operator = valueArr.shift();
- console.log('operator', operator, valueArr);
- if (filterKey) {
- props.addFilterByKeyAndValue(filterKey, valueArr, operator);
- }
- }
- });
- }
- }, []);
-
const onAddFilter = (filter: any) => {
props.addFilter(filter);
};
@@ -98,48 +53,51 @@ function SessionSearch(props: Props) {
});
};
- return hasEvents || hasFilters ? (
-
-
-
-
+ return (
+ <>
+
+ {hasEvents || hasFilters ? (
+
+
+
+
-
-
-
- {/* */}
-
-
+
+
+
+ {/* */}
+
+
+
+
+
+
+
-
-
-
-
-
- ) : (
- <>>
+ ) : (
+ <>>
+ )}
+ >
);
}
-export default withRouter(
- connect(
- (state: any) => ({
- saveRequestPayloads: state.getIn(['site', 'active', 'saveRequestPayloads']),
- appliedFilter: state.getIn(['search', 'instance']),
- }),
- { edit, addFilter, addFilterByKeyAndValue }
- )(SessionSearch)
-);
+export default connect(
+ (state: any) => ({
+ saveRequestPayloads: state.getIn(['site', 'active', 'saveRequestPayloads']),
+ appliedFilter: state.getIn(['search', 'instance']),
+ }),
+ { edit, addFilter }
+)(SessionSearch);
diff --git a/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx b/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx
new file mode 100644
index 000000000..bc75e0195
--- /dev/null
+++ b/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx
@@ -0,0 +1,111 @@
+import React, { useEffect } from 'react';
+import { useHistory } from 'react-router';
+import { connect } from 'react-redux';
+import { addFilterByKeyAndValue } from 'Duck/search';
+import { getFilterKeyTypeByKey, setQueryParamKeyFromFilterkey } from 'Types/filter/filterType';
+
+const allowedQueryKeys = [
+ 'userId',
+ 'userid',
+ 'uid',
+ 'usera',
+
+ 'clk',
+ 'inp',
+ 'loc',
+
+ 'os',
+ 'browser',
+ 'device',
+ 'platform',
+ 'revid',
+
+ 'country',
+
+ // 'startDate',
+ // 'endDate',
+ // 'minDuration',
+ // 'maxDuration',
+ 'ref',
+ 'sort',
+ 'order',
+ 'ce',
+ 'sa',
+ 'err',
+ 'iss',
+
+ // PERFORMANCE
+ 'domc',
+ 'lcp',
+ 'ttfb',
+ 'acpu',
+ 'amem',
+ 'ff',
+];
+
+interface Props {
+ appliedFilter: any;
+ addFilterByKeyAndValue: typeof addFilterByKeyAndValue;
+}
+function SessionSearchQueryParamHandler(props: Props) {
+ const { appliedFilter } = props;
+ const history = useHistory();
+
+ const createUrlQuery = (filters: any) => {
+ const query: any = {};
+ filters.forEach((filter: any) => {
+ if (filter.value.length > 0) {
+ const _key = setQueryParamKeyFromFilterkey(filter.key);
+ query[_key] = `${filter.operator}|${filter.value.join('|')}`;
+ }
+ });
+ return query;
+ };
+
+ const addFilter = ([key, value]: [string, string]): void => {
+ if (value !== '') {
+ const filterKey = getFilterKeyTypeByKey(key);
+ const valueArr = value.split('|');
+ const operator = valueArr.shift();
+ // TODO validate operator
+ if (filterKey) {
+ props.addFilterByKeyAndValue(filterKey, valueArr, operator);
+ }
+ }
+ };
+
+ const applyFilterFromQuery = () => {
+ const entires = getQueryObject(history.location.search);
+ console.log('entires', entires);
+ if (entires.length > 0) {
+ entires.forEach(addFilter);
+ }
+ };
+
+ useEffect(() => {
+ console.log('rerender');
+ applyFilterFromQuery();
+ }, []);
+
+ useEffect(() => {
+ const query: any = createUrlQuery(appliedFilter.filters);
+ history.replace({ search: new URLSearchParams(query).toString() });
+ }, [appliedFilter]);
+ return <>>;
+}
+
+export default connect(
+ (state: any) => ({
+ appliedFilter: state.getIn(['search', 'instance']),
+ }),
+ { addFilterByKeyAndValue }
+)(SessionSearchQueryParamHandler);
+
+function getQueryObject(search: any) {
+ const queryParams = Object.fromEntries(
+ Object.entries(Object.fromEntries(new URLSearchParams(search))).filter(([key]) =>
+ allowedQueryKeys.includes(key)
+ )
+ );
+ return Object.entries(queryParams);
+}
diff --git a/frontend/app/components/shared/SessionSearchQueryParamHandler/index.ts b/frontend/app/components/shared/SessionSearchQueryParamHandler/index.ts
new file mode 100644
index 000000000..c13bb493d
--- /dev/null
+++ b/frontend/app/components/shared/SessionSearchQueryParamHandler/index.ts
@@ -0,0 +1 @@
+export { default } from './SessionSearchQueryParamHandler';
\ No newline at end of file
diff --git a/frontend/app/types/filter/filterType.ts b/frontend/app/types/filter/filterType.ts
index 17c84ece3..9915a3aa5 100644
--- a/frontend/app/types/filter/filterType.ts
+++ b/frontend/app/types/filter/filterType.ts
@@ -8,18 +8,107 @@ export enum FilterCategory {
PERFORMANCE = 'Performance',
}
+export const setQueryParamKeyFromFilterkey = (filterKey: string) => {
+ switch (filterKey) {
+ case FilterKey.USERID:
+ return 'uid';
+ case FilterKey.USERANONYMOUSID:
+ return 'usera';
+ case FilterKey.CLICK:
+ return 'clk';
+ case FilterKey.INPUT:
+ return 'inp';
+ case FilterKey.LOCATION:
+ return 'loc';
+ case FilterKey.USER_OS:
+ return 'os';
+ case FilterKey.USER_BROWSER:
+ return 'browser';
+ case FilterKey.USER_DEVICE:
+ return 'device';
+ case FilterKey.PLATFORM:
+ return 'platform';
+ case FilterKey.REVID:
+ return 'revid';
+ case FilterKey.USER_COUNTRY:
+ return 'country';
+ case FilterKey.REFERRER:
+ return 'ref';
+ case FilterKey.CUSTOM:
+ return 'ce';
+ case FilterKey.STATEACTION:
+ return 'sa';
+ case FilterKey.ERROR:
+ return 'err';
+ case FilterKey.ISSUE:
+ return 'iss';
+
+ // PERFORMANCE
+ case FilterKey.DOM_COMPLETE:
+ return 'domc';
+ case FilterKey.LARGEST_CONTENTFUL_PAINT_TIME:
+ return 'lcp';
+ case FilterKey.TTFB:
+ return 'ttfb';
+ case FilterKey.AVG_CPU_LOAD:
+ return 'acpu';
+ case FilterKey.AVG_MEMORY_USAGE:
+ return 'amem';
+ case FilterKey.FETCH_FAILED:
+ return 'ff';
+ }
+};
+
export const getFilterKeyTypeByKey = (key: string) => {
switch (key) {
case 'userId':
+ case 'uid':
+ case 'userid':
return FilterKey.USERID;
- case 'userOs':
+ case 'usera':
+ return FilterKey.USERANONYMOUSID;
+ case 'clk':
+ return FilterKey.CLICK;
+ case 'inp':
+ return FilterKey.INPUT;
+ case 'loc':
+ return FilterKey.LOCATION;
+ case 'os':
return FilterKey.USER_OS;
- case 'userBrowser':
+ case 'browser':
return FilterKey.USER_BROWSER;
- case 'userDevice':
+ case 'device':
return FilterKey.USER_DEVICE;
- case 'userCountry':
+ case 'platform':
+ return FilterKey.PLATFORM;
+ case 'revid':
+ return FilterKey.REVID;
+ case 'country':
return FilterKey.USER_COUNTRY;
+ case 'ref':
+ return FilterKey.REFERRER;
+ case 'ce':
+ return FilterKey.CUSTOM;
+ case 'sa':
+ return FilterKey.STATEACTION;
+ case 'err':
+ return FilterKey.ERROR;
+ case 'iss':
+ return FilterKey.ISSUE;
+
+ // PERFORMANCE
+ case 'domc':
+ return FilterKey.DOM_COMPLETE;
+ case 'lcp':
+ return FilterKey.LARGEST_CONTENTFUL_PAINT_TIME;
+ case 'ttfb':
+ return FilterKey.TTFB;
+ case 'acpu':
+ return FilterKey.AVG_CPU_LOAD;
+ case 'amem':
+ return FilterKey.AVG_MEMORY_USAGE;
+ case 'ff':
+ return FilterKey.FETCH_FAILED;
}
};
diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js
index 9a87da2c6..452c4f1c9 100644
--- a/frontend/app/types/filter/newFilter.js
+++ b/frontend/app/types/filter/newFilter.js
@@ -11,7 +11,7 @@ export const filters = [
{ key: FilterKey.INPUT, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Input', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/input', isEvent: true },
{ key: FilterKey.LOCATION, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Path', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/location', isEvent: true },
{ key: FilterKey.CUSTOM, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Custom Events', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/custom', isEvent: true },
- { key: FilterKey.REQUEST, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', isEvent: true },
+ // { key: FilterKey.REQUEST, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', isEvent: true },
{ key: FilterKey.FETCH, type: FilterType.SUB_FILTERS, category: FilterCategory.JAVASCRIPT, operator: 'is', label: 'Network Request', filters: [
{ key: FilterKey.FETCH_URL, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with URL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' },
{ key: FilterKey.FETCH_STATUS_CODE, type: FilterType.NUMBER_MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with status code', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' },