Skip to content

Commit

Permalink
task/WG-242: Filters Panel react hazmapper (#225)
Browse files Browse the repository at this point in the history
* task/WG-242: Filters Panel react hazmapper

* updating requests and usefeatures hook to handle filters

* addressing multiple network requests and state changes

* added calendar comp for handling date range

* lifting state up to parent comp for date storage

* adding tooltip for date range

* optimizing chunk size by seperating several node packages

* refactoring and cleaning up code for requests and features

---------

Co-authored-by: Taylor Grafft <[email protected]>
Co-authored-by: Taylor Grafft <[email protected]>
Co-authored-by: Taylor Grafft <[email protected]>
Co-authored-by: Taylor Grafft <[email protected]>
  • Loading branch information
5 people authored Apr 30, 2024
1 parent 794e929 commit d96407b
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 9 deletions.
100 changes: 100 additions & 0 deletions react/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"prettier": "^2.7.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-datepicker": "^6.6.0",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-esri-leaflet": "^2.0.1",
Expand Down
108 changes: 108 additions & 0 deletions react/src/components/FiltersPanel/Filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import styles from './Filters.module.css';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

interface FiltersProps {
selectedAssetTypes: string[];
onFiltersChange: (selectedAssetTypes: string[]) => void;
startDate: Date;
setStartDate: (date: Date) => void;
endDate: Date;
setEndDate: (date: Date) => void;
}

interface CustomInputProps {
value?: string;
onClick?: () => void;
}

export const assetTypeOptions = {
Image: 'Image',
Video: 'Video',
PointCloud: 'Point Cloud',
Streetview: 'Streetview',
Questionnaire: 'Questionnaire',
NoAssetVector: 'No Asset Vector',
};

const Filters: React.FC<FiltersProps> = ({
selectedAssetTypes,
onFiltersChange,
startDate,
setStartDate,
endDate,
setEndDate,
}) => {
const handleFilterChange = (assetType: string) => {
if (selectedAssetTypes.includes(assetType)) {
onFiltersChange(selectedAssetTypes.filter((type) => type !== assetType));
} else {
onFiltersChange([...selectedAssetTypes, assetType]);
}
};

const CustomInputWithTooltip = React.forwardRef<
HTMLInputElement,
CustomInputProps
>(({ value, onClick }, ref) => (
<div className={styles.customInputContainer}>
<input
className={styles.customInput}
value={value}
onClick={onClick}
ref={ref}
readOnly
/>
<span
className={styles.tooltip}
title="Choose the date(s) corresponding to when the data collection occurred in the field, not when the data was uploaded to the map project."
>
?
</span>
</div>
));

CustomInputWithTooltip.displayName = 'CustomInputWithTooltip';

return (
<div className={styles.root}>
<h3>Filters</h3>
<h2>Date Range</h2>
<h5>Start Date</h5>
<DatePicker
selected={startDate}
onChange={(date: Date) => setStartDate(date)}
selectsStart
startDate={startDate}
endDate={endDate}
customInput={<CustomInputWithTooltip />}
/>
<h5>End Date</h5>
<DatePicker
selected={endDate}
onChange={(date: Date) => setEndDate(date)}
selectsEnd
startDate={startDate}
endDate={endDate}
minDate={startDate}
customInput={<CustomInputWithTooltip />}
/>
<h2>Asset Types</h2>
{Object.entries(assetTypeOptions).map(([key, value]) => (
<div key={key}>
<label className={styles.filterOption}>
<input
type="checkbox"
checked={selectedAssetTypes.includes(key)}
onChange={() => handleFilterChange(key)}
/>
{value}
</label>
</div>
))}
</div>
);
};

export default Filters;
52 changes: 52 additions & 0 deletions react/src/components/FiltersPanel/Filters.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.root {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
padding-left: 20px;
}

.customInputContainer {
position: relative;
display: inline-block;
}

.customInput {
padding-right: 20px;
width: 73%;
}

.tooltip {
font-weight: bold;
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
}

.filterOption {
display: flex;
align-items: center;
margin-bottom: 8px;
}

.filterLabel {
padding-top: 5px;
}

.filterOption input[type='checkbox'] {
margin-right: 10px;
}

h2 {
padding-top: 9px;
}

h3 {
color: #0f83bd;
}

h5 {
padding-top: 5px;
}
1 change: 1 addition & 0 deletions react/src/components/FiltersPanel/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Filter';
16 changes: 9 additions & 7 deletions react/src/hooks/features/useFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ const useFeatures = ({
projectId,
isPublic,
options,
}: UseFeaturesParams): UseQueryResult<FeatureCollection> => {
assetTypes,
}: UseFeaturesParams & {
assetTypes?: string[];
}): UseQueryResult<FeatureCollection> => {
const featuresRoute = isPublic ? 'public-projects' : 'projects';
const endpoint = `/${featuresRoute}/${projectId}/features/`;
let endpoint = `/${featuresRoute}/${projectId}/features/`;
if (assetTypes?.length) {
endpoint += `?assetType=${assetTypes.join(',')}`;
}

/* TODO_REACT add assets filter in https://tacc-main.atlassian.net/browse/WG-242.
Filter route looks like something like this in v2:
"projects/1027/features/?assetType=image%2Cvideo%2Cpoint_cloud%2Cstreetview%2Cquestionnaire%2Cno_asset_vector&&updates=null&cloneFrom=null&encoder=%5Bobject%20Object%5D&map=%5Bobject%20Map%5D&application=hazmapper"
*/
const query = useGet<FeatureCollection>({
endpoint,
key: ['features', { projectId, isPublic }],
key: ['features', { projectId, isPublic, assetTypes }],
options,
});
return query;
Expand Down
Loading

0 comments on commit d96407b

Please sign in to comment.