Commit 512b0794 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '202-mappage-center-zoom-level-in-url' into 'master'

MapPage center+zoom level in URL

Closes #202

See merge request genesys-pgr/genesys-ui!204
parents 161ae8ad 1fbae9b8
......@@ -402,7 +402,12 @@
"MCPD": "MCPD",
"zip": "ZIP",
"climateAtCollection": "Climate at origin",
"additionalInfo": "Bioclimatic variables"
"additionalInfo": "Bioclimatic variables",
"climateSimilar": {
"title": "Accessions with similar climatic properties",
"intro": "Georeferenced accesions in Genesys are linked to their climate data based on worldclim.org datasets. Genesys will try to find similar georeferenced accessions that match the basic climatic parameters: annual mean temperature, seasonality and rainfall.",
"view": "List accessions"
}
},
"browse": {
"title": "Accession browser",
......@@ -410,7 +415,11 @@
},
"map": {
"andMore": "And {{otherMore}} more",
"kml": "KML"
"kml": "KML",
"filterAccessions": "Filter accessions",
"pick": "Show climate",
"stopPick": "Cancel",
"noClimateData": "No climate data available for selected location"
}
}
......
......@@ -15,6 +15,7 @@ import { RECEIVE_ACCESSIONS, RECEIVE_ACCESSION, RECEIVE_ACCESSION_OVERVIEW, APPE
import AccessionService from 'service/genesys/AccessionService';
import { showSnackbar } from 'actions/snackbar';
import Page from 'model/Page';
import TileClimate from 'model/genesys/TileClimate';
const receiveAccessions = (paged: FilteredPage<Accession>, error = null) => ({
type: RECEIVE_ACCESSIONS,
......@@ -52,12 +53,12 @@ export const updateRoute = (paged: FilteredPage<Accession>, path: string = '/a')
s: paged.sort[0].property === Accession.DEFAULT_SORT.property ? undefined : paged.sort[0].property,
d: paged.sort[0].direction === Accession.DEFAULT_SORT.direction ? undefined : paged.sort[0].direction,
};
dispatch(updateRoute2(paged.filterCode, path, qs));
dispatch(updateRouteWithFilterCode(paged.filterCode, path, qs));
};
export const updateRoute2 = (filterCode: string, path: string = '/a', qs?: any) => (dispatch) => {
export const updateRouteWithFilterCode = (filterCode: string, path: string = '/a', qs?: any, postfix: string = '') => (dispatch) => {
console.log(`Update route2 ${filterCode} ${path}`, qs);
dispatch(navigateTo(filterCode ? `${path}/${filterCode}` : path, qs));
dispatch(navigateTo(filterCode ? `${path}/${filterCode}${postfix}` : path, qs));
};
export const applyFilters = (filters: string | AccessionFilter, page: IPageRequest = { page: 0 }) => (dispatch) => {
......@@ -97,7 +98,7 @@ export const applyOverviewFilters = (filters: string | AccessionFilter, page: IP
return AccessionService.listOverview(filters)
.then((overview) => {
dispatch(receiveAccessionOverview(overview));
dispatch(updateRoute2(overview.filterCode, '/a/overview'));
dispatch(updateRouteWithFilterCode(overview.filterCode, '/a/overview'));
}).catch((error) => {
console.log(`API error`, error);
dispatch(receiveAccessionOverview(null, error));
......@@ -114,7 +115,7 @@ export const loadAccessionsOverviewPage = (filterCode: string) => (dispatch) =>
});
};
export const loadAccessionsMapInfo = (filters: string | AccessionFilter) => (dispatch) => {
export const loadAccessionsMapInfo = (filters: string | AccessionFilter, viewPort?: {center: number[], zoom: number}) => (dispatch) => {
return AccessionService.mapInfo(filters)
.then((mapInfo: AccessionMapInfo) => {
if (!(mapInfo.bounds[0][0] && mapInfo.bounds[0][1] && mapInfo.bounds[1][0] && mapInfo.bounds[1][1])) {
......@@ -122,7 +123,12 @@ export const loadAccessionsMapInfo = (filters: string | AccessionFilter) => (dis
console.log('One of map bounds is null, setting to default.');
}
dispatch(receiveAccessionMapInfo(mapInfo));
dispatch(updateRoute2(mapInfo.filterCode, '/a/map'));
if (viewPort && viewPort.zoom && viewPort.center && viewPort.center.length === 2) {
console.log(`viewPort @..,z${viewPort.zoom}`, viewPort);
dispatch(updateRouteWithFilterCode(mapInfo.filterCode, '/a/map', null, viewPort && viewPort.center && `/@${viewPort.center[0]},${viewPort.center[1]},${viewPort.zoom}z`));
} else {
dispatch(updateRouteWithFilterCode(mapInfo.filterCode, '/a/map'));
}
}).catch((error) => {
console.log(`API error`, error);
dispatch(receiveAccessionMapInfo(null, error));
......@@ -207,6 +213,68 @@ const receiveTileLayerInfo = (tileLayer: MapLayer) => ({
payload: {tileLayer},
});
export const updateTileLayerInfo = (tileLayer: MapLayer) => (dispatch) => {
export const updateTileLayerInfo = (tileLayer: MapLayer) => (dispatch) => {
return dispatch(receiveTileLayerInfo(tileLayer));
};
const makeRange = (variable: number, diff: number) => {
return {
ge: Math.round(variable - diff),
le: Math.round(variable + diff),
};
};
export const applyClimateFilters = (climate: TileClimate, extraFilters?: any) => (dispatch) => {
// BIO1 = Annual Mean Temperature !!
// BIO2 = Mean Diurnal Range (Mean of monthly (max temp - min temp))
// BIO3 = Isothermality (BIO2/BIO7) (* 100)
// BIO4 = Temperature Seasonality (standard deviation *100)
// BIO5 = Max Temperature of Warmest Month
// BIO6 = Min Temperature of Coldest Month
// BIO7 = Temperature Annual Range (BIO5-BIO6)
// BIO8 = Mean Temperature of Wettest Quarter
// BIO9 = Mean Temperature of Driest Quarter
// BIO10 = Mean Temperature of Warmest Quarter
// BIO11 = Mean Temperature of Coldest Quarter
// BIO12 = Annual Precipitation
// BIO13 = Precipitation of Wettest Month
// BIO14 = Precipitation of Driest Month
// BIO15 = Precipitation Seasonality (Coefficient of Variation)
// BIO16 = Precipitation of Wettest Quarter
// BIO17 = Precipitation of Driest Quarter
// BIO18 = Precipitation of Warmest Quarter !!
// BIO19 = Precipitation of Coldest Quarter !!
const tempDiff = 2;
const filter = {
// taxa: {
// genus: [ accession.taxonomy.genus ],
// // species: [ accession.taxonomy.species ],
// },
geo: {
climate: {
// temperature
bio1: makeRange(climate.bio1, tempDiff),
// bio2: makeRange(climate.bio2, tempDiff),
bio4: makeRange(climate.bio4, climate.bio4 * .50),
// bio7: makeRange(climate.bio7, tempDiff),
// bio8: makeRange(climate.bio8, tempDiff),
// bio9: makeRange(climate.bio9, tempDiff),
// bio10: makeRange(climate.bio10, tempDiff),
// bio11: makeRange(climate.bio11, tempDiff),
// precipitation
bio12: makeRange(climate.bio12, climate.bio12 * .25),
// bio13: makeRange(climate.bio13, precDif),
// bio14: makeRange(climate.bio14, precDif),
// bio15: makeRange(climate.bio15, climate.bio15 * .25),
bio18: makeRange(climate.bio18, climate.bio18 * .25),
bio19: makeRange(climate.bio19, climate.bio19 * .25),
},
},
...extraFilters,
};
dispatch(applyFilters(filter));
};
......@@ -6,6 +6,7 @@ export const RECEIVE_ACCESSION_AUDIT_LOG = 'accessions/RECEIVE_ACCESSION_AUDIT_L
export const RECEIVE_ACCESSION = 'accessions/RECEIVE_ACCESSION';
export const RECEIVE_ACCESSION_MAPINFO = 'accessions/RECEIVE_ACCESSION_MAPINFO';
export const ACCESSION_FILTERFORM = 'Form/Accession/ACCESSION_FILTERFORM';
export const ACCESSION_MAP_FILTERFORM = 'Form/Accession/ACCESSION_MAP_FILTERFORM';
export const ACCESSION_FORM = 'Form/Accession/ACCESSION_FORM';
// Dashboard
......
......@@ -12,6 +12,16 @@ const publicRoutes = [
component: Loadable({ loader: () => import(/* webpackMode:"lazy", webpackChunkName: "accessions" */'accessions/ui/OverviewPage') }),
exact: true,
},
{
path: '/a/map/:filterCode(v.+)?/@:lat,:lng,:zoom?z',
component: Loadable({ loader: () => import(/* webpackMode:"lazy", webpackChunkName: "accessions" */'accessions/ui/MapPage') }),
exact: true,
},
{
path: '/a/map/@:lat,:lng,:zoom?z',
component: Loadable({ loader: () => import(/* webpackMode:"lazy", webpackChunkName: "accessions" */'accessions/ui/MapPage') }),
exact: true,
},
{
path: '/a/map/:filterCode(v.+)?',
component: Loadable({ loader: () => import(/* webpackMode:"lazy", webpackChunkName: "accessions" */'accessions/ui/MapPage') }),
......
......@@ -59,7 +59,12 @@
"MCPD": "MCPD",
"zip": "ZIP",
"climateAtCollection": "Climate at origin",
"additionalInfo": "Bioclimatic variables"
"additionalInfo": "Bioclimatic variables",
"climateSimilar": {
"title": "Accessions with similar climatic properties",
"intro": "Georeferenced accesions in Genesys are linked to their climate data based on worldclim.org datasets. Genesys will try to find similar georeferenced accessions that match the basic climatic parameters: annual mean temperature, seasonality and rainfall.",
"view": "List accessions"
}
},
"browse": {
"title": "Accession browser",
......@@ -67,7 +72,11 @@
},
"map": {
"andMore": "And {{otherMore}} more",
"kml": "KML"
"kml": "KML",
"filterAccessions": "Filter accessions",
"pick": "Show climate",
"stopPick": "Cancel",
"noClimateData": "No climate data available for selected location"
}
}
......
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { translate } from 'react-i18next';
import { withStyles } from '@material-ui/core/styles';
// Actions
import { loadAccession, applyFilters, loadAccessionAuditLog } from 'accessions/actions/public';
import {addAccessionToMyList, removeAccessionFromMyList} from 'list/actions/public';
import { addAccessionToMyList, removeAccessionFromMyList } from 'list/actions/public';
import navigateTo from 'actions/navigation';
// Constants
......@@ -39,11 +39,8 @@ import ImageGalleryView from 'repository/ui/c/ImageGalleryView';
import Button from '@material-ui/core/Button/Button';
import AuditedInfo from 'ui/common/AuditedInfo';
import Authorize from 'ui/common/authorized/Authorize';
import TemperatureChart from './c/TemperatureChart';
import PrecipitationChart from './c/PrecipitationChart';
import ClimateTable from './c/ClimateTable';
import BioClimateDisplay from 'accessions/ui/c/BioClimateDisplay';
import PageTitle from 'ui/common/PageTitle';
import ActionButton from 'ui/common/buttons/ActionButton';
const styles = (theme) => ({
pageSection: {
......@@ -137,66 +134,6 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
applyFilters(filter);
}
private makeRange = (variable: number, diff: number) => {
return {
ge: Math.round(variable - diff),
le: Math.round(variable + diff),
};
}
private applyClimateFilters = () => {
const { accession: {details: accession}, applyFilters } = this.props;
// BIO1 = Annual Mean Temperature !!
// BIO2 = Mean Diurnal Range (Mean of monthly (max temp - min temp))
// BIO3 = Isothermality (BIO2/BIO7) (* 100)
// BIO4 = Temperature Seasonality (standard deviation *100)
// BIO5 = Max Temperature of Warmest Month
// BIO6 = Min Temperature of Coldest Month
// BIO7 = Temperature Annual Range (BIO5-BIO6)
// BIO8 = Mean Temperature of Wettest Quarter
// BIO9 = Mean Temperature of Driest Quarter
// BIO10 = Mean Temperature of Warmest Quarter
// BIO11 = Mean Temperature of Coldest Quarter
// BIO12 = Annual Precipitation
// BIO13 = Precipitation of Wettest Month
// BIO14 = Precipitation of Driest Month
// BIO15 = Precipitation Seasonality (Coefficient of Variation)
// BIO16 = Precipitation of Wettest Quarter
// BIO17 = Precipitation of Driest Quarter
// BIO18 = Precipitation of Warmest Quarter !!
// BIO19 = Precipitation of Coldest Quarter !!
const tempDiff = 2;
const filter = {
taxa: {
genus: [ accession.taxonomy.genus ],
// species: [ accession.taxonomy.species ],
},
geo: {
climate: {
// temperature
bio1: this.makeRange(accession.geo.climate.bio1, tempDiff),
// bio2: this.makeRange(accession.geo.climate.bio2, tempDiff),
bio4: this.makeRange(accession.geo.climate.bio4, accession.geo.climate.bio4 * .50),
// bio7: this.makeRange(accession.geo.climate.bio7, tempDiff),
// bio8: this.makeRange(accession.geo.climate.bio8, tempDiff),
// bio9: this.makeRange(accession.geo.climate.bio9, tempDiff),
// bio10: this.makeRange(accession.geo.climate.bio10, tempDiff),
// bio11: this.makeRange(accession.geo.climate.bio11, tempDiff),
// precipitation
bio12: this.makeRange(accession.geo.climate.bio12, accession.geo.climate.bio12 * .25),
// bio13: this.makeRange(accession.geo.climate.bio13, precDif),
// bio14: this.makeRange(accession.geo.climate.bio14, precDif),
// bio15: this.makeRange(accession.geo.climate.bio15, accession.geo.climate.bio15 * .25),
bio18: this.makeRange(accession.geo.climate.bio18, accession.geo.climate.bio18 * .25),
bio19: this.makeRange(accession.geo.climate.bio19, accession.geo.climate.bio19 * .25),
},
},
};
applyFilters(filter);
}
public render() {
const { t, error, uuid, doi, accessions, auditLog, classes } = this.props;
......@@ -405,36 +342,13 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
</Properties>
{ hasLatLon &&
<LocationMap locations={ [{ id: accession.geo.id, lat: accession.geo.latitude, lng: accession.geo.longitude }] }/>
<LocationMap locations={ [{ id: accession.geo.id, lat: accession.geo.latitude, lng: accession.geo.longitude }] } />
}
</PageSection>
}
{ accession.geo && accession.geo.climate &&
<PageSection title={ t('accessions.public.p.display.climateAtCollection') }>
<GridContainer className="container-spacing-vertical">
<TemperatureChart halfWidth climate={ accession.geo.climate }/>
<PrecipitationChart halfWidth climate={ accession.geo.climate }/>
</GridContainer>
<div>
<ClimateTable climate={ accession.geo.climate }/>
</div>
</PageSection>
}
{ accession.geo && accession.geo.climate &&
<PageSection title={ t('accessions.public.p.display.additionalInfo') }>
<Properties>
{ [...Array(19).keys()].map((i) => (
<PropertiesItem md numeric key={ `month-${i}` } title={ t(`accessions.climate.bio${i + 1}`) }>
{ accession.geo.climate[`bio${i + 1}`] && Number(accession.geo.climate[`bio${i + 1}`]).toFixed(1) }
</PropertiesItem>
)) }
</Properties>
<div>
<ActionButton action={ this.applyClimateFilters } title="View accessions with similar climate" />
</div>
</PageSection>
<BioClimateDisplay climateData={ accession.geo.climate } extraFilters={ { taxa: { genus: [ accession.taxonomy.genus ] } } } />
}
{ accession.remarks && accession.remarks.length > 0 && <PageSection title={ t('accessions.public.p.display.remarks') }>
......
......@@ -4,6 +4,8 @@ import { Link } from 'react-router-dom';
import { translate } from 'react-i18next';
import { withStyles } from '@material-ui/core/styles';
import { bindActionCreators } from 'redux';
import {showSnackbar} from 'actions/snackbar';
import navigateTo from 'actions/navigation';
import { loadAccessionsMapInfo } from 'accessions/actions/public';
import AccessionFilter from 'model/accession/AccessionFilter';
import Loading from 'ui/common/Loading';
......@@ -17,7 +19,11 @@ import ButtonBar from 'ui/common/buttons/ButtonBar';
import ContentLayout from 'ui/layout/ContentLayout';
import MapConfigSection from './c/MapConfigSection';
import ClimateService from 'service/genesys/ClimateService';
import AccessionService from 'service/genesys/AccessionService';
import MapAccessionsFilters from 'accessions/ui/c/MapAccessionsFilters';
import BioClimateDisplay from 'accessions/ui/c/BioClimateDisplay';
import {Dialog, Drawer} from '@material-ui/core';
import PageTitle from 'ui/common/PageTitle';
let Map;
......@@ -37,6 +43,10 @@ interface IMapPageProps {
filterCode: string;
loadAccessionsMapInfo: any;
mapLayers: MapLayer[];
showSnackbar: (message: string) => void;
navigateTo: (location: string) => void;
initialPosition: number[];
initialZoom: number;
}
const styles = (theme) => ({
......@@ -45,15 +55,37 @@ const styles = (theme) => ({
minHeight: '500px',
height: 'calc(100vh - 186px)',
},
crosshair: {
'& > div': {
cursor: 'crosshair !important' as 'crosshair !important',
},
},
climateDialog: {
marginBottom: 0,
overflow: 'auto' as 'auto',
},
filterAccessionsButton: {
position: 'absolute' as 'absolute',
zIndex: 1000,
top: '8px',
left: '48px',
},
pickPositionButton: {
position: 'absolute' as 'absolute',
zIndex: 1000,
top: '48px',
left: '48px',
},
});
class BrowsePage extends React.Component<IMapPageProps, any> {
private clickTimeout;
private mapRef = null;
protected static needs = [
({ params: { filterCode } }) => {
return loadAccessionsMapInfo(filterCode || '');
({ params: { filterCode, initialPosition, initialZoom } }) => {
return loadAccessionsMapInfo(filterCode || '', {center: initialPosition, zoom: initialZoom});
},
];
......@@ -62,6 +94,10 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
searchBox: null,
geoData: [],
otherCount: 0,
sidebarOpened: false,
trackClickPos: false,
dialogOpened: false,
climateData: null,
};
constructor(props, context) {
......@@ -76,18 +112,77 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
public componentWillMount() {
const { mapInfo, filterCode, loadAccessionsMapInfo } = this.props;
const { mapInfo, filterCode, loadAccessionsMapInfo, initialPosition, initialZoom } = this.props;
// console.log(`Filter code for map ${filterCode} ?== ${mapInfo && mapInfo.filterCode}`, filterCode, mapInfo ? mapInfo.filterCode : 'No mapInfo');
if (mapInfo && mapInfo.filterCode !== filterCode) {
// console.log(`mapInfo.filterCode !== filterCode. updatingRoute`);
loadAccessionsMapInfo(filterCode || '');
loadAccessionsMapInfo(filterCode || '', {center: initialPosition, zoom: initialZoom});
} else if (!mapInfo) {
loadAccessionsMapInfo(filterCode || '');
loadAccessionsMapInfo(filterCode || '', {center: initialPosition, zoom: initialZoom});
}
}
private openSidebar = () => {
return this.setState({sidebarOpened: true});
}
private closeSidebar = () => {
return this.setState({sidebarOpened: false});
}
private setPositionPick = (e) => {
e.preventDefault();
e.stopPropagation();
this.setState({trackClickPos: !this.state.trackClickPos});
return false;
}
private handleTrackPosition = (e) => {
const {showSnackbar, t} = this.props;
const { lat, lng } = e.latlng;
this.setState({climateData: null});
ClimateService.getCurrentClimate(lat, lng)
.then((res) => {
// @ts-ignore
if (!res || res === '') {
return showSnackbar(t('accessions.public.p.map.noClimateData'));
}
return this.setState({climateData: res, dialogOpened: true});
})
.catch((error) => {
if (error.code === 404) {
return showSnackbar(t('accessions.public.p.map.noClimateData'));
}
});
}
private hideDialog = () => {
this.setState({dialogOpened: false});
}
private handleMoveEnd = (e) => {
const {navigateTo, filterCode} = this.props;
if (this.mapRef) {
const {viewport: {center, zoom}} = this.mapRef;
// console.log('Updating URL center: ', center, ' Zoom: ', zoom);
if (center && center[0] !== 0 || center[1] !== 0) {
navigateTo(`/a/map${filterCode && `/${filterCode}`}/@${center[0]},${center[1]},${zoom}z`);
}
}
}
private onMapClick = (e) => {
if (e.originalEvent.target.className.indexOf('leaflet-touch') === -1) {
return;
}
if (this.state.trackClickPos) {
return this.handleTrackPosition(e);
}
if (this.clickTimeout) {
console.log('prevented');
clearTimeout(this.clickTimeout);
......@@ -109,7 +204,7 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
console.log(e);
const width = Math.pow(2, currentZoom - 2);
console.log(`zoom=${currentZoom} width=${width} diff=${ 3 / width}`);
// console.log(`zoom=${currentZoom} width=${width} diff=${ 3 / width}`);
const searchBounds: number[][] = [
[ e.latlng.lat - (3 / width), correctLng - (3 / width) ],
[ e.latlng.lat + (3 / width), correctLng + (3 / width) ],
......@@ -125,6 +220,7 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
ge: searchBounds[0][0],
le: searchBounds[1][0],
},
climate: filter && filter.geo && filter.geo.climate,
},
};
AccessionService.geoJson(filterWithGeo, popupContentLimit)
......@@ -140,10 +236,10 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
}
public render() {
const { searchBox, geoData, otherCount } = this.state;
const position = [30, 0];
const { searchBox, geoData, otherCount, sidebarOpened, trackClickPos, dialogOpened, climateData} = this.state;
const { mapInfo, mapLayers, currentTab, classes, filterCode, t, loadAccessionsMapInfo, initialPosition, initialZoom } = this.props;
const { mapInfo, mapLayers, currentTab, classes, filterCode, t } = this.props;
const position = initialPosition[0] && initialPosition[1] ? initialPosition : [30, 0];
if (! mapInfo) {
return <Loading />;
......@@ -160,7 +256,17 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
>
<PageTitle title={ t('accessions.public.p.browse.title') } />
<ContentHeader title={ t('accessions.public.p.browse.title') } subTitle={ t('accessions.public.p.browse.subTitle') } />
<Tabs
<Drawer variant="temporary" open={ sidebarOpened } onClose={ this.closeSidebar }>
<MapAccessionsFilters onSubmit={ loadAccessionsMapInfo } initialValues={ mapInfo && mapInfo.filter }/>
</Drawer>
<Dialog open={ dialogOpened } onClose={ this.hideDialog } maxWidth="md" fullWidth>
<BioClimateDisplay classes={ {section: classes.climateDialog} } climateData={ climateData }/>
</Dialog>
<Tabs
tab={ currentTab }
actions={
<ButtonBar>
......@@ -182,14 +288,19 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
filterObj={ mapInfo && mapInfo.filter || {} }
onSubmit={ this.myApplyFilters }
/>
<div className={ classes.leafletContainer }>
{ mapInfo && typeof window !== 'undefined' &&
<div className={ `${classes.leafletContainer} ${trackClickPos && classes.crosshair}` }>
{ mapInfo && typeof window !== 'undefined' &&
<Map
onMoveend={ this.handleMoveEnd }
onClick={ this.onMapClick }
center={ position }
zoom={ 3 } minZoom={ 2 } maxZoom={ 14 }
bounds={ mapInfo.bounds }>
<TileLayer
zoom={ initialZoom || 3 } minZoom={ 2 } maxZoom={ 14 }
bounds={ !initialZoom && initialPosition[0] && !initialPosition[1] ? mapInfo.bounds : undefined }
ref={ (ref) => this.mapRef = ref }
>
<Button variant="contained" className={ classes.filterAccessionsButton } onClick={ this.openSidebar }>{ t(`accessions.public.p.map.filterAccessions`) }</Button>
<Button variant="contained" className={ classes.pickPositionButton } onClick={ this.setPositionPick }>{ t(`accessions.public.p.map.${ trackClickPos ? 'stopPick' : 'pick'}`) }</Button>
<TileLayer
zIndex={ 0 }
opacity={ 0.50 }
attribution={ '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' }
......@@ -232,10 +343,14 @@ const mapStateToProps = (state, ownProps) => ({
mapLayers: state.accessions.public.mapLayers,
filterCode: ownProps.match.params.filterCode || '',
currentTab: ownProps.match.params.tab || 'map', // current tab, or ownProps.location.pathname
initialPosition: isNaN(Number(ownProps.match.params.lat)) || isNaN(Number(ownProps.match.params.lng)) ? [] : [Number(ownProps.match.params.lat), Number(ownProps.match.params.lng)],
initialZoom: isNaN(Number(ownProps.match.params.zoom)) ? null : Number(ownProps.match.params.zoom),
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadAccessionsMapInfo,
showSnackbar,
navigateTo,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(translate()(BrowsePage)));
import * as React from 'react';