feat(ui) - filters global search list
This commit is contained in:
parent
ee02cf8b88
commit
af03760075
6 changed files with 76 additions and 143 deletions
|
|
@ -2,6 +2,8 @@
|
|||
border-radius: 3px;
|
||||
border: solid thin $gray-light;
|
||||
padding: 20px;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.optionItem {
|
||||
white-space: nowrap;
|
||||
|
|
@ -14,4 +16,21 @@
|
|||
fill: $teal !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filterSearchItem {
|
||||
&:hover {
|
||||
background-color: $active-blue;
|
||||
color: $teal;
|
||||
|
||||
& svg {
|
||||
fill: $teal;
|
||||
}
|
||||
}
|
||||
|
||||
& div {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,15 +3,53 @@ import { Icon } from 'UI';
|
|||
import { connect } from 'react-redux';
|
||||
import cn from 'classnames';
|
||||
import stl from './FilterModal.css';
|
||||
import { filtersMap } from 'Types/filter/newFilter'
|
||||
|
||||
interface Props {
|
||||
filters: any,
|
||||
onFilterClick?: (filter) => void
|
||||
onFilterClick?: (filter) => void,
|
||||
filterSearchList: any,
|
||||
}
|
||||
function FilterModal(props: Props) {
|
||||
const { filters, onFilterClick = () => null } = props;
|
||||
const { filters, onFilterClick = () => null, filterSearchList } = props;
|
||||
const hasFilerSearchList = filterSearchList && Object.keys(filterSearchList).length > 0;
|
||||
|
||||
const onFilterSearchClick = (filter) => {
|
||||
const _filter = filtersMap[filter.type];
|
||||
_filter.value = [filter.value];
|
||||
onFilterClick(_filter);
|
||||
}
|
||||
return (
|
||||
<div className={stl.wrapper} style={{ width: '490px', height: '400px', overflowY: 'auto'}}>
|
||||
{ hasFilerSearchList && (
|
||||
<div className="border-b -mx-6 px-6 mb-3">
|
||||
{ filterSearchList && Object.keys(filterSearchList).map((key, index) => {
|
||||
const filter = filterSearchList[key];
|
||||
const option = filtersMap[key];
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={cn('mb-3')}
|
||||
>
|
||||
<div className="font-medium uppercase color-gray-medium text-sm mb-2">{option.label}</div>
|
||||
<div>
|
||||
{filter.map((f, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cn(stl.filterSearchItem, "cursor-pointer px-3 py-1 text-sm flex items-center")}
|
||||
onClick={() => onFilterSearchClick({ type: key, value: f.value })}
|
||||
>
|
||||
<Icon className="mr-2" name={option.icon} size="16" />
|
||||
<div className="whitespace-nowrap text-ellipsis overflow-hidden">{f.value}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="" style={{ columns: "100px 2" }}>
|
||||
{filters && Object.keys(filters).map((key) => (
|
||||
<div className="mb-6">
|
||||
|
|
@ -32,5 +70,6 @@ function FilterModal(props: Props) {
|
|||
}
|
||||
|
||||
export default connect(state => ({
|
||||
filters: state.getIn([ 'filters', 'filterList' ])
|
||||
filters: state.getIn([ 'filters', 'filterList' ]),
|
||||
filterSearchList: state.getIn([ 'search', 'filterSearchList' ])
|
||||
}))(FilterModal);
|
||||
|
|
@ -30,7 +30,7 @@ function SessionSearchField(props: Props) {
|
|||
}
|
||||
|
||||
const onAddFilter = (filter) => {
|
||||
filter.value = [""]
|
||||
filter.value = filter.value ? filter.value : [""]
|
||||
const newFilters = appliedFilter.filters.concat(filter);
|
||||
props.editFilter({
|
||||
...appliedFilter.filter,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const initialState = Map({
|
|||
alertMetricId: null,
|
||||
instance: new Filter({ filters: [] }),
|
||||
savedSearch: null,
|
||||
filterSearchList: List(),
|
||||
filterSearchList: {},
|
||||
});
|
||||
|
||||
// Metric - Series - [] - filters
|
||||
|
|
@ -69,7 +69,17 @@ function reducer(state = initialState, action = {}) {
|
|||
const { data } = action;
|
||||
return state.set("list", List(data.map(SavedFilter)));
|
||||
case success(FETCH_FILTER_SEARCH):
|
||||
return state.set("filterSearchList", action.data.map(NewFilter));
|
||||
const groupedList = action.data.reduce((acc, item) => {
|
||||
const { projectId, type, value } = item;
|
||||
const key = type;
|
||||
if (!acc[key]) {
|
||||
acc[key] = [];
|
||||
}
|
||||
acc[key].push({ projectId, value });
|
||||
return acc;
|
||||
}, {});
|
||||
console.log('groupedList', groupedList);
|
||||
return state.set('filterSearchList', groupedList);
|
||||
case APPLY_SAVED_SEARCH:
|
||||
return state.set('savedSearch', action.filter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export enum FilterKey {
|
|||
REFERRER = "REFERRER",
|
||||
USER_COUNTRY = "USER_COUNTRY",
|
||||
JOURNEY = "JOURNEY",
|
||||
FETCH = "FETCH",
|
||||
REQUEST = "REQUEST",
|
||||
GRAPHQL = "GRAPHQL",
|
||||
STATEACTION = "STATEACTION",
|
||||
REVID = "REVID",
|
||||
|
|
|
|||
|
|
@ -19,148 +19,13 @@ 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 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'
|
||||
// }
|
||||
// ];
|
||||
|
||||
// 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' },
|
||||
// ]
|
||||
|
||||
// export const filterOptions.customOperators = [
|
||||
// { key: '=', text: '=', value: '=' },
|
||||
// { key: '<', text: '<', value: '<' },
|
||||
// { key: '>', text: '>', value: '>' },
|
||||
// { key: '<=', text: '<=', value: '<=' },
|
||||
// { key: '>=', text: '>=', value: '>=' },
|
||||
// ]
|
||||
|
||||
export const filtersMap = {
|
||||
// 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.REQUEST]: { key: FilterKey.REQUEST, 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 },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue