This commit is contained in:
Taha Yassine Kraiem 2022-01-27 16:01:40 +01:00
commit fea33ca3a1
13 changed files with 392 additions and 243 deletions

View file

@ -30,7 +30,7 @@ function FitlerItem(props: Props) {
<FilterOperator filter={filter} onChange={onOperatorChange} className="mx-2 flex-shrink-0"/>
<FilterValue filter={filter} onUpdate={props.onUpdate} />
</div>
<div className="flex self-start mt-2 ml-auto">
<div className="flex self-start mt-1 ml-auto px-2">
<div
className="cursor-pointer p-1"
onClick={props.onRemoveFilter}

View file

@ -14,6 +14,7 @@ function FilterList(props: Props) {
const filters = filter.filters;
const hasEvents = filter.filters.filter(i => i.isEvent).size > 0;
const hasFilters = filter.filters.filter(i => !i.isEvent).size > 0;
let rowIndex = 0;
const onRemoveFilter = (filterIndex) => {
const newFilters = filters.filter((_filter, i) => {
@ -50,7 +51,7 @@ function FilterList(props: Props) {
</div>
{filters.map((filter, filterIndex) => filter.isEvent ? (
<FilterItem
filterIndex={filterIndex}
filterIndex={rowIndex++}
filter={filter}
onUpdate={(filter) => props.onUpdateFilter(filterIndex, filter)}
onRemoveFilter={() => onRemoveFilter(filterIndex) }

View file

@ -0,0 +1,3 @@
.optionItem {
}

View file

@ -1,6 +1,8 @@
import React from 'react';
import { Icon } from 'UI';
import { connect } from 'react-redux';
import cn from 'classnames';
import stl from './FilterModal.css';
interface Props {
filters: any,
@ -16,7 +18,7 @@ function FilterModal(props: Props) {
<div className="uppercase font-medium mb-1">{key}</div>
<div>
{filters[key].map((filter: any) => (
<div className="flex items-center py-2 cursor-pointer hover:bg-gray-lightest -mx-2 px-2" onClick={() => onFilterClick(filter)}>
<div className={cn(stl.optionItem, "flex items-center py-2 cursor-pointer hover:bg-gray-lightest -mx-2 px-2")} onClick={() => onFilterClick(filter)}>
<Icon name={filter.icon} size="16"/>
<span className="ml-2">{filter.label}</span>
</div>

View file

@ -7,7 +7,7 @@
height: 26px;
& .right {
height: 26px;
height: 24px;
display: flex;
align-items: stretch;
padding: 0;

View file

@ -18,11 +18,12 @@ interface Props {
onAddValue?: () => void;
}
function FilterValueDropdown(props: Props) {
const { multiple = false, search = false, options, onChange, value, className = '', showCloseButton = true, showOrButton = true } = props;
const { filter, multiple = false, search = false, options, onChange, value, className = '', showCloseButton = true, showOrButton = true } = props;
// const options = []
return (
<div className={stl.wrapper}>
{ filter.sourceOperatorOptions && <div>test</div> }
<Dropdown
search={search}
className={ cn(stl.operatorDropdown, className) }

View file

@ -1,24 +1,40 @@
import React from 'react';
import stl from './SavedSearchDropdown.css';
import { Icon } from 'UI';
import { applyFilter } from 'Duck/search'
import { connect } from 'react-redux';
interface Props {
list: Array<any>
applyFilter: (filter: any) => void
}
function Row ({ name }) {
function Row ({ name, onClick }) {
return (
<div className="p-2 cursor-pointer hover:bg-gray-lightest">{name}</div>
<div
onClick={onClick}
className="flex items-center cursor-pointer hover:bg-active-blue"
>
<div className="px-3 py-2">{name}</div>
<div className="ml-auto flex items-center">
<div className="cursor-pointer px-2 hover:bg-active-blue"><Icon name="pencil" size="14" /></div>
<div className="cursor-pointer px-2 hover:bg-active-blue"><Icon name="trash" size="14" /></div>
</div>
</div>
)
}
function SavedSearchDropdown(props: Props) {
const onClick = (item) => {
props.applyFilter(item.filter)
}
return (
<div className={stl.wrapper}>
{props.list.map(item => (
<Row key={item.searchId} name={item.name} />
<Row key={item.searchId} name={item.name} onClick={() => onClick(item)} />
))}
</div>
);
}
export default SavedSearchDropdown;
export default connect(null, { applyFilter })(SavedSearchDropdown);

View file

@ -1,4 +1,5 @@
import React from 'react';
import { List } from 'immutable';
import FilterList from 'Shared/Filters/FilterList';
import FilterSelection from 'Shared/Filters/FilterSelection';
import SaveFilterButton from 'Shared/SaveFilterButton';
@ -12,6 +13,8 @@ interface Props {
}
function SessionSearch(props) {
const { appliedFilter } = props;
const hasEvents = appliedFilter.filters.filter(i => i.isEvent).size > 0;
const hasFilters = appliedFilter.filters.filter(i => !i.isEvent).size > 0;
const onAddFilter = (filter) => {
filter.value = [""]
@ -55,16 +58,14 @@ function SessionSearch(props) {
const clearSearch = () => {
props.edit({
filters: [],
filters: List(),
});
}
return (
return (hasEvents || hasFilters) ? (
<div className="border bg-white rounded mt-4">
<div className="p-5">
<FilterList
// filters={appliedFilter.filter.filters.toJS()}
filter={appliedFilter}
onUpdateFilter={onUpdateFilter}
onRemoveFilter={onRemoveFilter}
@ -88,11 +89,9 @@ function SessionSearch(props) {
</div>
</div>
</div>
);
) : <></>;
}
export default connect(state => ({
appliedFilter: state.getIn([ 'search', 'instance' ]),
}), { edit })(SessionSearch);
// appliedFilter: state.getIn([ 'filters', 'appliedFilter' ]),
}), { edit })(SessionSearch);

View file

@ -2,9 +2,10 @@ import React, { useRef, useState } from 'react';
import { connect } from 'react-redux';
import stl from './SessionSearchField.css';
import { Input } from 'UI';
import FilterModal from 'Shared/EventFilter/FilterModal';
import FilterModal from 'Shared/Filters/FilterModal';
import { fetchList as fetchEventList } from 'Duck/events';
import { debounce } from 'App/utils';
import { edit as editFilter } from 'Duck/search';
import {
addEvent, applyFilter, moveEvent, clearEvents,
addCustomFilter, addAttribute, setSearchQuery, setActiveFlow, setFilterOption
@ -13,9 +14,12 @@ import {
interface Props {
setSearchQuery: (query: string) => void;
fetchEventList: (query: any) => void;
searchQuery: string
searchQuery: string;
appliedFilter: any;
editFilter: typeof editFilter;
}
function SessionSearchField(props: Props) {
const { appliedFilter } = props;
const debounceFetchEventList = debounce(props.fetchEventList, 1000)
const [showModal, setShowModal] = useState(false)
@ -24,13 +28,22 @@ function SessionSearchField(props: Props) {
debounceFetchEventList({ q: value });
}
const onAddFilter = (filter) => {
filter.value = [""]
const newFilters = appliedFilter.filters.concat(filter);
props.editFilter({
...appliedFilter.filter,
filters: newFilters,
});
}
return (
<div className="relative">
<Input
inputProps={ { "data-openreplay-label": "Search", "autocomplete": "off" } }
className={stl.searchField}
onFocus={ () => setShowModal(true) }
onBlur={ () => setTimeout(setShowModal, 100, false) }
onBlur={ () => setTimeout(setShowModal, 50, false) }
// ref={ this.inputRef }
onChange={ onSearchChange }
// onKeyUp={this.onKeyUp}
@ -44,21 +57,28 @@ function SessionSearchField(props: Props) {
autocomplete="off"
/>
<FilterModal
{/* <FilterModal
close={ () => setShowModal(false) }
displayed={ showModal }
// displayed={ true }
// loading={ loading }
// searchedEvents={ searchedEvents }
searchQuery={ props.searchQuery }
/>
/> */}
{ showModal && (
<div className="absolute left-0 top-20 border shadow rounded bg-white z-50">
<FilterModal
onFilterClick={onAddFilter}
/>
</div>
)}
</div>
);
}
export default connect(state => ({
events: state.getIn([ 'filters', 'appliedFilter', 'events' ]),
appliedFilter: state.getIn([ 'filters', 'appliedFilter' ]),
// appliedFilter: state.getIn([ 'filters', 'appliedFilter' ]),
searchQuery: state.getIn([ 'filters', 'searchQuery' ]),
appliedFilterKeys: state.getIn([ 'filters', 'appliedFilter', 'filters' ])
.map(({type}) => type).toJS(),
@ -66,4 +86,5 @@ export default connect(state => ({
loading: state.getIn([ 'events', 'loading' ]),
strict: state.getIn([ 'filters', 'appliedFilter', 'strict' ]),
blink: state.getIn([ 'funnels', 'blink' ]),
}), { setSearchQuery, fetchEventList })(SessionSearchField);
appliedFilter: state.getIn(['search', 'instance']),
}), { setSearchQuery, fetchEventList, editFilter })(SessionSearchField);

View file

@ -0,0 +1,143 @@
export const options = [
{
key: 'is',
text: 'is',
value: 'is'
}, {
key: 'isNot',
text: 'is not',
value: 'isNot'
}, {
key: 'startsWith',
text: 'starts with',
value: 'startsWith'
}, {
key: 'endsWith',
text: 'ends with',
value: 'endsWith'
}, {
key: 'contains',
text: 'contains',
value: 'contains'
}, {
key: 'notContains',
text: 'not contains',
value: 'notContains'
}, {
key: 'hasAnyValue',
text: 'has any value',
value: 'hasAnyValue'
}, {
key: 'hasNoValue',
text: 'has no value',
value: 'hasNoValue'
},
{
key: 'isSignedUp',
text: 'is signed up',
value: 'isSignedUp'
}, {
key: 'notSignedUp',
text: 'not signed up',
value: 'notSignedUp'
},
{
key: 'before',
text: 'before',
value: 'before'
}, {
key: 'after',
text: 'after',
value: 'after'
}, {
key: 'on',
text: 'on',
value: 'on'
}, {
key: 'notOn',
text: 'not on',
value: 'notOn'
}, {
key: 'inRage',
text: 'in rage',
value: 'inRage'
}, {
key: 'notInRage',
text: 'not in rage',
value: 'notInRage'
}, {
key: 'withinLast',
text: 'within last',
value: 'withinLast'
}, {
key: 'notWithinLast',
text: 'not within last',
value: 'notWithinLast'
},
{
key: 'greaterThan',
text: 'greater than',
value: 'greaterThan'
}, {
key: 'lessThan',
text: 'less than',
value: 'lessThan'
}, {
key: 'equal',
text: 'equal',
value: 'equal'
}, {
key: 'not equal',
text: 'not equal',
value: 'not equal'
},
{
key: 'onSelector',
text: 'on selector',
value: 'onSelector'
}, {
key: 'onText',
text: 'on text',
value: 'onText'
}, {
key: 'onComponent',
text: 'on component',
value: 'onComponent'
},
{
key: 'onAny',
text: 'on any',
value: 'onAny'
}
];
const filterKeys = ['is', 'isNot'];
const stringFilterKeys = ['is', 'isNot', 'contains', 'startsWith', 'endsWith', 'notContains'];
const targetFilterKeys = ['on', 'notOn', 'onAny'];
const signUpStatusFilterKeys = ['isSignedUp', 'notSignedUp'];
const rangeFilterKeys = ['before', 'after', 'on', 'inRange', 'notInRange', 'withInLast', 'notWithInLast'];
export const baseOperators = options.filter(({key}) => filterKeys.includes(key));
export const stringOperators = options.filter(({key}) => stringFilterKeys.includes(key));
export const targetOperators = options.filter(({key}) => targetFilterKeys.includes(key));
export const booleanOperators = [
{ key: 'true', text: 'true', value: 'true' },
{ key: 'false', text: 'false', value: 'false' },
]
export const customOperators = [
{ key: '=', text: '=', value: '=' },
{ key: '<', text: '<', value: '<' },
{ key: '>', text: '>', value: '>' },
{ key: '<=', text: '<=', value: '<=' },
{ key: '>=', text: '>=', value: '>=' },
]
export default {
options,
baseOperators,
stringOperators,
targetOperators,
booleanOperators,
customOperators,
}

View file

@ -19,3 +19,4 @@ export {
SLACK as CHANNEL_SLACK,
WEBHOOK as CHANNEL_WEBHOOK
} from './schedule';
export { default } from './filterOptions';

View file

@ -5,6 +5,7 @@ import { createFetch, fetchListType, fetchType, saveType, removeType, editType,
import { createRequestReducer, ROOT_KEY } from './funcTools/request';
import { array, request, success, failure, createListUpdater, mergeReducers } from './funcTools/tools';
import Filter from 'Types/filter';
import NewFilter from 'Types/filter/newFilter';
import SavedFilter from 'Types/filter/savedFilter';
import { errors as errorsRoute, isRoute } from "App/routes";
import { fetchList as fetchSessionList } from './sessions';
@ -60,7 +61,7 @@ function reducer(state = initialState, action = {}) {
return state.set("instance", ErrorInfo(action.data));
case success(FETCH_LIST):
const { data } = action;
return state.set("list", List(data.map(CustomMetric)));
return state.set("list", List(data.map(NewFilter)));
}
return state;
}

View file

@ -1,6 +1,6 @@
import Record from 'Types/Record';
import { FilterType, FilterKey, FilterCategory } from './filterType'
import { countries, platformOptions } from 'App/constants';
import filterOptions, { countries, platformOptions } from 'App/constants';
const countryOptions = Object.keys(countries).map(i => ({ text: countries[i], value: i }));
@ -19,198 +19,174 @@ const ISSUE_OPTIONS = [
{ text: 'JS Exception', value: 'js_exception' },
]
const filterKeys = ['is', 'isNot'];
const stringFilterKeys = ['is', 'isNot', 'contains', 'startsWith', 'endsWith', 'notContains'];
const targetFilterKeys = ['on', 'notOn', 'onAny'];
const signUpStatusFilterKeys = ['isSignedUp', 'notSignedUp'];
const rangeFilterKeys = ['before', 'after', 'on', 'inRange', 'notInRange', 'withInLast', 'notWithInLast'];
// const filterKeys = ['is', 'isNot'];
// const stringFilterKeys = ['is', 'isNot', 'contains', 'startsWith', 'endsWith', 'notContains'];
// const targetFilterKeys = ['on', 'notOn', 'onAny'];
// const signUpStatusFilterKeys = ['isSignedUp', 'notSignedUp'];
// const rangeFilterKeys = ['before', 'after', 'on', 'inRange', 'notInRange', 'withInLast', 'notWithInLast'];
const options = [
{
key: 'is',
text: 'is',
value: 'is'
}, {
key: 'isNot',
text: 'is not',
value: 'isNot'
}, {
key: 'startsWith',
text: 'starts with',
value: 'startsWith'
}, {
key: 'endsWith',
text: 'ends with',
value: 'endsWith'
}, {
key: 'contains',
text: 'contains',
value: 'contains'
}, {
key: 'notContains',
text: 'not contains',
value: 'notContains'
}, {
key: 'hasAnyValue',
text: 'has any value',
value: 'hasAnyValue'
}, {
key: 'hasNoValue',
text: 'has no value',
value: 'hasNoValue'
},
// const options = [
// {
// key: 'is',
// text: 'is',
// value: 'is'
// }, {
// key: 'isNot',
// text: 'is not',
// value: 'isNot'
// }, {
// key: 'startsWith',
// text: 'starts with',
// value: 'startsWith'
// }, {
// key: 'endsWith',
// text: 'ends with',
// value: 'endsWith'
// }, {
// key: 'contains',
// text: 'contains',
// value: 'contains'
// }, {
// key: 'notContains',
// text: 'not contains',
// value: 'notContains'
// }, {
// key: 'hasAnyValue',
// text: 'has any value',
// value: 'hasAnyValue'
// }, {
// key: 'hasNoValue',
// text: 'has no value',
// value: 'hasNoValue'
// },
// {
// key: 'isSignedUp',
// text: 'is signed up',
// value: 'isSignedUp'
// }, {
// key: 'notSignedUp',
// text: 'not signed up',
// value: 'notSignedUp'
// },
// {
// key: 'before',
// text: 'before',
// value: 'before'
// }, {
// key: 'after',
// text: 'after',
// value: 'after'
// }, {
// key: 'on',
// text: 'on',
// value: 'on'
// }, {
// key: 'notOn',
// text: 'not on',
// value: 'notOn'
// }, {
// key: 'inRage',
// text: 'in rage',
// value: 'inRage'
// }, {
// key: 'notInRage',
// text: 'not in rage',
// value: 'notInRage'
// }, {
// key: 'withinLast',
// text: 'within last',
// value: 'withinLast'
// }, {
// key: 'notWithinLast',
// text: 'not within last',
// value: 'notWithinLast'
// },
// {
// key: 'greaterThan',
// text: 'greater than',
// value: 'greaterThan'
// }, {
// key: 'lessThan',
// text: 'less than',
// value: 'lessThan'
// }, {
// key: 'equal',
// text: 'equal',
// value: 'equal'
// }, {
// key: 'not equal',
// text: 'not equal',
// value: 'not equal'
// },
// {
// key: 'onSelector',
// text: 'on selector',
// value: 'onSelector'
// }, {
// key: 'onText',
// text: 'on text',
// value: 'onText'
// }, {
// key: 'onComponent',
// text: 'on component',
// value: 'onComponent'
// },
// {
// key: 'onAny',
// text: 'on any',
// value: 'onAny'
// }
// ];
{
key: 'isSignedUp',
text: 'is signed up',
value: 'isSignedUp'
}, {
key: 'notSignedUp',
text: 'not signed up',
value: 'notSignedUp'
},
{
key: 'before',
text: 'before',
value: 'before'
}, {
key: 'after',
text: 'after',
value: 'after'
}, {
key: 'on',
text: 'on',
value: 'on'
}, {
key: 'notOn',
text: 'not on',
value: 'notOn'
}, {
key: 'inRage',
text: 'in rage',
value: 'inRage'
}, {
key: 'notInRage',
text: 'not in rage',
value: 'notInRage'
}, {
key: 'withinLast',
text: 'within last',
value: 'withinLast'
}, {
key: 'notWithinLast',
text: 'not within last',
value: 'notWithinLast'
},
// export const filterOptions = options.filter(({key}) => filterKeys.includes(key));
// export const filterOptions.stringOperators = options.filter(({key}) => stringFilterKeys.includes(key));
// export const filterOptions.targetOperators = options.filter(({key}) => targetFilterKeys.includes(key));
// export const booleanOptions = [
// { key: 'true', text: 'true', value: 'true' },
// { key: 'false', text: 'false', value: 'false' },
// ]
{
key: 'greaterThan',
text: 'greater than',
value: 'greaterThan'
}, {
key: 'lessThan',
text: 'less than',
value: 'lessThan'
}, {
key: 'equal',
text: 'equal',
value: 'equal'
}, {
key: 'not equal',
text: 'not equal',
value: 'not equal'
},
{
key: 'onSelector',
text: 'on selector',
value: 'onSelector'
}, {
key: 'onText',
text: 'on text',
value: 'onText'
}, {
key: 'onComponent',
text: 'on component',
value: 'onComponent'
},
{
key: 'onAny',
text: 'on any',
value: 'onAny'
}
];
export const filterOptions = options.filter(({key}) => filterKeys.includes(key));
export const stringFilterOptions = options.filter(({key}) => stringFilterKeys.includes(key));
export const targetFilterOptions = options.filter(({key}) => targetFilterKeys.includes(key));
export const booleanOptions = [
{ key: 'true', text: 'true', value: 'true' },
{ key: 'false', text: 'false', value: 'false' },
]
export const customOperators = [
{ key: '=', text: '=', value: '=' },
{ key: '<', text: '<', value: '<' },
{ key: '>', text: '>', value: '>' },
{ key: '<=', text: '<=', value: '<=' },
{ key: '>=', text: '>=', value: '>=' },
]
// export const filterOptions.customOperators = [
// { key: '=', text: '=', value: '=' },
// { key: '<', text: '<', value: '<' },
// { key: '>', text: '>', value: '>' },
// { key: '<=', text: '<=', value: '<=' },
// { key: '>=', text: '>=', value: '>=' },
// ]
export const filtersMap = {
[FilterKey.CLICK]: { key: FilterKey.CLICK, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Click', operator: 'on', operatorOptions: targetFilterOptions, icon: 'filters/click', isEvent: true },
[FilterKey.INPUT]: { key: FilterKey.INPUT, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Input', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/input', isEvent: true },
[FilterKey.LOCATION]: { key: FilterKey.LOCATION, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Page', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/location', isEvent: true },
[FilterKey.CUSTOM]: { key: FilterKey.CUSTOM, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Custom Events', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/custom', isEvent: true },
[FilterKey.FETCH]: { key: FilterKey.FETCH, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/fetch', isEvent: true },
[FilterKey.GRAPHQL]: { key: FilterKey.GRAPHQL, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'GraphQL', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/graphql', isEvent: true },
[FilterKey.STATEACTION]: { key: FilterKey.STATEACTION, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'StateAction', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/state-action', isEvent: true },
[FilterKey.ERROR]: { key: FilterKey.ERROR, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Error', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/error', isEvent: true },
// [FilterKey.METADATA]: { key: FilterKey.METADATA, type: FilterType.MULTIPLE, category: FilterCategory.METADATA, label: 'Metadata', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/metadata', isEvent: true },
// EVENTS
[FilterKey.CLICK]: { key: FilterKey.CLICK, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Click', operator: 'on', operatorOptions: filterOptions.targetOperators, icon: 'filters/click', isEvent: true },
[FilterKey.INPUT]: { key: FilterKey.INPUT, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Input', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/input', isEvent: true },
[FilterKey.LOCATION]: { key: FilterKey.LOCATION, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Page', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/location', isEvent: true },
[FilterKey.CUSTOM]: { key: FilterKey.CUSTOM, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Custom Events', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/custom', isEvent: true },
[FilterKey.FETCH]: { key: FilterKey.FETCH, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', isEvent: true },
[FilterKey.GRAPHQL]: { key: FilterKey.GRAPHQL, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'GraphQL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/graphql', isEvent: true },
[FilterKey.STATEACTION]: { key: FilterKey.STATEACTION, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'StateAction', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/state-action', isEvent: true },
[FilterKey.ERROR]: { key: FilterKey.ERROR, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Error', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/error', isEvent: true },
// [FilterKey.METADATA]: { key: FilterKey.METADATA, type: FilterType.MULTIPLE, category: FilterCategory.METADATA, label: 'Metadata', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/metadata', isEvent: true },
[FilterKey.USER_OS]: { key: FilterKey.USER_OS, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User OS', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/os' },
[FilterKey.USER_BROWSER]: { key: FilterKey.USER_BROWSER, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User Browser', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/browser' },
[FilterKey.USER_DEVICE]: { key: FilterKey.USER_DEVICE, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User Device', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/device' },
[FilterKey.PLATFORM]: { key: FilterKey.PLATFORM, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.GEAR, label: 'Platform', operator: 'is', operatorOptions: filterOptions, icon: 'filters/platform', options: platformOptions },
[FilterKey.REVID]: { key: FilterKey.REVID, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'RevId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/rev-id' },
[FilterKey.REFERRER]: { key: FilterKey.REFERRER, type: FilterType.MULTIPLE, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Referrer', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/referrer' },
[FilterKey.DURATION]: { key: FilterKey.DURATION, type: FilterType.DURATION, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Duration', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/duration' },
[FilterKey.USER_COUNTRY]: { key: FilterKey.USER_COUNTRY, type: FilterType.DROPDOWN, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'User Country', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/country', options: countryOptions },
[FilterKey.CONSOLE]: { key: FilterKey.CONSOLE, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Console', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/console' },
[FilterKey.USERID]: { key: FilterKey.USERID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'UserId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/userid' },
[FilterKey.USERANONYMOUSID]: { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'UserAnonymousId', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/userid' },
[FilterKey.DOM_COMPLETE]: { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'is', operatorOptions: stringFilterOptions, sourcesourceOperatorOptions: customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.LARGEST_CONTENTFUL_PAINT_TIME]: { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint Time', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click', isEvent: true },
// [FilterKey.TIME_BETWEEN_EVENTS]: { key: FilterKey.TIME_BETWEEN_EVENTS, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'Time Between Events', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
[FilterKey.TTFB]: { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'is', operatorOptions: stringFilterOptions, sourceOperatorOptions: customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.AVG_CPU_LOAD]: { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', operator: 'is', operatorOptions: stringFilterOptions, sourceOperatorOptions: customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.AVG_MEMORY_USAGE]: { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', operator: 'is', operatorOptions: stringFilterOptions, sourceOperatorOptions: customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.FETCH_FAILED]: { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Fetch Failed', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click', isEvent: true },
// [FilterKey.AVG_CPU_LOAD]: { key: FilterKey.AVG_CPU_LOAD, type: FilterType.NUMBER, category: 'new', label: 'Avg CPU Load', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
// [FilterKey.AVG_MEMORY_USAGE]: { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.NUMBER, category: 'new', label: 'Avg Memory Usage', operator: 'is', operatorOptions: stringFilterOptions, icon: 'filters/click' },
// [FilterKey.SLOW_SESSION]: { key: FilterKey.SLOW_SESSION, type: FilterType.BOOLEAN, category: 'new', label: 'Slow Session', operator: 'true', operatorOptions: [{ key: 'true', text: 'true', value: 'true' }], icon: 'filters/click' },
// [FilterKey.MISSING_RESOURCE]: { key: FilterKey.MISSING_RESOURCE, type: FilterType.BOOLEAN, category: 'new', label: 'Missing Resource', operator: 'true', operatorOptions: [{ key: 'inImages', text: 'in images', value: 'true' }], icon: 'filters/click' },
// [FilterKey.CLICK_RAGE]: { key: FilterKey.CLICK_RAGE, type: FilterType.BOOLEAN, category: 'new', label: 'Click Rage', operator: 'onAnything', operatorOptions: [{ key: 'onAnything', text: 'on anything', value: 'true' }], icon: 'filters/click' },
[FilterKey.ISSUE]: { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', operator: 'is', operatorOptions: filterOptions, icon: 'filters/click', options: ISSUE_OPTIONS },
// [FilterKey.URL]: { / [TYPES,TYPES. category: 'interactions', label: 'URL', operator: 'is', operatorOptions: stringFilterOptions },
// [FilterKey.CUSTOM]: { / [TYPES,TYPES. category: 'interactions', label: 'Custom', operator: 'is', operatorOptions: stringFilterOptions },
// [FilterKey.METADATA]: { / [TYPES,TYPES. category: 'interactions', label: 'Metadata', operator: 'is', operatorOptions: stringFilterOptions },
// FILTERS
[FilterKey.USER_OS]: { key: FilterKey.USER_OS, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User OS', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/os' },
[FilterKey.USER_BROWSER]: { key: FilterKey.USER_BROWSER, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User Browser', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/browser' },
[FilterKey.USER_DEVICE]: { key: FilterKey.USER_DEVICE, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User Device', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/device' },
[FilterKey.PLATFORM]: { key: FilterKey.PLATFORM, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.GEAR, label: 'Platform', operator: 'is', operatorOptions: filterOptions.baseOperators, icon: 'filters/platform', options: platformOptions },
[FilterKey.REVID]: { key: FilterKey.REVID, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'RevId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/rev-id' },
[FilterKey.REFERRER]: { key: FilterKey.REFERRER, type: FilterType.MULTIPLE, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Referrer', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/referrer' },
[FilterKey.DURATION]: { key: FilterKey.DURATION, type: FilterType.DURATION, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Duration', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/duration' },
[FilterKey.USER_COUNTRY]: { key: FilterKey.USER_COUNTRY, type: FilterType.DROPDOWN, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'User Country', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/country', options: countryOptions },
[FilterKey.CONSOLE]: { key: FilterKey.CONSOLE, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Console', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/console' },
[FilterKey.USERID]: { key: FilterKey.USERID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'UserId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' },
[FilterKey.USERANONYMOUSID]: { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'UserAnonymousId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' },
[FilterKey.DOM_COMPLETE]: { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'is', operatorOptions: filterOptions.stringOperators, sourcesourceOperatorOptions: filterOptions.customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.LARGEST_CONTENTFUL_PAINT_TIME]: { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint Time', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/click', isEvent: true },
// [FilterKey.TIME_BETWEEN_EVENTS]: { key: FilterKey.TIME_BETWEEN_EVENTS, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'Time Between Events', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/click' },
[FilterKey.TTFB]: { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'is', operatorOptions: filterOptions.stringOperators, sourceOperatorOptions: filterOptions.customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.AVG_CPU_LOAD]: { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', operator: 'is', operatorOptions: filterOptions.stringOperators, sourceOperatorOptions: filterOptions.customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.AVG_MEMORY_USAGE]: { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', operator: 'is', operatorOptions: filterOptions.stringOperators, sourceOperatorOptions: filterOptions.customOperators, source: [], icon: 'filters/click', isEvent: true },
[FilterKey.FETCH_FAILED]: { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Fetch Failed', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/click', isEvent: true },
[FilterKey.ISSUE]: { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', operator: 'is', operatorOptions: filterOptions.baseOperators, icon: 'filters/click', options: ISSUE_OPTIONS },
}
export default Record({
@ -240,38 +216,23 @@ export default Record({
options: [],
}, {
keyKey: "_key",
fromJS: ({ key, ...filter }) => ({
...filter,
key,
type: filter.type, // camelCased(filter.type.toLowerCase()),
// key: filter.type === METADATA ? filter.label : filter.key || filter.type, // || camelCased(filter.type.toLowerCase()),
// label: getLabel(filter),
// target: Target(target),
// operator: getOperatorDefault(key),
// value: target ? target.label : filter.value,
// value: typeof value === 'string' ? [value] : value,
// icon: filter.type ? getfilterIcon(filter.type) : 'filters/metadata'
}),
fromJS: ({ value, type, ...filter }) => {
const _filter = filtersMap[type]
return {
...filter,
..._filter,
key: _filter.key,
type: _filter.type, // camelCased(filter.type.toLowerCase()),
value: value
}
},
})
// const NewFilterType = (key, category, icon, isEvent = false) => {
// return {
// key: key,
// category: category,
// label: filterMap[key].label,
// icon: icon,
// isEvent: isEvent,
// operators: filterMap[key].operatorOptions,
// value: [""]
// }
// }
const getOperatorDefault = (type) => {
if (type === MISSING_RESOURCE) return 'true';
if (type === SLOW_SESSION) return 'true';
if (type === CLICK_RAGE) return 'true';
if (type === CLICK) return 'on';
// const getOperatorDefault = (type) => {
// if (type === MISSING_RESOURCE) return 'true';
// if (type === SLOW_SESSION) return 'true';
// if (type === CLICK_RAGE) return 'true';
// if (type === CLICK) return 'on';
return 'is';
}
// return 'is';
// }