Skip to content

Commit

Permalink
Add option to remove lens search panel filters with click and pass ad…
Browse files Browse the repository at this point in the history
…ditional filters to display
  • Loading branch information
Ryan Herman committed Oct 17, 2024
1 parent a9c9290 commit dd2e0a4
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 43 deletions.
13 changes: 13 additions & 0 deletions src/assets/stylesheets/components/_search-panel-filters.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@
border-bottom: none;
}
}

.search-panel-filters-list-item-remove {
background: transparent;
box-shadow: none;
font-size: 0.8em;
height: 100%;
display: flex;

button {
padding: 0;
color: black;
}
}
}

}
6 changes: 5 additions & 1 deletion src/components/Lens/Lens.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const Lens = ({
placeholder = 'Search',
availableFilters,
showFilters = true,
additionalFilterItems,
hideGeometryFilter = false,
availableLayers = null,
hideNativeLayers = true,
fetchLayerData,
Expand Down Expand Up @@ -182,7 +184,7 @@ const Lens = ({
</div>
)}
{displayFiltersPanel && (
<LensSearchPanelFilters hasFilterCancel={hasFilterCancel} />
<LensSearchPanelFilters hasFilterCancel={hasFilterCancel} hideGeometryFilter={hideGeometryFilter} additionalFilterItems={additionalFilterItems} />
)}
{SidebarComponents && (
<LensSidebarComponents SidebarComponents={SidebarComponents} />
Expand Down Expand Up @@ -252,6 +254,8 @@ Lens.propTypes = {
searchType: PropTypes.string,
placeholder: PropTypes.string,
showFilters: PropTypes.bool,
hideGeometryFilter: PropTypes.bool,
additionalFilterItems: PropTypes.array,
availableFilters: PropTypes.array,
hideNativeLayers: PropTypes.bool,
fetchLayerData: PropTypes.oneOfType([
Expand Down
54 changes: 50 additions & 4 deletions src/components/LensSearchPanelFilters/LensSearchPanelFilters.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';

import { useLens } from '../../hooks';

import SearchPanelFilters from '../SearchPanelFilters';

const LensSearchPanelFilters = (props) => {
const { geoSearch = {}, geoFilters = {} } = useLens();
const { updateSearch } = geoSearch;
const LensSearchPanelFilters = ({ hideGeometryFilter = false, additionalFilterItems = [], ...props }) => {
const { map = {}, geoSearch = {}, geoFilters = {} } = useLens();
const { queryParams: { date, geoJson } = {}, updateSearch } = geoSearch;
const {
filters = {},
openFilters,
cancelFilterChanges,
saveFilterChanges
saveFilterChanges,
removeSingleFilter
} = geoFilters;

function handleSaveFilters () {
Expand All @@ -23,15 +25,59 @@ const LensSearchPanelFilters = (props) => {
});
}

function handleRemoveFilter (filterId) {
const { active } = removeSingleFilter(filterId);
updateSearch({
filters: active
});
}

additionalFilterItems = additionalFilterItems.map(({ onClickParams, ...rest }) => ({
...rest,
onClick: onClickParams && (() => {
map.clearLayers();
updateSearch(onClickParams);
})
}));

if (!hideGeometryFilter && geoJson && geoJson.features && geoJson.features[0]) {
additionalFilterItems.push({
label: 'Geometry',
value: geoJson.features[0].geometry.type === 'Point' ? 'POINT' : 'POLYGON',
onClick: () => {
map.clearLayers();
updateSearch({ geoJson: {} });
}
});
}

if (date && (date.start || date.end)) {
additionalFilterItems.push({
label: 'Datetime',
value: `${(date.start && new Date(date.start).toISOString()) || 'Any'} to ${(date.end && new Date(date.end).toISOString()) || 'Any'}`,
onClick: () => {
map.clearLayers();
updateSearch({ date: {} });
}
});
}

return (
<SearchPanelFilters
filters={filters}
onOpenFilters={openFilters}
onCancelFilterChanges={cancelFilterChanges}
onSaveFiltersChanges={handleSaveFilters}
handleRemoveClick={handleRemoveFilter}
additionalFilterItems={additionalFilterItems}
{...props}
/>
);
};

LensSearchPanelFilters.propTypes = {
hideGeometryFilter: PropTypes.bool,
additionalFilterItems: PropTypes.array
};

export default LensSearchPanelFilters;
2 changes: 1 addition & 1 deletion src/components/SearchFilters/SearchFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ const SearchFilters = ({
id={id}
label={label}
subLabel={subLabel}
value={value || defaultValue}
value={value || defaultValue || range}
range={range}
onChange={handleFilterChange}
/>
Expand Down
66 changes: 37 additions & 29 deletions src/components/SearchFiltersRange/SearchFiltersRange.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,23 @@ const SearchFiltersRange = ({
const [rangeValue, setRangeValue] = useState(value);

useEffect(() => {
if ( maxError === true ) {
handleInputChange({target : { id: 'incidence_angle-range-max', value: valueMaxLocal.toString() }});
if (maxError === true) {
handleInputChange({ target: { id: 'incidence_angle-range-max', value: valueMaxLocal.toString() } });
}
if ( minError === true ) {
handleInputChange({target : { id: 'incidence_angle-range-min', value: valueMinLocal.toString() }});
if (minError === true) {
handleInputChange({ target: { id: 'incidence_angle-range-min', value: valueMinLocal.toString() } });
}
}, [valueMinLocal, valueMaxLocal, rangeValue]);

useEffect(() => {
const { min, max } = value;
if ((min && (rangeValue.min !== min)) || (max && (rangeValue.max !== max))) {
setValueMinLocal(min);
setValueMaxLocal(max);
setRangeValue({ min, max });
}
}, [value]);

/**
* handleInputChange
* @description When the text inputs change, fire away
Expand Down Expand Up @@ -70,20 +79,20 @@ const SearchFiltersRange = ({
if (floatValue < range.min || floatValue > range.max || floatValue > valueMaxLocal) {
updateMinErrorState(true);
return;
} else {
updateMinErrorState(false);
setRangeValue({min: floatValue, max: rangeValue.max});
};
} else {
updateMinErrorState(false);
setRangeValue({ min: floatValue, max: rangeValue.max });
}
break;
case 'max':
setValueMaxLocal(floatValue);
if (floatValue > range.max || floatValue < range.min || floatValue < valueMinLocal) {
updateMaxErrorState(true);
return;
} else {
} else {
updateMaxErrorState(false);
setRangeValue({min: rangeValue.min, max: floatValue});
};
setRangeValue({ min: rangeValue.min, max: floatValue });
}
break;
default:
}
Expand All @@ -102,14 +111,14 @@ const SearchFiltersRange = ({
function handleOnSliderChange (updatedValue) {
handleOnChange(updatedValue);

let cleanedValues = updatedValue;
const cleanedValues = updatedValue;
const { min, max } = cleanedValues;
if ( parseInt(min) % 1 !== 0 ) {
cleanedValues.min = parseInt(parseFloat(cleanedValues.min).toFixed(2));
};
if ( parseInt(max) % 1 !== 0 ) {
cleanedValues.max = parseInt(parseFloat(cleanedValues.max).toFixed(2));
};
if (parseInt(min) % 1 !== 0) {
cleanedValues.min = parseInt(parseFloat(cleanedValues.min).toFixed(2));
}
if (parseInt(max) % 1 !== 0) {
cleanedValues.max = parseInt(parseFloat(cleanedValues.max).toFixed(2));
}

setValueMaxLocal(cleanedValues.max);
setValueMinLocal(cleanedValues.min);
Expand All @@ -118,18 +127,17 @@ const SearchFiltersRange = ({
if (cleanedValues.min < range.min || cleanedValues.min > range.max) {
updateMinErrorState(true);
return;
} else {
updateMinErrorState(false);
setRangeValue(cleanedValues);
};
} else {
updateMinErrorState(false);
setRangeValue(cleanedValues);
}

if (cleanedValues.max > range.max|| cleanedValues.max < range.min) {
if (cleanedValues.max > range.max || cleanedValues.max < range.min) {
updateMaxErrorState(true);
return;
} else {
} else {
updateMaxErrorState(false);
setRangeValue(cleanedValues);
};
}
}

/**
Expand Down Expand Up @@ -187,7 +195,7 @@ const SearchFiltersRange = ({
</div>
)}
<div className="search-filters-range">
<div className={`search-filters-range-input ${minError ? "min-error" : ""} ${maxError ? "max-error" : ""}`}>
<div className={`search-filters-range-input ${minError ? 'min-error' : ''} ${maxError ? 'max-error' : ''}`}>
<FormInputDebounced
id={`${namePrefix}-min`}
type="number"
Expand All @@ -202,8 +210,8 @@ const SearchFiltersRange = ({
value={Math.round(rangeValue.max * 100) / 100}
onChange={handleInputChange}
/>
<span className="error">{`${minError ? "Invalid Min Range" : ""}`}</span>
<span className="error">{`${maxError ? "Invalid Max Range" : ""}`}</span>
<span className="error">{`${minError ? 'Invalid Min Range' : ''}`}</span>
<span className="error">{`${maxError ? 'Invalid Max Range' : ''}`}</span>
</div>
<div className="search-filters-range-slider">
<InputRange
Expand Down
39 changes: 31 additions & 8 deletions src/components/SearchPanelFilters/SearchPanelFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FaPlus, FaCheck, FaTimes, FaEdit } from 'react-icons/fa';
import { findFilterById } from '../../lib/filters';
import { sortByKey } from '../../lib/util';

import Button from '../Button';
import Panel from '../Panel';
import PanelActions from '../PanelActions';
import { ALL_VALUES_ITEM } from '../../data/search-filters';
Expand All @@ -14,7 +15,9 @@ const SearchPanelFilters = ({
onOpenFilters,
onSaveFiltersChanges,
onCancelFilterChanges,
hasFilterCancel = true
hasFilterCancel = true,
additionalFilterItems = [],
handleRemoveClick
}) => {
const { active, isOpen, available } = filters;

Expand Down Expand Up @@ -104,6 +107,7 @@ const SearchPanelFilters = ({
value = `${value}`;

return {
id,
label,
value
};
Expand Down Expand Up @@ -134,15 +138,15 @@ const SearchPanelFilters = ({

function hasActiveFilters (filters) {
const availableValues = filters.map(({ value } = {}) => value);
return availableValues.filter((value) => valueIsValid(value)).length > 0;
return (availableValues.filter((value) => valueIsValid(value)).length > 0 || additionalFilterItems.length > 0);
}

const panelFiltersMapped =
panelFilters &&
panelFilters
const panelFiltersMapped = additionalFilterItems.concat(
(panelFilters || [])
.filter(filterActiveFiltersNoValue)
.filter(({ type } = {}) => type !== 'hidden')
.map(mapActiveFiltersToRow);
.map(mapActiveFiltersToRow)
);

return (
<Panel
Expand All @@ -158,8 +162,25 @@ const SearchPanelFilters = ({
<span>{filter.label}</span>
</div>
<div className="table-cell table-row-first table-column-first table-cell-align-right column-value">
<span>{filter.value}</span>
<span style={{ verticalAlign: 'middle' }}>{filter.value}</span>
</div>
{(handleRemoveClick || filter.onClick) && (
<div className="table-cell" style={{ width: 'auto' }}>
<Button
className="search-panel-filters-list-item-remove"
onClick={() => {
if (filter.onClick) {
filter.onClick();
} else {
handleRemoveClick(filter.id);
}
}}
>
<span className="visually-hidden">Remove Filter</span>
<FaTimes />
</Button>
</div>
)}
</div>
))}
</div>
Expand All @@ -173,7 +194,9 @@ SearchPanelFilters.propTypes = {
onOpenFilters: PropTypes.func,
onSaveFiltersChanges: PropTypes.func,
onCancelFilterChanges: PropTypes.func,
hasFilterCancel: PropTypes.bool
hasFilterCancel: PropTypes.bool,
additionalFilterItems: PropTypes.array,
handleRemoveClick: PropTypes.func
};

export default SearchPanelFilters;
Expand Down
22 changes: 22 additions & 0 deletions src/hooks/useGeoFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ export default function useGeoFilters (filterSettings) {
return setActiveFilters(newFilters, options);
}

/**
* removeSingleFilter
* @description Disables a single activated filter
*/

function removeSingleFilter (filterId) {
const updatedFilterState = {
...filters,
active: filters.active.filter(({ id } = {}) => id !== filterId),
unsaved: filters.unsaved.filter(({ id } = {}) => id !== filterId),
available: filters.available.map(filterInstance => ({
...filterInstance,
value: filterInstance.id === filterId ? undefined : filterInstance.value
}))
};

updateFilters(updatedFilterState);

return updatedFilterState;
}

/**
* saveFilterChanges
* @description Stores any new unsaved changes to active and clears unsaved
Expand Down Expand Up @@ -225,6 +246,7 @@ export default function useGeoFilters (filterSettings) {
saveFilterChanges,
setActiveFilters,
addActiveFilters,
removeSingleFilter,
cancelFilterChanges,
clearActiveFilters
};
Expand Down

0 comments on commit dd2e0a4

Please sign in to comment.