setTimeout(function() {
setShowModal(false)
- }, 20)}
+ }, 50)}
>
{ children ? React.cloneElement(children, { onClick: () => setShowModal(true)}) : (
setShowModal(true)}
>
{filter.label}
diff --git a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx
index 65e123ba4..3483b3340 100644
--- a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx
+++ b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx
@@ -4,25 +4,29 @@ import FilterAutoComplete from '../FilterAutoComplete';
interface Props {
index: number;
value: any; // event/filter
+ // type: string;
+ key: string;
onRemoveValue?: () => void;
onAddValue?: () => void;
+ showCloseButton: boolean;
showOrButton: boolean;
onSelect: (e, item) => void;
}
function FilterValue(props: Props) {
- const { index, value, showOrButton, onRemoveValue , onAddValue } = props;
+ const { index, value, key, showOrButton, showCloseButton, onRemoveValue , onAddValue } = props;
return (
);
diff --git a/frontend/app/components/ui/SegmentSelection/segmentSelection.css b/frontend/app/components/ui/SegmentSelection/segmentSelection.css
index a74d7d77b..e33ec3b73 100644
--- a/frontend/app/components/ui/SegmentSelection/segmentSelection.css
+++ b/frontend/app/components/ui/SegmentSelection/segmentSelection.css
@@ -3,16 +3,16 @@
align-items: center;
justify-content: space-around;
border: solid thin $gray-light;
- border-radius: 5px;
+ border-radius: 3px;
overflow: hidden;
& .item {
color: $gray-medium;
font-weight: medium;
padding: 10px;
- flex: 1;
+ /* flex: 1; */
text-align: center;
- border-right: solid thin $gray-light;
+ border-right: solid thin $teal;
cursor: pointer;
background-color: $gray-lightest;
display: flex;
@@ -64,6 +64,6 @@
}
.extraSmall .item {
- padding: 2px 4px;
+ padding: 0 4px;
font-size: 12px;
}
\ No newline at end of file
diff --git a/frontend/app/duck/customMetrics.js b/frontend/app/duck/customMetrics.js
index 0909ff3b1..f6a7b0b88 100644
--- a/frontend/app/duck/customMetrics.js
+++ b/frontend/app/duck/customMetrics.js
@@ -48,6 +48,7 @@ function reducer(state = initialState, action = {}) {
case EDIT:
return state.mergeIn([ 'instance' ], CustomMetric(action.instance));
case UPDATE_SERIES:
+ console.log('update series', action.series);
return state.setIn(['instance', 'series', action.index], FilterSeries(action.series));
case success(SAVE):
return state.set([ 'instance' ], CustomMetric(action.data));
@@ -55,11 +56,7 @@ function reducer(state = initialState, action = {}) {
return state.set("instance", ErrorInfo(action.data));
case success(FETCH_LIST):
const { data } = action;
- return state
- .set("totalCount", data ? data.total : 0)
- .set("list", List(data && data.errors).map(CustomMetric)
- .filter(e => e.parentErrorId == null)
- .map(e => e.update("chart", chartWrapper)));
+ return state.set("list", List(data.map(CustomMetric)));
}
return state;
}
@@ -95,11 +92,9 @@ export function save(instance) {
};
}
-export function fetchList(params = {}, clear = false) {
+export function fetchList() {
return {
types: array(FETCH_LIST),
- call: client => client.post('/errors/search', params),
- clear,
- params: cleanParams(params),
+ call: client => client.get(`/${name}s`),
};
}
\ No newline at end of file
diff --git a/frontend/app/duck/filters.js b/frontend/app/duck/filters.js
index 290a4f1cb..9122fb9c2 100644
--- a/frontend/app/duck/filters.js
+++ b/frontend/app/duck/filters.js
@@ -14,11 +14,9 @@ import { newFiltersList } from 'Types/filter'
import NewFilter, { filtersMap } from 'Types/filter/newFilter';
const filterOptions = {}
-// newFiltersList.forEach(filter => {
-// filterOptions[filter.category] = filter
-// })
Object.keys(filtersMap).forEach(key => {
+ // const filter = NewFilter(filtersMap[key]);
const filter = filtersMap[key];
if (filterOptions.hasOwnProperty(filter.category)) {
filterOptions[filter.category].push(filter);
diff --git a/frontend/app/styles/main.css b/frontend/app/styles/main.css
index 077ec9904..8915fd341 100644
--- a/frontend/app/styles/main.css
+++ b/frontend/app/styles/main.css
@@ -107,8 +107,9 @@
}
.form-group {
- margin-bottom: 20px;
+ margin-bottom: 25px;
& label {
+ display: inline-block;
margin-bottom: 5px;
}
}
\ No newline at end of file
diff --git a/frontend/app/types/customMetric.js b/frontend/app/types/customMetric.js
index 32c4386b6..1bfaebbd6 100644
--- a/frontend/app/types/customMetric.js
+++ b/frontend/app/types/customMetric.js
@@ -17,6 +17,7 @@ export const FilterSeries = Record({
methods: {
toData() {
const js = this.toJS();
+ delete js.key;
// js.filter = js.filter.toData();
return js;
},
@@ -42,6 +43,7 @@ export default Record({
toData() {
const js = this.toJS();
+
js.series = js.series.map(series => {
series.filter.filters = series.filter.filters.map(filter => {
delete filter.operatorOptions
@@ -51,6 +53,8 @@ export default Record({
return series;
});
+ delete js.key;
+
return js;
},
},
diff --git a/frontend/app/types/filter/filter.js b/frontend/app/types/filter/filter.js
index 41c3421f8..e3663e860 100644
--- a/frontend/app/types/filter/filter.js
+++ b/frontend/app/types/filter/filter.js
@@ -46,6 +46,7 @@ export default Record({
suspicious: undefined,
consoleLevel: undefined,
strict: false,
+ eventsOrder: 'and',
}, {
idKey: 'searchId',
methods: {
@@ -53,10 +54,12 @@ export default Record({
const js = this.toJS();
js.filters = js.filters.map(filter => {
delete filter.operatorOptions
+ delete filter._key
return filter;
});
delete js.createdAt;
+ delete js.key;
return js;
}
},
diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js
index 2c1a49f48..091b16277 100644
--- a/frontend/app/types/filter/newFilter.js
+++ b/frontend/app/types/filter/newFilter.js
@@ -219,41 +219,41 @@ export const booleanOptions = [
]
export const filtersMap = {
- [TYPES.CLICK]: { category: 'interactions', label: 'Click', operator: 'on', operatorOptions: targetFilterOptions, icon: 'filters/click' },
- [TYPES.INPUT]: { category: 'interactions', label: 'Input', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.LOCATION]: { category: 'interactions', label: 'Page', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.CLICK]: { key: TYPES.CLICK, type: 'multiple', category: 'interactions', label: 'Click', operator: 'on', operatorOptions: targetFilterOptions, icon: 'filters/click', isEvent: true },
+ [TYPES.INPUT]: { key: TYPES.INPUT, type: 'multiple', category: 'interactions', label: 'Input', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click', isEvent: true },
+ [TYPES.LOCATION]: { key: TYPES.LOCATION, type: 'multiple', category: 'interactions', label: 'Page', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click', isEvent: true },
- [TYPES.USER_OS]: { category: 'gear', label: 'User OS', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.USER_BROWSER]: { category: 'gear', label: 'User Browser', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.USER_DEVICE]: { category: 'gear', label: 'User Device', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.PLATFORM]: { category: 'gear', label: 'Platform', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.REVID]: { category: 'gear', label: 'RevId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.USER_OS]: { key: TYPES.USER_OS, type: 'multiple', category: 'gear', label: 'User OS', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.USER_BROWSER]: { key: TYPES.USER_BROWSER, type: 'multiple', category: 'gear', label: 'User Browser', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.USER_DEVICE]: { key: TYPES.USER_DEVICE, type: 'multiple', category: 'gear', label: 'User Device', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.PLATFORM]: { key: TYPES.PLATFORM, type: 'multiple', category: 'gear', label: 'Platform', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.REVID]: { key: TYPES.REVID, type: 'multiple', category: 'gear', label: 'RevId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.REFERRER]: { category: 'recording_attributes', label: 'Referrer', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.DURATION]: { category: 'recording_attributes', label: 'Duration', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.USER_COUNTRY]: { category: 'recording_attributes', label: 'User Country', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.REFERRER]: { key: TYPES.REFERRER, type: 'multiple', category: 'recording_attributes', label: 'Referrer', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.DURATION]: { key: TYPES.DURATION, type: 'number', category: 'recording_attributes', label: 'Duration', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.USER_COUNTRY]: { key: TYPES.USER_COUNTRY, type: 'multiple', category: 'recording_attributes', label: 'User Country', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.CONSOLE]: { category: 'javascript', label: 'Console', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.ERROR]: { category: 'javascript', label: 'Error', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.FETCH]: { category: 'javascript', label: 'Fetch', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.GRAPHQL]: { category: 'javascript', label: 'GraphQL', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.STATEACTION]: { category: 'javascript', label: 'StateAction', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.CONSOLE]: { key: TYPES.CONSOLE, type: 'multiple', category: 'javascript', label: 'Console', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.ERROR]: { key: TYPES.ERROR, type: 'multiple', category: 'javascript', label: 'Error', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.FETCH]: { key: TYPES.FETCH, type: 'multiple', category: 'javascript', label: 'Fetch', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.GRAPHQL]: { key: TYPES.GRAPHQL, type: 'multiple', category: 'javascript', label: 'GraphQL', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.STATEACTION]: { key: TYPES.STATEACTION, type: 'multiple', category: 'javascript', label: 'StateAction', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.USERID]: { category: 'user', label: 'UserId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.USERANONYMOUSID]: { category: 'user', label: 'UserAnonymousId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.USERID]: { key: TYPES.USERID, type: 'multiple', category: 'user', label: 'UserId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.USERANONYMOUSID]: { key: TYPES.USERANONYMOUSID, type: 'multiple', category: 'user', label: 'UserAnonymousId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.DOM_COMPLETE]: { category: 'new', label: 'DOM Complete', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.LARGEST_CONTENTFUL_PAINT_TIME]: { category: 'new', label: 'Largest Contentful Paint Time', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.TIME_BETWEEN_EVENTS]: { category: 'new', label: 'Time Between Events', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.TTFB]: { category: 'new', label: 'TTFB', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.AVG_CPU_LOAD]: { category: 'new', label: 'Avg CPU Load', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.AVG_MEMORY_USAGE]: { category: 'new', label: 'Avg Memory Usage', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
- [TYPES.SLOW_SESSION]: { category: 'new', label: 'Slow Session', operator: 'true', operatorOptions: [{ key: 'true', text: 'true', value: 'true' }], icon: 'filters/click' },
- [TYPES.MISSING_RESOURCE]: { category: 'new', label: 'Missing Resource', operator: 'true', operatorOptions: [{ key: 'inImages', text: 'in images', value: 'true' }], icon: 'filters/click' },
- [TYPES.CLICK_RAGE]: { category: 'new', label: 'Click Rage', operator: 'onAnything', operatorOptions: [{ key: 'onAnything', text: 'on anything', value: 'true' }], icon: 'filters/click' },
- // [TYPES.URL]: { category: 'interactions', label: 'URL', operator: 'is', operatorOptions: stringFilterOptions },
- // [TYPES.CUSTOM]: { category: 'interactions', label: 'Custom', operator: 'is', operatorOptions: stringFilterOptions },
- // [TYPES.METADATA]: { category: 'interactions', label: 'Metadata', operator: 'is', operatorOptions: stringFilterOptions },
+ [TYPES.DOM_COMPLETE]: { key: TYPES.DOM_COMPLETE, type: 'multiple', category: 'new', label: 'DOM Complete', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.LARGEST_CONTENTFUL_PAINT_TIME]: { key: TYPES.LARGEST_CONTENTFUL_PAINT_TIME, type: 'number', category: 'new', label: 'Largest Contentful Paint Time', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.TIME_BETWEEN_EVENTS]: { key: TYPES.TIME_BETWEEN_EVENTS, type: 'number', category: 'new', label: 'Time Between Events', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.TTFB]: { key: TYPES.TTFB, type: 'time', category: 'new', label: 'TTFB', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.AVG_CPU_LOAD]: { key: TYPES.AVG_CPU_LOAD, type: 'number', category: 'new', label: 'Avg CPU Load', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.AVG_MEMORY_USAGE]: { key: TYPES.AVG_MEMORY_USAGE, type: 'number', category: 'new', label: 'Avg Memory Usage', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
+ [TYPES.SLOW_SESSION]: { key: TYPES.SLOW_SESSION, type: 'boolean', category: 'new', label: 'Slow Session', operator: 'true', operatorOptions: [{ key: 'true', text: 'true', value: 'true' }], icon: 'filters/click' },
+ [TYPES.MISSING_RESOURCE]: { key: TYPES.MISSING_RESOURCE, type: 'boolean', category: 'new', label: 'Missing Resource', operator: 'true', operatorOptions: [{ key: 'inImages', text: 'in images', value: 'true' }], icon: 'filters/click' },
+ [TYPES.CLICK_RAGE]: { key: TYPES.CLICK_RAGE, type: 'boolean', category: 'new', label: 'Click Rage', operator: 'onAnything', operatorOptions: [{ key: 'onAnything', text: 'on anything', value: 'true' }], icon: 'filters/click' },
+ // [TYPES.URL]: { / [TYPES,TYPES. category: 'interactions', label: 'URL', operator: 'is', operatorOptions: stringFilterOptions },
+ // [TYPES.CUSTOM]: { / [TYPES,TYPES. category: 'interactions', label: 'Custom', operator: 'is', operatorOptions: stringFilterOptions },
+ // [TYPES.METADATA]: { / [TYPES,TYPES. category: 'interactions', label: 'Metadata', operator: 'is', operatorOptions: stringFilterOptions },
}
export default Record({
@@ -263,6 +263,7 @@ export default Record({
icon: '',
type: '',
value: [""],
+ category: '',
custom: '',
// target: Target(),
@@ -274,10 +275,13 @@ export default Record({
operator: 'is',
operatorOptions: [],
+ isEvent: false,
+ index: 0,
}, {
keyKey: "_key",
fromJS: ({ ...filter }) => ({
...filter,
+ key: filter.type,
type: filter.type, // camelCased(filter.type.toLowerCase()),
// key: filter.type === METADATA ? filter.label : filter.key || filter.type, // || camelCased(filter.type.toLowerCase()),
// label: getLabel(filter),
@@ -299,10 +303,4 @@ export default Record({
// operators: filterMap[key].operatorOptions,
// value: [""]
// }
-// }
-
-// export const newFiltersList = [
-// NewFilterType(TYPES.CLICK, 'Click', 'filters/click', true),
-// NewFilterType(TYPES.CLICK, 'Input', 'filters/click', true),
-// NewFilterType(TYPES.CONSOLE, 'Console', 'filters/click', true),
-// ];
\ No newline at end of file
+// }
\ No newline at end of file