feat(fitlers) - fitlers and custommetrics

This commit is contained in:
Shekar Siri 2022-01-27 23:40:18 +05:30
parent 562f4d976d
commit 985301e1c0
12 changed files with 114 additions and 28 deletions

View file

@ -3,6 +3,7 @@ import FilterOperator from '../FilterOperator';
import FilterSelection from '../FilterSelection';
import FilterValue from '../FilterValue';
import { Icon } from 'UI';
import FilterSource from '../FilterSource';
interface Props {
filterIndex: number;
@ -21,16 +22,40 @@ function FitlerItem(props: Props) {
const onOperatorChange = (e, { name, value }) => {
props.onUpdate({ ...filter, operator: value })
}
const onSourceOperatorChange = (e, { name, value }) => {
props.onUpdate({ ...filter, sourceOperator: value })
}
return (
<div className="flex items-center hover:bg-active-blue -mx-5 px-5 py-2">
<div className="flex items-start w-full">
{ !isFilter && <div className="mt-1 flex-shrink-0 border w-6 h-6 text-xs flex justify-center rounded-full bg-gray-light-shade mr-2">{filterIndex+1}</div> }
<FilterSelection filter={filter} onFilterClick={replaceFilter} />
<FilterOperator filter={filter} onChange={onOperatorChange} className="mx-2 flex-shrink-0"/>
{/* Filter with Source */}
{ filter.hasSource && (
<>
<FilterOperator
options={filter.sourceOperatorOptions}
onChange={onSourceOperatorChange}
className="mx-2 flex-shrink-0"
value={filter.sourceOperator}
/>
<FilterSource filter={filter} onUpdate={props.onUpdate} />
</>
)}
{/* Filter values */}
<FilterOperator
options={filter.operatorOptions}
onChange={onOperatorChange}
className="mx-2 flex-shrink-0"
value={filter.operator}
/>
<FilterValue filter={filter} onUpdate={props.onUpdate} />
</div>
<div className="flex self-start mt-1 ml-auto px-2">
<div className="flex flex-shrink-0 self-start mt-1 ml-auto px-2">
<div
className="cursor-pointer p-1"
onClick={props.onRemoveFilter}

View file

@ -1,3 +1,17 @@
.wrapper {
border-radius: 3px;
border: solid thin $gray-light;
padding: 20px;
}
.optionItem {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
&:hover {
background-color: $active-blue;
color: $teal !important;
& svg {
fill: $teal !important;
}
}
}

View file

@ -11,14 +11,14 @@ interface Props {
function FilterModal(props: Props) {
const { filters, onFilterClick = () => null } = props;
return (
<div className="border p-3" style={{ width: '490px', height: '400px', overflowY: 'auto'}}>
<div className={stl.wrapper} style={{ width: '490px', height: '400px', overflowY: 'auto'}}>
<div className="" style={{ columns: "100px 2" }}>
{filters && Object.keys(filters).map((key) => (
<div className="p-3 aspect-w-1">
<div className="uppercase font-medium mb-1">{key}</div>
<div className="mb-4">
<div className="uppercase font-medium mb-1 color-gray-medium">{key}</div>
<div>
{filters[key].map((filter: any) => (
<div className={cn(stl.optionItem, "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 -mx-2 px-2")} onClick={() => onFilterClick(filter)}>
<Icon name={filter.icon} size="16"/>
<span className="ml-2">{filter.label}</span>
</div>

View file

@ -4,21 +4,21 @@ import { Dropdown, Icon } from 'UI';
import stl from './FilterOperator.css';
interface Props {
filter: any; // event/filter
// filter: any; // event/filter
onChange: (e, { name, value }) => void;
className?: string;
options?: any;
value?: string;
}
function FilterOperator(props: Props) {
const { filter, onChange, className = '' } = props;
console.log('FilterOperator', filter.operator);
const { options, value, onChange, className = '' } = props;
return (
<Dropdown
className={ cn(stl.operatorDropdown, className, 'hover:bg-gray-light-shade') }
options={ filter.operatorOptions }
options={ options }
name="operator"
value={ filter.operator }
value={ value }
onChange={ onChange }
placeholder="Select operator"
icon={ <Icon className="ml-5" name="chevron-down" size="12" /> }

View file

@ -0,0 +1,10 @@
.inputField {
display: inline-block;
margin-right: 10px;
border: solid thin $gray-light;
border-radius: 3px;
height: 26px;
background-color: $white;
padding: 0 5px;
max-width: 100px;
}

View file

@ -0,0 +1,30 @@
import { FilterType } from 'App/types/filter/filterType';
import React from 'react';
import stl from './FilterSource.css';
interface Props {
filter: any,
onUpdate: (filter) => void;
}
function FilterSource(props: Props) {
const { filter } = props;
const onChange = ({ target: { value, name } }) => {
props.onUpdate({ ...filter, source: [value] })
}
const renderFiled = () => {
switch(filter.sourceType) {
case FilterType.NUMBER:
return <input className={stl.inputField} value={filter.source[0]} onBlur={onChange} type="number" />
}
}
return (
<div>
{ renderFiled()}
</div>
);
}
export default FilterSource;

View file

@ -0,0 +1 @@
export { default } from './FilterSource';

View file

@ -22,7 +22,7 @@ function FilterValue(props: Props) {
props.onUpdate({ ...filter, value: newValues })
}
const onSelect = (e, item, valueIndex) => {
const onChange = (e, item, valueIndex) => {
const newValues = filter.value.map((_, _index) => {
if (_index === valueIndex) {
return item.value;
@ -61,7 +61,7 @@ function FilterValue(props: Props) {
value={value}
filter={filter}
options={filter.options}
onChange={(e, { name, value }) => onSelect(e, { value }, valueIndex)}
onChange={(e, { name, value }) => onChange(e, { value }, valueIndex)}
/>
)
case FilterType.ISSUE:
@ -72,7 +72,7 @@ function FilterValue(props: Props) {
value={value}
filter={filter}
options={filter.options}
onChange={(e, { name, value }) => onSelect(e, { value }, valueIndex)}
onChange={(e, { name, value }) => onChange(e, { value }, valueIndex)}
onAddValue={onAddValue}
onRemoveValue={() => onRemoveValue(valueIndex)}
showCloseButton={showCloseButton}
@ -96,7 +96,7 @@ function FilterValue(props: Props) {
type="number"
name={`${filter.key}-${valueIndex}`}
value={value}
onChange={(e) => onSelect(e, { value: e.target.value }, valueIndex)}
onChange={(e) => onChange(e, { value: e.target.value }, valueIndex)}
/>
)
case FilterType.MULTIPLE:
@ -112,7 +112,7 @@ function FilterValue(props: Props) {
params={{ type: filter.key }}
headerText={''}
// placeholder={''}
onSelect={(e, item) => onSelect(e, item, valueIndex)}
onSelect={(e, item) => onChange(e, item, valueIndex)}
/>
)
}

View file

@ -24,8 +24,6 @@ Object.keys(filtersMap).forEach(key => {
filterOptions[filter.category] = [filter];
}
})
console.log('filterOptions', filterOptions)
// for (var i = 0; i < newFiltersList.length; i++) {

View file

@ -74,13 +74,14 @@ export default mergeReducers(
}),
);
const filterMap = ({value, type, key, operator, source, custom, isEvent }) => ({
// value: Array.isArray(value) ? value: [value],
const filterMap = ({value, key, operator, sourceOperator, source, custom, isEvent }) => ({
value: value.filter(i => i !== '' && i !== null),
custom,
type: key,
key, operator,
// key,
operator,
source,
sourceOperator,
isEvent
});

View file

@ -46,6 +46,7 @@ export default Record({
consoleLevel: undefined,
strict: false,
eventsOrder: 'and',
sourceOperator: '',
}, {
idKey: 'searchId',
methods: {

View file

@ -179,7 +179,9 @@ export const filtersMap = {
[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 },
// PERFORMANCE
[FilterKey.DOM_COMPLETE]: { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'is', operatorOptions: filterOptions.stringOperators, sourceOperatorOptions: filterOptions.customOperators, source: [], icon: 'filters/click', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER },
[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 },
@ -202,15 +204,19 @@ export default Record({
custom: '',
// target: Target(),
level: '',
source: null,
hasNoValue: false,
isFilter: false,
actualValue: '',
operator: '',
hasSource: false,
source: [""],
sourceType: '',
sourceOperator: '=',
operatorOptions: [],
sourceOptions: [],
sourceOperatorOptions: [],
operator: '',
operatorOptions: [],
isEvent: false,
index: 0,
options: [],