Commit 8a65116a authored by Viacheslav Pavlov's avatar Viacheslav Pavlov Committed by Matija Obreza

MapPage center+zoom level in URL

- Fixed SSR
- Fixed filterCode + position recognizing in routes
Signed-off-by: Matija Obreza's avatarMatija Obreza <matija.obreza@croptrust.org>
parent ed7e0195
......@@ -53,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) => {
......@@ -98,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));
......@@ -115,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])) {
......@@ -123,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));
......
......@@ -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') }),
......
......@@ -5,6 +5,7 @@ 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';
......@@ -43,6 +44,9 @@ interface IMapPageProps {
loadAccessionsMapInfo: any;
mapLayers: MapLayer[];
showSnackbar: (message: string) => void;
navigateTo: (location: string) => void;
initialPosition: number[];
initialZoom: number;
}
const styles = (theme) => ({
......@@ -77,10 +81,11 @@ const styles = (theme) => ({
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});
},
];
......@@ -107,13 +112,13 @@ 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});
}
}
......@@ -157,6 +162,17 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
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) {
......@@ -188,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) ],
......@@ -221,9 +237,9 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
public render() {
const { searchBox, geoData, otherCount, sidebarOpened, trackClickPos, dialogOpened, climateData} = this.state;
const position = [30, 0];
const { mapInfo, mapLayers, currentTab, classes, filterCode, t, loadAccessionsMapInfo, initialPosition, initialZoom } = this.props;
const { mapInfo, mapLayers, currentTab, classes, filterCode, t, loadAccessionsMapInfo } = this.props;
const position = initialPosition[0] && initialPosition[1] ? initialPosition : [30, 0];
if (! mapInfo) {
return <Loading />;
......@@ -275,10 +291,12 @@ class BrowsePage extends React.Component<IMapPageProps, any> {
<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 }
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>
......@@ -325,11 +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)));
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment