From e78f8a2c34566b8e7800748b1c3b68676dea0fc9 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 27 Jan 2022 18:34:38 +0530 Subject: [PATCH] feat(fitlers) - fitlers and custommetrics --- .../shared/Filters/FilterItem/FilterItem.tsx | 2 +- .../shared/Filters/FilterList/FilterList.tsx | 3 +- .../Filters/FilterModal/FilterModal.css | 3 + .../Filters/FilterModal/FilterModal.tsx | 4 +- .../FilterValueDropdown.css | 2 +- .../FilterValueDropdown.tsx | 3 +- .../SavedSearchDropdown.tsx | 24 +- .../shared/SessionSearch/SessionSearch.tsx | 15 +- .../SessionSearchField/SessionSearchField.tsx | 35 +- frontend/app/constants/filterOptions.js | 143 +++++++ frontend/app/constants/index.js | 1 + frontend/app/duck/search.js | 3 +- frontend/app/types/filter/newFilter.js | 397 ++++++++---------- 13 files changed, 392 insertions(+), 243 deletions(-) create mode 100644 frontend/app/components/shared/Filters/FilterModal/FilterModal.css create mode 100644 frontend/app/constants/filterOptions.js diff --git a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx index 75ab72f3a..8c1cffbd9 100644 --- a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx +++ b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx @@ -30,7 +30,7 @@ function FitlerItem(props: Props) { -
+
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) {
{filters.map((filter, filterIndex) => filter.isEvent ? ( props.onUpdateFilter(filterIndex, filter)} onRemoveFilter={() => onRemoveFilter(filterIndex) } diff --git a/frontend/app/components/shared/Filters/FilterModal/FilterModal.css b/frontend/app/components/shared/Filters/FilterModal/FilterModal.css new file mode 100644 index 000000000..88ec3280a --- /dev/null +++ b/frontend/app/components/shared/Filters/FilterModal/FilterModal.css @@ -0,0 +1,3 @@ +.optionItem { + +} \ No newline at end of file diff --git a/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx b/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx index e282ab78f..c1ccc6096 100644 --- a/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx +++ b/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx @@ -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) {
{key}
{filters[key].map((filter: any) => ( -
onFilterClick(filter)}> +
onFilterClick(filter)}> {filter.label}
diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css index b11308759..14574c05e 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css @@ -7,7 +7,7 @@ height: 26px; & .right { - height: 26px; + height: 24px; display: flex; align-items: stretch; padding: 0; diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx index 4b01d544a..b489be676 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx @@ -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 (
+ { filter.sourceOperatorOptions &&
test
} + applyFilter: (filter: any) => void } -function Row ({ name }) { +function Row ({ name, onClick }) { return ( -
{name}
+
+
{name}
+
+
+
+
+
) } function SavedSearchDropdown(props: Props) { + const onClick = (item) => { + props.applyFilter(item.filter) + } return (
{props.list.map(item => ( - + onClick(item)} /> ))}
); } -export default SavedSearchDropdown; \ No newline at end of file +export default connect(null, { applyFilter })(SavedSearchDropdown); \ No newline at end of file diff --git a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx index b9fb60913..370c7977f 100644 --- a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx +++ b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx @@ -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) ? (
- ); + ) : <>; } export default connect(state => ({ appliedFilter: state.getIn([ 'search', 'instance' ]), -}), { edit })(SessionSearch); - -// appliedFilter: state.getIn([ 'filters', 'appliedFilter' ]), \ No newline at end of file +}), { edit })(SessionSearch); \ No newline at end of file diff --git a/frontend/app/components/shared/SessionSearchField/SessionSearchField.tsx b/frontend/app/components/shared/SessionSearchField/SessionSearchField.tsx index 76aac5240..6d9f62cd5 100644 --- a/frontend/app/components/shared/SessionSearchField/SessionSearchField.tsx +++ b/frontend/app/components/shared/SessionSearchField/SessionSearchField.tsx @@ -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 (
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" /> - setShowModal(false) } displayed={ showModal } // displayed={ true } // loading={ loading } // searchedEvents={ searchedEvents } searchQuery={ props.searchQuery } - /> + /> */} + { showModal && ( +
+ +
+ )}
); } 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); \ No newline at end of file + appliedFilter: state.getIn(['search', 'instance']), +}), { setSearchQuery, fetchEventList, editFilter })(SessionSearchField); \ No newline at end of file diff --git a/frontend/app/constants/filterOptions.js b/frontend/app/constants/filterOptions.js new file mode 100644 index 000000000..51fcca4a5 --- /dev/null +++ b/frontend/app/constants/filterOptions.js @@ -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, +} \ No newline at end of file diff --git a/frontend/app/constants/index.js b/frontend/app/constants/index.js index 8ba18841a..239c7478a 100644 --- a/frontend/app/constants/index.js +++ b/frontend/app/constants/index.js @@ -19,3 +19,4 @@ export { SLACK as CHANNEL_SLACK, WEBHOOK as CHANNEL_WEBHOOK } from './schedule'; +export { default } from './filterOptions'; diff --git a/frontend/app/duck/search.js b/frontend/app/duck/search.js index 27091ce04..340e8c433 100644 --- a/frontend/app/duck/search.js +++ b/frontend/app/duck/search.js @@ -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; } diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js index 07628ffe2..281fcfecb 100644 --- a/frontend/app/types/filter/newFilter.js +++ b/frontend/app/types/filter/newFilter.js @@ -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'; -} \ No newline at end of file +// return 'is'; +// } \ No newline at end of file