Skip to content

Commit

Permalink
Added map options
Browse files Browse the repository at this point in the history
  • Loading branch information
raffael-mnhn committed Oct 20, 2022
1 parent 821a4e1 commit eb2e862
Showing 1 changed file with 109 additions and 33 deletions.
142 changes: 109 additions & 33 deletions src/observations.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ import maplibreglWorker from 'maplibre-gl/dist/maplibre-gl-csp-worker';
import {Map as MapGL, Source, Layer, NavigationControl} from 'react-map-gl';
// import SpaIcon from '@mui/icons-material/Spa';
import { parse } from 'wkt';
import { Stack } from '@mui/material';
import { Stack, Autocomplete, TextField as MuiTextField,
FormControl, FormLabel, RadioGroup, FormControlLabel, Radio } from '@mui/material';

maplibregl.workerClass = maplibreglWorker; // part of hack above

const filters = [
<DateInput label="Determined after" alwaysOn source="determined_at_start@gte"/>,
<DateInput label="Determined before" alwaysOn source="determined_at_start@lte"/>,
<TextInput label="Determiner name" source="determined_name@ilike" />,
<DateInput label="Entered after" alwaysOn source="entered_at_start@gte"/>,
<DateInput label="Entered before" alwaysOn source="entered_at_start@lte"/>,
<TextInput label="Entered name" source="entered_name@ilike" />,
<TextInput label="External id" alwaysOn source="external_id"/>,
<DateInput label="Sampled after" alwaysOn source="sampled_at_start@gte"/>,
<DateInput label="Sampled before" alwaysOn source="sampled_at_start@lte"/>,
<TextInput label="Determiner name" source="determiner_name@ilike" />,
<TextInput label="Taxon ListItemKey" source="taxon_list_item_key@eq" alwaysOn />,
<TextInput label="Taxon Name" source="taxon_name@ilike" alwaysOn />,
mkReferenceInput('Species', 'spp'),
Expand Down Expand Up @@ -64,27 +63,38 @@ export const pointLayer = {
type: 'circle',
filter: ["==", ["get", "type"], "Point"],
paint: {
'circle-radius': ['case', ['get', 'highlighted'], 8, 4],
'circle-radius': ['case', ['get', 'highlighted'], 4, 4],
'circle-color': ['case', ['get', 'highlighted'], '#0f0', '#000'],
'circle-stroke-width': ['case', ['get', 'highlighted'], 1, 0],
'circle-opacity': 0.4,
// 'circle-sort-key': 'sort',
}
};

const GeoMap = React.forwardRef(({viewState, setViewState, highlighted}, ref) => {
function getGeography(displayType, record) {
if (displayType === 'polygon') {
return record.location_geography || record.sample_geography;
} else {
return record.location_geography_centroid || record.sample_geography_centroid;
}
}

const GeoMap = React.forwardRef(({viewState, setViewState, highlighted, featureCount, displayType}, ref) => {
// const { data, isLoading } = useListContext();

const {
sort, // a sort object { field, order }, e.g. { field: 'date', order: 'DESC' }
filterValues, // a dictionary of filter values, e.g. { title: 'lorem', nationality: 'fr' }
resource, // the resource name, deduced from the location. e.g. 'posts'
page, // Current page
perPage,
} = useListController();

// eslint-disable-next-line
const { data, __, isLoading, error } = useGetList(
resource,
{
pagination: { page: 1, perPage: 5000 },
pagination: { page: featureCount === 'page' ? page : 1, perPage: featureCount === 'page' ? perPage : '1000' },
sort,
filter: filterValues
}
Expand All @@ -95,9 +105,9 @@ const GeoMap = React.forwardRef(({viewState, setViewState, highlighted}, ref) =>

const featureCollection = {
type: "FeatureCollection",
features: data.filter(r => r.geography !== null).map(r => {
//console.log(r.geography);
const geo = parse(r.geography);
features: data.filter(r => getGeography(displayType, r)).map(r => {
// console.log(r.external_id, r.location_geography, r.sample_geography);
const geo = parse(getGeography(displayType, r));
const hi = r.external_id === highlighted;
return {
type: "Feature",
Expand Down Expand Up @@ -153,6 +163,65 @@ function isUrl(s) {
return s.substring(0, 4) === 'http';
}


function getOptions() {
return [
{label: "foo"},
{label: "bar"}
];
}
const TaxonFilter = () => {
const fetch = React.useMemo(
(request, callback ) => {
// autocompleteService.current.getPlacePredictions(
// request,
// callback,
// );
return getOptions();
},
[],
);

return (
<Autocomplete
options={getOptions()}
renderInput={(params) => <MuiTextField {...params} label="Taxon" />}
/>
);
}

const MapOptions = ({onFeatureCountChange, featureCount,
onDisplayTypeChange, displayType}) => {
return (
<Stack direction="row">
<FormControl>
<FormLabel>Observations on map</FormLabel>
<RadioGroup
row
aria-labelledby="demo-radio-buttons-group-label"
defaultValue="page"
value={featureCount}
onChange={(e) => onFeatureCountChange(e.target.value)}>
<FormControlLabel value="page" control={<Radio />} label="This page" />
<FormControlLabel value="1000" control={<Radio />} label="First 1000 results" />
</RadioGroup>
</FormControl>
<FormControl>
<FormLabel>Display observation as</FormLabel>
<RadioGroup
row
aria-labelledby="demo-radio-buttons-group-label"
defaultValue="page"
value={displayType}
onChange={(e) => onDisplayTypeChange(e.target.value)}>
<FormControlLabel value="centroid" control={<Radio />} label="Center" />
<FormControlLabel value="polygon" control={<Radio />} label="Polygon" />
</RadioGroup>
</FormControl>
</Stack>
);
}

export const ObservationList = () => {
const [viewState, setViewState] = React.useState({
longitude: 6.08,
Expand All @@ -163,18 +232,22 @@ export const ObservationList = () => {
const [highlighted, setHighlighted] = React.useState();
const [imageUrl, setImageUrl] = React.useState();

const [featureCount, setFeatureCount] = React.useState('page');
const [displayType, setDisplayType] = React.useState('centroid');

const mapRef = React.useRef();

const postRowClick = (id, resource, record) => {
if (record.geography) {
const geo = parse(record.geography);
if (getGeography(displayType, record)) {
const geo = parse(getGeography(displayType, record));
let center;
if (geo.type === 'Polygon') {
center = geo['coordinates'][0][0];
} else if (geo.type === 'Point') {
center = geo['coordinates'];
}
setHighlighted(id);
// FIXME: This should probably be handled one up using a callback passet to this component
mapRef.current?.flyTo({center: center, duration: 800});
}

Expand All @@ -195,25 +268,28 @@ export const ObservationList = () => {
<List filters={filters}
pagination={<ObservationPagination />}
aside={<Image url={imageUrl}/>}>
<Stack spacing={2}>
<GeoMap viewState={viewState}
setViewState={setViewState}
highlighted={highlighted}
ref={mapRef} />
<Datagrid rowClick={postRowClick}>
<TextField source="id" />
<TextField source="taxon_name"
sx={{ display: 'inline-block', maxWidth: '20em', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} />
<TextField source="determined_name" />
<DateField source="determined_at_start" />
<DateField source="determined_at_end" />
<TextField source="entered_name" />
<DateField source="entered_at_start" />
<DateField source="entered_at_end" />
<TextField source="source" />
<Stack spacing={2}>
<MapOptions onFeatureCountChange={setFeatureCount}
featureCount={featureCount}
onDisplayTypeChange={setDisplayType}
displayType={displayType} />
<TaxonFilter />
<GeoMap viewState={viewState}
setViewState={setViewState}
highlighted={highlighted}
ref={mapRef}
featureCount={featureCount}
displayType={displayType} />
<Datagrid rowClick={postRowClick}>
<TextField source="id" />
<TextField source="taxon_name"
sx={{ display: 'inline-block', maxWidth: '20em', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} />
<TextField source="sampler_names" />
<DateField source="sampled_at_end" />
<TextField source="source" />
{/* <TextField source="geography" sx={{ display: 'inline-block', maxWidth: '20em', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} /> */}
</Datagrid>
</Stack>
</Datagrid>
</Stack>
</List>
);
}

0 comments on commit eb2e862

Please sign in to comment.