feat(ui) - filters fixes
This commit is contained in:
parent
49adef4971
commit
fe265eb247
10 changed files with 57 additions and 32 deletions
|
|
@ -28,9 +28,9 @@ export default class FunnelSaveModal extends React.PureComponent {
|
|||
onChangeOption = (e, { checked, name }) => this.props.edit({ [ name ]: checked })
|
||||
|
||||
onSave = () => {
|
||||
const { funnel, closeHandler } = this.props;
|
||||
const { funnel, filter } = this.props;
|
||||
if (funnel.name.trim() === '') return;
|
||||
this.props.save({ ...funnel, filter: filter }).then(function() {
|
||||
this.props.save(funnel).then(function() {
|
||||
this.props.fetchFunnelsList();
|
||||
this.props.closeHandler();
|
||||
}.bind(this));
|
||||
|
|
|
|||
|
|
@ -45,8 +45,7 @@ function FilterAutoComplete(props: Props) {
|
|||
const [query, setQuery] = useState(value);
|
||||
|
||||
|
||||
const requestValues = (q) => {
|
||||
// const { params, method } = props;
|
||||
const requestValues = (q) => {
|
||||
setLoading(true);
|
||||
|
||||
return new APIClient()[method?.toLowerCase()](endpoint, { ...params, q })
|
||||
|
|
@ -55,13 +54,7 @@ function FilterAutoComplete(props: Props) {
|
|||
if (errors) {
|
||||
// this.setError();
|
||||
} else {
|
||||
setOptions(data);
|
||||
// this.setState({
|
||||
// ddOpen: true,
|
||||
// values: data,
|
||||
// loading: false,
|
||||
// noResultsMessage: NO_RESULTS_MSG,
|
||||
// });
|
||||
setOptions(data);
|
||||
}
|
||||
}).finally(() => setLoading(false));
|
||||
// .catch(this.setError);
|
||||
|
|
@ -81,6 +74,17 @@ function FilterAutoComplete(props: Props) {
|
|||
debouncedRequestValues(query)
|
||||
}, [query])
|
||||
|
||||
useEffect(() => {
|
||||
if(value === '') {
|
||||
setQuery(value);
|
||||
}
|
||||
}, [value])
|
||||
|
||||
const onBlur = (e) => {
|
||||
setTimeout(() => { setShowModal(false) }, 200)
|
||||
props.onSelect(e, { value: query })
|
||||
}
|
||||
|
||||
const onItemClick = (e, item) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
|
@ -103,7 +107,7 @@ function FilterAutoComplete(props: Props) {
|
|||
<input
|
||||
name="query"
|
||||
onChange={ onInputChange }
|
||||
onBlur={ () => setTimeout(() => { setShowModal(false) }, 200) }
|
||||
onBlur={ onBlur }
|
||||
onFocus={ () => setShowModal(true)}
|
||||
value={ query }
|
||||
autoFocus={ true }
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ interface Props {
|
|||
}
|
||||
function FilterItem(props: Props) {
|
||||
const { isFilter = false, filterIndex, filter } = props;
|
||||
const canShowValues = !(filter.operator === "isAny" || filter.operator === "onAny");
|
||||
|
||||
const replaceFilter = (filter) => {
|
||||
props.onUpdate({ ...filter, value: [""]});
|
||||
|
|
@ -53,9 +54,7 @@ function FilterItem(props: Props) {
|
|||
className="mx-2 flex-shrink-0"
|
||||
value={filter.operator}
|
||||
/>
|
||||
{ !(filter.operator === "isAny" || filter.operator === "onAny") && (
|
||||
<FilterValue filter={filter} onUpdate={props.onUpdate} />
|
||||
)}
|
||||
{ canShowValues && (<FilterValue filter={filter} onUpdate={props.onUpdate} />) }
|
||||
|
||||
</div>
|
||||
<div className="flex flex-shrink-0 self-start mt-1 ml-auto px-2">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { FilterType } from 'App/types/filter/filterType';
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import stl from './FilterSource.css';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -8,11 +8,22 @@ interface Props {
|
|||
}
|
||||
function FilterSource(props: Props) {
|
||||
const { filter } = props;
|
||||
const [value, setValue] = useState(filter.source[0] || '');
|
||||
|
||||
const onChange = ({ target: { value, name } }) => {
|
||||
props.onUpdate({ ...filter, [name]: [value] })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setValue(filter.source[0] || '');
|
||||
}, [filter])
|
||||
|
||||
useEffect(() => {
|
||||
props.onUpdate({ ...filter, source: [value] })
|
||||
}, [value])
|
||||
|
||||
const write = ({ target: { value, name } }) => setValue(value)
|
||||
|
||||
const renderFiled = () => {
|
||||
switch(filter.sourceType) {
|
||||
case FilterType.NUMBER:
|
||||
|
|
@ -20,9 +31,9 @@ function FilterSource(props: Props) {
|
|||
<input
|
||||
name="source"
|
||||
className={stl.inputField}
|
||||
value={filter.source[0]}
|
||||
onBlur={onChange}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
onBlur={write}
|
||||
onChange={write}
|
||||
type="number"
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ interface Props {
|
|||
function FilterValue(props: Props) {
|
||||
const { filter } = props;
|
||||
const [durationValues, setDurationValues] = useState({ minDuration: filter.value[0], maxDuration: filter.value[1] });
|
||||
const showCloseButton = filter.value.length > 1;
|
||||
const lastIndex = filter.value.length - 1;
|
||||
|
||||
const onAddValue = () => {
|
||||
const newValues = filter.value.concat("")
|
||||
|
|
@ -65,8 +67,7 @@ function FilterValue(props: Props) {
|
|||
}
|
||||
|
||||
const renderValueFiled = (value, valueIndex) => {
|
||||
const showCloseButton = filter.value.length > 1;
|
||||
const showOrButton = valueIndex === filter.value.length - 1;
|
||||
const showOrButton = valueIndex === lastIndex;
|
||||
switch(filter.type) {
|
||||
case FilterType.DROPDOWN:
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -122,6 +122,10 @@ const targetFilterKeys = ['on', 'notOn', 'onAny'];
|
|||
const signUpStatusFilterKeys = ['isSignedUp', 'notSignedUp'];
|
||||
const rangeFilterKeys = ['before', 'after', 'on', 'inRange', 'notInRange', 'withInLast', 'notWithInLast'];
|
||||
|
||||
const getOperatorsByKeys = (keys) => {
|
||||
return options.filter(option => keys.includes(option.key));
|
||||
};
|
||||
|
||||
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));
|
||||
|
|
@ -145,4 +149,5 @@ export default {
|
|||
targetOperators,
|
||||
booleanOperators,
|
||||
customOperators,
|
||||
getOperatorsByKeys,
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import { createItemInListUpdater, mergeReducers, success, array } from './funcTo
|
|||
import { createRequestReducer } from './funcTools/request';
|
||||
import { getDateRangeFromValue } from 'App/dateRange';
|
||||
import { LAST_7_DAYS } from 'Types/app/period';
|
||||
import { filterMap as searchFilterMap } from './search';
|
||||
|
||||
const name = 'funnel';
|
||||
const idKey = 'funnelId';
|
||||
|
|
@ -265,16 +266,20 @@ export const fetchIssueTypes = () => {
|
|||
}
|
||||
}
|
||||
|
||||
export const save = (instance) => {
|
||||
export const save = (instance) => (dispatch, getState) => {
|
||||
// export const save = (instance) => {
|
||||
const filter = getState().getIn([ 'search', 'instance']).toData();
|
||||
filter.filters = filter.filters.map(searchFilterMap);
|
||||
|
||||
const _instance = instance instanceof Funnel ? instance : Funnel(instance);
|
||||
const url = _instance.exists()
|
||||
? `/funnels/${ _instance[idKey] }`
|
||||
: `/funnels`;
|
||||
|
||||
return {
|
||||
return dispatch({
|
||||
types: array(_instance.exists() ? SAVE : UPDATE),
|
||||
call: client => client.post(url, _instance.toData()),
|
||||
}
|
||||
call: client => client.post(url, { ..._instance.toData(), filter }),
|
||||
});
|
||||
}
|
||||
|
||||
export const updateFunnelFilters = (funnelId, filter) => {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import SavedFilter from 'Types/filter/savedFilter';
|
|||
import { errors as errorsRoute, isRoute } from "App/routes";
|
||||
import { fetchList as fetchSessionList } from './sessions';
|
||||
import { fetchList as fetchErrorsList } from './errors';
|
||||
import { FilterCategory, FilterKey } from '../types/filter/filterType';
|
||||
|
||||
const ERRORS_ROUTE = errorsRoute();
|
||||
|
||||
|
|
@ -88,13 +89,12 @@ export default mergeReducers(
|
|||
}),
|
||||
);
|
||||
|
||||
const filterMap = ({value, key, operator, sourceOperator, source, custom, isEvent }) => ({
|
||||
export const filterMap = ({category, value, key, operator, sourceOperator, source, custom, isEvent }) => ({
|
||||
value: value.filter(i => i !== '' && i !== null),
|
||||
custom,
|
||||
type: key,
|
||||
// key,
|
||||
type: category === FilterCategory.METADATA ? FilterKey.METADATA : key,
|
||||
operator,
|
||||
source,
|
||||
source: category === FilterCategory.METADATA ? key : source,
|
||||
sourceOperator,
|
||||
isEvent
|
||||
});
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export default Record({
|
|||
suspicious: undefined,
|
||||
consoleLevel: undefined,
|
||||
strict: false,
|
||||
eventsOrder: 'and',
|
||||
eventsOrder: 'then',
|
||||
}, {
|
||||
idKey: 'searchId',
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ export const filtersMap = {
|
|||
[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.baseOperators, icon: 'filters/duration' },
|
||||
[FilterKey.USER_COUNTRY]: { key: FilterKey.USER_COUNTRY, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'User Country', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/country', options: countryOptions },
|
||||
[FilterKey.DURATION]: { key: FilterKey.DURATION, type: FilterType.DURATION, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Duration', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is']), icon: 'filters/duration' },
|
||||
[FilterKey.USER_COUNTRY]: { key: FilterKey.USER_COUNTRY, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'User Country', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is', 'isAny', 'isNot']), 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: 'User Id', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' },
|
||||
[FilterKey.USERANONYMOUSID]: { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User AnonymousId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue