+
-

+
-
-
-
-
OpenReplay Cloud is the hosted version of our open-source project.
-
We’ll manage hosting, scaling and upgrades.
-
-
-
-
-
+

+
+
+
+ OpenReplay Cloud{' '}
+
+
+
+
+
OpenReplay Cloud is the hosted version of our open-source project.
+
We’ll manage hosting, scaling and upgrades.
+
+
+
+
+
+
-
-
-
-
+
+
);
}
}
diff --git a/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx b/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx
index 1951b00a4..820ed4aa0 100644
--- a/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx
+++ b/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx
@@ -2,10 +2,8 @@ import React, { useEffect } from 'react';
import { useHistory } from 'react-router';
import { connect } from 'react-redux';
import { addFilterByKeyAndValue, addFilter } from 'Duck/search';
-import { getFilterKeyTypeByKey, setQueryParamKeyFromFilterkey } from 'Types/filter/filterType';
-import { filtersMap } from 'App/types/filter/newFilter';
-import Filter from 'Types/filter/filter';
import { applyFilter } from 'Duck/search';
+import { createUrlQuery, getFiltersFromQuery } from 'App/utils/search';
interface Props {
appliedFilter: any;
@@ -13,93 +11,25 @@ interface Props {
addFilterByKeyAndValue: typeof addFilterByKeyAndValue;
addFilter: typeof addFilter;
}
-const SessionSearchQueryParamHandler = React.memo((props: Props) => {
+const SessionSearchQueryParamHandler = (props: Props) => {
const { appliedFilter } = props;
const history = useHistory();
- const createUrlQuery = (filters: any) => {
- const query: any = [];
- filters.forEach((filter: any) => {
- const item: any = {};
- if (filter.value.length > 0) {
- const _key = setQueryParamKeyFromFilterkey(filter.key);
- if (_key) {
- let str = `${filter.operator}|${filter.value.join('|')}`;
- if (filter.hasSource) {
- str = `${str}^${filter.sourceOperator}|${filter.source.join('|')}`;
- }
- item.key = _key + '[]';
- item.value = str;
- } else {
- let str = `${filter.operator}|${filter.value.join('|')}`;
- item.key = [filter.key] + '[]';
- item.value = str;
- }
-
- query.push(item);
- }
-
- });
- return query;
- };
-
const applyFilterFromQuery = () => {
- if (appliedFilter.filters.size > 0 || history.location.search === "") {
- return;
- }
- const entires = getQueryObject(history.location.search);
- const _filters: any = { ...filtersMap };
- if (entires.length > 0) {
- const filters: any = [];
- entires.forEach((item: any) => {
- if (!item.key || !item.value) { return }
- let filter: any = {}
- const filterKey = getFilterKeyTypeByKey(item.key);
- const tmp = item.value.split('^');
- const valueArr = tmp[0].split('|');
- const operator = valueArr.shift();
- const sourceArr = tmp[1] ? tmp[1].split('|') : [];
- const sourceOperator = sourceArr.shift();
-
- if (filterKey) {
- filter.type = filterKey;
- filter.key = filterKey;
- } else {
- filter = _filters[item.key];
- if (!!filter) {
- filter.type = filter.key;
- filter.key = filter.key;
- }
- }
- filter.value = valueArr;
- filter.operator = operator;
- filter.source = sourceArr;
- filter.sourceOperator = !!sourceOperator ? decodeURI(sourceOperator) : null;
- filters.push(filter);
- });
- const f = Filter({ filters })
- props.applyFilter(f);
- }
+ const filter = getFiltersFromQuery(history.location.search, appliedFilter);
+ props.applyFilter(filter, true);
};
const generateUrlQuery = () => {
- const query: any = createUrlQuery(appliedFilter.filters);
-
- let queryString = query.reduce((acc: any, curr: any, index: any) => {
- acc += `${curr.key}=${curr.value}`;
- if (index < query.length - 1) {
- acc += '&';
- }
- return acc;
- }, '');
-
- history.replace({ search: queryString });
+ const search: any = createUrlQuery(appliedFilter);
+ history.replace({ search });
};
useEffect(applyFilterFromQuery, []);
useEffect(generateUrlQuery, [appliedFilter]);
+
return <>>;
-});
+};
export default connect(
(state: any) => ({
@@ -107,11 +37,3 @@ export default connect(
}),
{ addFilterByKeyAndValue, addFilter, applyFilter }
)(SessionSearchQueryParamHandler);
-
-function getQueryObject(search: any) {
- let jsonArray = search.slice(1).split('&').map((item: any) => {
- let [key, value] = item.split('=');
- return {key: key.slice(0, -2), value};
- });
- return jsonArray;
-}
diff --git a/frontend/app/duck/search.js b/frontend/app/duck/search.js
index ce4306cbb..f4d84ffce 100644
--- a/frontend/app/duck/search.js
+++ b/frontend/app/duck/search.js
@@ -71,6 +71,7 @@ function reducer(state = initialState, action = {}) {
case EDIT:
return state.mergeIn(['instance'], action.instance).set('currentPage', 1);
case APPLY:
+
return action.fromUrl ? state.set('instance', Filter(action.filter)) : state.mergeIn(['instance'], action.filter).set('currentPage', 1);
case success(FETCH):
return state.set('instance', action.data);
diff --git a/frontend/app/svg/register.svg b/frontend/app/svg/register.svg
new file mode 100644
index 000000000..e0de5d4c7
--- /dev/null
+++ b/frontend/app/svg/register.svg
@@ -0,0 +1,57 @@
+
diff --git a/frontend/app/utils/search.ts b/frontend/app/utils/search.ts
new file mode 100644
index 000000000..82b3daee1
--- /dev/null
+++ b/frontend/app/utils/search.ts
@@ -0,0 +1,117 @@
+import { getFilterKeyTypeByKey, setQueryParamKeyFromFilterkey } from 'Types/filter/filterType';
+import Period, { LAST_24_HOURS, LAST_7_DAYS, LAST_30_DAYS, CUSTOM_RANGE } from 'Types/app/period';
+import Filter from 'Types/filter/filter';
+import { filtersMap } from 'App/types/filter/newFilter';
+
+export const createUrlQuery = (filter: any) => {
+ const query = [];
+
+ for (const f of filter.filters) {
+ if (!f.value.length) {
+ continue;
+ }
+
+ let str = `${f.operator}|${f.value.join('|')}`;
+ if (f.hasSource) {
+ str = `${str}^${f.sourceOperator}|${f.source.join('|')}`;
+ }
+
+ let key: any = setQueryParamKeyFromFilterkey(f.key);
+ if (!key) {
+ key = [f.key];
+ }
+
+ query.push({ key: key + '[]', value: str });
+ }
+
+ if (query.length > 0) {
+ query.push({ key: 'range[]', value: filter.rangeValue });
+ if (filter.rangeValue === CUSTOM_RANGE) {
+ query.push({ key: 'rStart[]', value: filter.startDate });
+ query.push({ key: 'rEnd[]', value: filter.endDate });
+ }
+ }
+
+ return query.map(({ key, value }) => `${key}=${value}`).join('&');
+};
+
+export const getFiltersFromQuery = (search: string, filter: any) => {
+ if (!search || filter.filters.size > 0) {
+ return;
+ }
+
+ const entires = getQueryObject(search);
+ const period: any = getPeriodFromEntries(entires);
+ const filters = getFiltersFromEntries(entires);
+
+ return Filter({ filters, rangeValue: period.rangeName });
+};
+
+const getFiltersFromEntries = (entires: any) => {
+ const _filters: any = { ...filtersMap };
+ const filters: any = [];
+ if (entires.length > 0) {
+ entires.forEach((item: any) => {
+ if (!item.key || !item.value) {
+ return;
+ }
+
+ let filter: any = {};
+ const filterKey = getFilterKeyTypeByKey(item.key);
+ if (!filterKey) {
+ return;
+ }
+ const tmp = item.value.split('^');
+ const valueArr = tmp[0].split('|');
+ const operator = valueArr.shift();
+ const sourceArr = tmp[1] ? tmp[1].split('|') : [];
+ const sourceOperator = sourceArr.shift();
+
+ if (filterKey) {
+ filter.type = filterKey;
+ filter.key = filterKey;
+ } else {
+ filter = _filters[item.key];
+ if (!!filter) {
+ filter.type = filter.key;
+ filter.key = filter.key;
+ }
+ }
+
+ filter.value = valueArr;
+ filter.operator = operator;
+ filter.source = sourceArr;
+ filter.sourceOperator = !!sourceOperator ? decodeURI(sourceOperator) : null;
+ if (!filter.filters || filter.filters.size === 0) {
+ filters.push(filter);
+ }
+ });
+ }
+ return filters;
+};
+
+const getPeriodFromEntries = (entires: any) => {
+ const rangeFilter = entires.find(({ key }: any) => key === 'range');
+ if (!rangeFilter) {
+ return Period();
+ }
+
+ if (rangeFilter.value === CUSTOM_RANGE) {
+ const start = entires.find(({ key }: any) => key === 'rStart').value;
+ const end = entires.find(({ key }: any) => key === 'rEnd').value;
+ return Period({ rangeName: rangeFilter.value, start, end });
+ }
+
+ return Period({ rangeName: rangeFilter.value });
+};
+
+function getQueryObject(search: any) {
+ let jsonArray = search
+ .slice(1)
+ .split('&')
+ .map((item: any) => {
+ let [key, value] = item.split('=');
+ return { key: key.slice(0, -2), value };
+ });
+ return jsonArray;
+}