diff --git a/src/assets/stylesheets/components/_search-panel-filters.scss b/src/assets/stylesheets/components/_search-panel-filters.scss
index dd1f5dd..70f3cad 100644
--- a/src/assets/stylesheets/components/_search-panel-filters.scss
+++ b/src/assets/stylesheets/components/_search-panel-filters.scss
@@ -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;
+ }
+ }
}
}
diff --git a/src/components/Lens/Lens.js b/src/components/Lens/Lens.js
index 8a92473..5276ba8 100644
--- a/src/components/Lens/Lens.js
+++ b/src/components/Lens/Lens.js
@@ -34,6 +34,8 @@ const Lens = ({
placeholder = 'Search',
availableFilters,
showFilters = true,
+ additionalFilterItems,
+ hideGeometryFilter = false,
availableLayers = null,
hideNativeLayers = true,
fetchLayerData,
@@ -182,7 +184,7 @@ const Lens = ({
)}
{displayFiltersPanel && (
-
+
)}
{SidebarComponents && (
@@ -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([
diff --git a/src/components/LensSearchPanelFilters/LensSearchPanelFilters.js b/src/components/LensSearchPanelFilters/LensSearchPanelFilters.js
index 0e779f2..74494c8 100644
--- a/src/components/LensSearchPanelFilters/LensSearchPanelFilters.js
+++ b/src/components/LensSearchPanelFilters/LensSearchPanelFilters.js
@@ -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 () {
@@ -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 (
);
};
+LensSearchPanelFilters.propTypes = {
+ hideGeometryFilter: PropTypes.bool,
+ additionalFilterItems: PropTypes.array
+};
+
export default LensSearchPanelFilters;
diff --git a/src/components/SearchFilters/SearchFilters.js b/src/components/SearchFilters/SearchFilters.js
index ccafd29..c1f3d49 100644
--- a/src/components/SearchFilters/SearchFilters.js
+++ b/src/components/SearchFilters/SearchFilters.js
@@ -172,7 +172,7 @@ const SearchFilters = ({
id={id}
label={label}
subLabel={subLabel}
- value={value || defaultValue}
+ value={value || defaultValue || range}
range={range}
onChange={handleFilterChange}
/>
diff --git a/src/components/SearchFiltersRange/SearchFiltersRange.js b/src/components/SearchFiltersRange/SearchFiltersRange.js
index 9548e1b..9dfc3b1 100644
--- a/src/components/SearchFiltersRange/SearchFiltersRange.js
+++ b/src/components/SearchFiltersRange/SearchFiltersRange.js
@@ -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
@@ -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:
}
@@ -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);
@@ -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);
- };
+ }
}
/**
@@ -187,7 +195,7 @@ const SearchFiltersRange = ({
)}
-
+
- {`${minError ? "Invalid Min Range" : ""}`}
- {`${maxError ? "Invalid Max Range" : ""}`}
+ {`${minError ? 'Invalid Min Range' : ''}`}
+ {`${maxError ? 'Invalid Max Range' : ''}`}
{
const { active, isOpen, available } = filters;
@@ -104,6 +107,7 @@ const SearchPanelFilters = ({
value = `${value}`;
return {
+ id,
label,
value
};
@@ -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 (
{filter.label}
- {filter.value}
+ {filter.value}
+ {(handleRemoveClick || filter.onClick) && (
+
+
+
+ )}
))}
@@ -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;
diff --git a/src/hooks/useGeoFilters.js b/src/hooks/useGeoFilters.js
index c719eb9..aaa25e8 100644
--- a/src/hooks/useGeoFilters.js
+++ b/src/hooks/useGeoFilters.js
@@ -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
@@ -225,6 +246,7 @@ export default function useGeoFilters (filterSettings) {
saveFilterChanges,
setActiveFilters,
addActiveFilters,
+ removeSingleFilter,
cancelFilterChanges,
clearActiveFilters
};