diff --git a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx index c812d373b..cb0e0a7d1 100644 --- a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx @@ -298,14 +298,13 @@ const FilterAutoComplete: React.FC = ({ )} - {showOrButton && ( -
- or -
- )} + {/*{showOrButton && (*/} + {/*
*/} + {/* or*/} + {/*
*/} + {/*)}*/} - {!showOrButton && !hideOrText &&
or
} ); }; diff --git a/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx b/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx index ad73be681..7c79d5d10 100644 --- a/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx @@ -1,90 +1,102 @@ import React, { useState, useEffect } from 'react'; import { Icon } from 'UI'; import stl from './FilterAutoCompleteLocal.module.css'; + interface Props { showOrButton?: boolean; showCloseButton?: boolean; - onRemoveValue?: () => void; - onAddValue?: () => void; + onRemoveValue?: (index: number) => void; + onAddValue?: (index: number) => void; placeholder?: string; - onSelect: (e, item) => void; + onSelect: (e: any, item: Record, index: number) => void; value: any; icon?: string; type?: string; - isMultilple?: boolean; + isMultiple?: boolean; allowDecimals?: boolean; } -function FilterAutoCompleteLocal(props: Props) { +function FilterAutoCompleteLocal(props: Props & { index: number }) { const { - showCloseButton = false, - placeholder = 'Enter', - showOrButton = false, - onRemoveValue = () => null, - onAddValue = () => null, - value = '', - icon = null, - type = "text", - isMultilple = true, - allowDecimals = true, + showCloseButton = false, + placeholder = 'Enter', + showOrButton = false, + onRemoveValue = () => null, + onAddValue = () => null, + value = '', + type = 'text', + isMultiple = true, + allowDecimals = true, + index, } = props; - const [showModal, setShowModal] = useState(true) const [query, setQuery] = useState(value); const onInputChange = (e) => { - if(allowDecimals) { + if (allowDecimals) { const value = e.target.value; setQuery(value); - props.onSelect(null, value); + props.onSelect(null, value, index); } else { - const value = e.target.value.replace(/[^\d]/, ""); + const value = e.target.value.replace(/[^\d]/, ''); if (+value !== 0) { setQuery(value); - props.onSelect(null, value); + props.onSelect(null, value, index); } } }; useEffect(() => { setQuery(value); - }, [value]) - - const onBlur = (e) => { - setTimeout(() => { setShowModal(false) }, 200) - props.onSelect(e, { value: query }) - } + }, [value]); const handleKeyDown = (e) => { if (e.key === 'Enter') { - props.onSelect(e, { value: query }) + props.onSelect(e, { value: query }, index); } - } + }; return (
setShowModal(true)} - value={ query } - autoFocus={ true } - type={ type } - placeholder={ placeholder } + onInput={onInputChange} + value={query} + autoFocus={true} + type={type} + placeholder={placeholder} onKeyDown={handleKeyDown} /> -
- { showCloseButton &&
} - { showOrButton &&
or
} +
+ {showCloseButton && ( +
onRemoveValue(index)}> + +
+ )} + {showOrButton && isMultiple ? ( +
onAddValue(index)} className="color-teal"> + or +
+ ) : null}
- { !showOrButton && isMultilple &&
or
} + {!showOrButton && isMultiple ?
or
: null}
); } -export default FilterAutoCompleteLocal; \ No newline at end of file +function FilterLocalController(props: Props) { + return props.value.map((value, index) => ( + 1} + value={value} + /> + )); +} + +export default FilterLocalController; diff --git a/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx b/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx index 28b5eeba8..d5003cc7c 100644 --- a/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx +++ b/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx @@ -107,7 +107,7 @@ export const getMatchingEntries = ( if (lowerCaseQuery.length === 0) return { - matchingCategories: Object.keys(filters), + matchingCategories: ['ALL', ...Object.keys(filters)], matchingFilters: filters, }; @@ -125,7 +125,7 @@ export const getMatchingEntries = ( } }); - return { matchingCategories, matchingFilters }; + return { matchingCategories: ['ALL', ...matchingCategories], matchingFilters }; }; interface Props { @@ -211,7 +211,7 @@ function FilterModal(props: Props) { return (
(
setCategory(key)} + className={cn('rounded px-4 py-2 hover:bg-active-blue capitalize', key === category ? 'bg-active-blue' : '')} > {key.toLowerCase()}
))}
{displayedFilters.length diff --git a/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx b/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx index bc2e10c34..4aec1ce40 100644 --- a/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx +++ b/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx @@ -10,16 +10,12 @@ const dropdownStyles = { cursor: 'pointer', height: '26px', minHeight: '26px', - backgroundColor: '#f6f6f6', - '&:hover': { - backgroundColor: '#EEEEEE', - }, + backgroundColor: 'white', } return obj; }, valueContainer: (provided: any) => ({ ...provided, - paddingRight: '0px', width: 'fit-content', '& input': { marginTop: '-3px', @@ -29,9 +25,7 @@ const dropdownStyles = { ...provided, }), indicatorsContainer: (provided: any) => ({ - ...provided, - padding: '0px', - height: '26px', + display: 'none', }), // option: (provided: any, state: any) => ({ // ...provided, @@ -39,11 +33,13 @@ const dropdownStyles = { // }), menu: (provided: any, state: any) => ({ ...provided, - top: 20, + marginTop: '0.5rem', left: 0, minWidth: 'fit-content', overflow: 'hidden', zIndex: 100, + border: 'none', + boxShadow: '0px 4px 10px rgba(0,0,0, 0.15)', }), container: (provided: any) => ({ ...provided, diff --git a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx index c7c2758fc..f3a8de136 100644 --- a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx +++ b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx @@ -32,6 +32,10 @@ function FilterSelection(props: Props) { } = props; const [showModal, setShowModal] = useState(false); + const onAddFilter = (filter: any) => { + onFilterClick(filter); + setShowModal(false); + } return (
setShowModal(true)} > @@ -70,14 +72,13 @@ function FilterSelection(props: Props) { > {filter.label}
-
)} {showModal && (
void; - isConditional?: boolean; + filter: any; + onUpdate: (filter: any) => void; + isConditional?: boolean; } function FilterValue(props: Props) { - const { filter } = props; - const [durationValues, setDurationValues] = useState({ - minDuration: filter.value[0], - maxDuration: filter.value.length > 1 ? filter.value[1] : filter.value[0], - }); - const showCloseButton = filter.value.length > 1; - const lastIndex = filter.value.length - 1; + const { filter } = props; + const [durationValues, setDurationValues] = useState({ + minDuration: filter.value[0], + maxDuration: filter.value.length > 1 ? filter.value[1] : filter.value[0], + }); + const showCloseButton = filter.value.length > 1; - const onAddValue = () => { - const newValue = filter.value.concat(''); - props.onUpdate({ ...filter, value: newValue }); - }; + const onAddValue = () => { + const newValue = filter.value.concat(''); + props.onUpdate({ ...filter, value: newValue }); + }; - const onRemoveValue = (valueIndex: any) => { - const newValue = filter.value.filter((_: any, index: any) => index !== valueIndex); - props.onUpdate({ ...filter, value: newValue }); - }; - - const onChange = (e: any, item: any, valueIndex: any) => { - const newValues = filter.value.map((_: any, _index: any) => { - if (_index === valueIndex) { - return item; - } - return _; - }); - props.onUpdate({ ...filter, value: newValues }); - }; - - const debounceOnSelect = React.useCallback(debounce(onChange, 500), [onChange]); - - const onDurationChange = (newValues: any) => { - setDurationValues({ ...durationValues, ...newValues }); - }; - - const handleBlur = () => { - if (filter.type === FilterType.DURATION) { - const { maxDuration, minDuration } = filter; - if (maxDuration || minDuration) return; - if (maxDuration !== durationValues.maxDuration || minDuration !== durationValues.minDuration) { - props.onUpdate({ ...filter, value: [durationValues.minDuration, durationValues.maxDuration] }); - } - } - }; - - const getParms = (key: any) => { - let params: any = { type: filter.key }; - switch (filter.category) { - case FilterCategory.METADATA: - params = { type: FilterKey.METADATA, key: key }; - } - - if (isRoute(ASSIST_ROUTE, window.location.pathname)) { - params = { ...params, live: true }; - } - - return params; - }; - - const renderValueFiled = (value: any, valueIndex: any) => { - const showOrButton = valueIndex === lastIndex && filter.type !== FilterType.NUMBER; - switch (filter.type) { - case FilterType.STRING: - return ( - onRemoveValue(valueIndex)} - onSelect={(e, item) => debounceOnSelect(e, item, valueIndex)} - icon={filter.icon} - /> - ); - case FilterType.DROPDOWN: - return ( - onChange(null, { value }, valueIndex)} - /> - ); - case FilterType.ISSUE: - case FilterType.MULTIPLE_DROPDOWN: - return ( - onChange(null, value, valueIndex)} - onAddValue={onAddValue} - onRemoveValue={() => onRemoveValue(valueIndex)} - showCloseButton={showCloseButton} - showOrButton={showOrButton} - /> - ); - case FilterType.DURATION: - return ( - - ); - case FilterType.NUMBER_MULTIPLE: - return ( - onRemoveValue(valueIndex)} - onSelect={(e, item) => debounceOnSelect(e, item, valueIndex)} - icon={filter.icon} - type="number" - /> - ); - case FilterType.NUMBER: - return ( - onRemoveValue(valueIndex)} - onSelect={(e, item) => debounceOnSelect(e, item, valueIndex)} - icon={filter.icon} - type="number" - allowDecimals={false} - isMultilple={false} - /> - ); - case FilterType.MULTIPLE: - return ( - onRemoveValue(valueIndex)} - method={'GET'} - endpoint="/PROJECT_ID/events/search" - params={getParms(filter.key)} - headerText={''} - placeholder={filter.placeholder} - onSelect={(e, item) => onChange(e, item, valueIndex)} - icon={filter.icon} - /> - ); - } - }; - - return ( -
- {filter.type === FilterType.DURATION - ? renderValueFiled(filter.value, 0) - : filter.value && - filter.value.map((value: any, valueIndex: any) =>
{renderValueFiled(value, valueIndex)}
)} -
+ const onRemoveValue = (valueIndex: any) => { + const newValue = filter.value.filter( + (_: any, index: any) => index !== valueIndex ); + props.onUpdate({ ...filter, value: newValue }); + }; + + const onChange = (e: any, item: any, valueIndex: any) => { + const newValues = filter.value.map((_: any, _index: any) => { + if (_index === valueIndex) { + return item; + } + return _; + }); + props.onUpdate({ ...filter, value: newValues }); + }; + + const debounceOnSelect = React.useCallback(debounce(onChange, 500), [ + onChange, + ]); + + const onDurationChange = (newValues: any) => { + setDurationValues({ ...durationValues, ...newValues }); + }; + + const handleBlur = () => { + if (filter.type === FilterType.DURATION) { + const { maxDuration, minDuration } = filter; + if (maxDuration || minDuration) return; + if ( + maxDuration !== durationValues.maxDuration || + minDuration !== durationValues.minDuration + ) { + props.onUpdate({ + ...filter, + value: [durationValues.minDuration, durationValues.maxDuration], + }); + } + } + }; + + const getParms = (key: any) => { + let params: any = { type: filter.key }; + switch (filter.category) { + case FilterCategory.METADATA: + params = { type: FilterKey.METADATA, key: key }; + } + + if (isRoute(ASSIST_ROUTE, window.location.pathname)) { + params = { ...params, live: true }; + } + + return params; + }; + + const renderValueFiled = (value: any[]) => { + const showOrButton = filter.value.length > 1; + const valueIndex = 0; + const BaseFilterLocalAutoComplete = (props) => ( + onRemoveValue(index)} + onSelect={(e, item, index) => debounceOnSelect(e, item, index)} + icon={filter.icon} + {...props} + /> + ); + switch (filter.type) { + case FilterType.NUMBER_MULTIPLE: + return ; + case FilterType.NUMBER: + return ( + + ); + case FilterType.STRING: + return ; + case FilterType.DROPDOWN: + return ( + onChange(null, { value: item.value }, index)} + /> + ); + case FilterType.ISSUE: + case FilterType.MULTIPLE_DROPDOWN: + return ( + onChange(null, { value: item.value }, index)} + onAddValue={onAddValue} + onRemoveValue={(ind) => onRemoveValue(ind)} + showCloseButton={showCloseButton} + showOrButton={showOrButton} + /> + ); + case FilterType.DURATION: + return ( + + ); + case FilterType.MULTIPLE: + return ( + onRemoveValue(valueIndex)} + method={'GET'} + endpoint="/PROJECT_ID/events/search" + params={getParms(filter.key)} + headerText={''} + placeholder={filter.placeholder} + onSelect={(e, item) => onChange(e, item, valueIndex)} + icon={filter.icon} + /> + ); + } + }; + + return ( +
+ {renderValueFiled(filter.value)} +
+ ); } -export default FilterValue; +// const isEmpty = filter.value.length === 0 || !filter.value[0].length; +// return ( +//
+//
setShowValueModal(true)} className={'flex items-center gap-2 '}> +// {!isEmpty ? ( +// <> +//
+// {filter.value[0]} +//
+//
+// + {filter.value.length - 1} More +//
+// +// ) : ( +//
Select values
+// )} +//
+// {showValueModal ? ( +//
+// {filter.type === FilterType.DURATION +// ? renderValueFiled(filter.value, 0) +// : filter.value && +// filter.value.map((value: any, valueIndex: any) => ( +//
+// {renderValueFiled(value, valueIndex)} +//
+// ))} +//
+// +// +//
+//
+// ) : null} +//
+// ); + +export default observer(FilterValue); diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.module.css b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.module.css index 6e34010b3..913e37c72 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.module.css +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.module.css @@ -13,7 +13,7 @@ display: flex; align-items: stretch; padding: 0; - background-color: $gray-lightest; + background-color: white; border-top-right-radius: 3px; border-bottom-right-radius: 3px; margin-left: auto; diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx index 54509dfc8..2cacad21b 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx @@ -72,26 +72,28 @@ const dropdownStyles = { interface Props { placeholder?: string; value: string; - onChange: (value: any) => void; + onChange: (value: any, ind: number) => void; className?: string; options: any[]; search?: boolean; showCloseButton?: boolean; showOrButton?: boolean; - onRemoveValue?: () => void; - onAddValue?: () => void; - isMultilple?: boolean; + onRemoveValue?: (ind: number) => void; + onAddValue?: (ind: number) => void; + isMultiple?: boolean; + index: number; } function FilterValueDropdown(props: Props) { const { placeholder = 'Select', - isMultilple = true, + isMultiple = true, search = false, options, onChange, value, showCloseButton = true, showOrButton = true, + index, } = props; return ( @@ -102,27 +104,54 @@ function FilterValueDropdown(props: Props) { options={options} name="issue_type" value={value ? options.find((item) => item.value === value) : null} - onChange={(value: any) => onChange(value.value)} + onChange={(value: any) => onChange(value.value, index)} placeholder={placeholder} styles={dropdownStyles} />
{showCloseButton && ( -
+
props.onRemoveValue?.(index)}>
)} {showOrButton && ( -
+
props.onAddValue?.(index)} className="color-teal"> or
)}
- {!showOrButton && isMultilple &&
or
} + {!showOrButton && isMultiple &&
or
}
); } -export default FilterValueDropdown; +interface MainProps { + placeholder?: string; + value: string[]; + onChange: (value: any, ind: number) => void; + className?: string; + options: any[]; + search?: boolean; + showCloseButton?: boolean; + showOrButton?: boolean; + onRemoveValue?: (ind: number) => void; + onAddValue?: (ind: number) => void; + isMultiple?: boolean; +} + +function FilterDropdownController(props: MainProps) { + return props.value.map((value, index) => ( + 1} + /> + )) +} + +export default FilterDropdownController; diff --git a/frontend/app/components/shared/Select/Select.tsx b/frontend/app/components/shared/Select/Select.tsx index f4f5f32a5..ea3e417a7 100644 --- a/frontend/app/components/shared/Select/Select.tsx +++ b/frontend/app/components/shared/Select/Select.tsx @@ -26,19 +26,19 @@ interface Props { } export default function ({ - placeholder = 'Select', - name = '', - onChange, - right = false, - plain = false, - options, - isSearchable = false, - components = {}, - styles = {}, - defaultValue = '', - controlStyle = {}, - ...rest - }: Props) { + placeholder = 'Select', + name = '', + onChange, + right = false, + plain = false, + options, + isSearchable = false, + components = {}, + styles = {}, + defaultValue = '', + controlStyle = {}, + ...rest +}: Props) { const defaultSelected = Array.isArray(defaultValue) ? defaultValue.map((value) => options.find((option) => option.value === value)) : @@ -79,7 +79,7 @@ export default function ({ }), menuList: (provided: any, state: any) => ({ ...provided, - padding: 0 + padding: 0, }), control: (provided: any) => { const obj = { diff --git a/frontend/app/types/filter/filterType.ts b/frontend/app/types/filter/filterType.ts index 0f57a5dcd..5a665e4b5 100644 --- a/frontend/app/types/filter/filterType.ts +++ b/frontend/app/types/filter/filterType.ts @@ -4,7 +4,7 @@ export enum FilterCategory { RECORDING_ATTRIBUTES = 'Recording Attributes', TECHNICAL = 'Technical', USER = 'User Identification', - METADATA = 'Session & User Metadata', + METADATA = 'Metadata', PERFORMANCE = 'Performance', }