Improved SelectionMap

This commit is contained in:
vjrj 2017-12-11 18:23:24 +01:00
parent 2ef2fee802
commit 29f9a2d476
5 changed files with 106 additions and 76 deletions

View file

@ -1,18 +1,20 @@
import { Meteor } from 'meteor/meteor'; import { Meteor } from 'meteor/meteor';
import { ReactiveVar } from 'meteor/reactive-var';
const geolocation = new ReactiveVar(); const geolocation = new ReactiveVar();
Meteor.startup(function() { Meteor.startup(() => {
Meteor.call("geo", function (error, response) { Meteor.call('geo', (error, response) => {
if (error) { if (error) {
console.warn(error); console.warn(error);
} else { } else {
var pos = [ const pos = [
response.location.latitude, response.location.latitude,
response.location.longitude response.location.longitude
]; ];
geolocation.set(pos); geolocation.set(pos);
} }
}); });
}); });
export default geolocation; export default geolocation;

View file

@ -30,6 +30,7 @@ class DistanceSlider extends React.Component {
}; };
this.onSliderChange = this.onSliderChange.bind(this); this.onSliderChange = this.onSliderChange.bind(this);
this.onAfterChange = this.onAfterChange.bind(this); this.onAfterChange = this.onAfterChange.bind(this);
this.props.onChange(10);
} }
onSliderChange(value) { onSliderChange(value) {

View file

@ -1,8 +1,13 @@
/* global setTimeout */
/* eslint-disable react/jsx-indent-props */
/* eslint-disable import/no-absolute-path */
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Map, TileLayer, Marker, CircleMarker, Circle } from 'react-leaflet'; import { Map, TileLayer, Marker, CircleMarker, Circle } from 'react-leaflet';
import Leaflet from 'leaflet'; import Leaflet from 'leaflet';
import { translate } from 'react-i18next'; import { translate } from 'react-i18next';
import { withTracker } from 'meteor/react-meteor-data';
import update from 'immutability-helper';
import geolocation from '/imports/startup/client/geolocation'; import geolocation from '/imports/startup/client/geolocation';
import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.css'; import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.css';
import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.js'; import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.js';
@ -25,11 +30,11 @@ class SelectionMap extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
center: geolocation.get(), center: props.center,
marker: geolocation.get(), marker: props.center,
zoom: 11, zoom: 11,
draggable: true, distance: props.distance,
modified: false draggable: true
}; };
this.getMap = this.getMap.bind(this); this.getMap = this.getMap.bind(this);
@ -41,7 +46,20 @@ class SelectionMap extends Component {
} }
componentDidMount() { componentDidMount() {
this.addScale(); if (this.isValidState()) {
this.addScale();
}
}
componentWillReceiveProps(nextProps) {
const nextCenter = nextProps.center[0] ? nextProps.center : this.state.center;
const nextMarker = nextProps.center[0] ? nextProps.center : this.state.marker;
this.setState({
center: nextCenter,
marker: nextMarker,
distance: nextProps.distance || this.state.distance
});
this.fit();
} }
componentDidUpdate() { componentDidUpdate() {
@ -58,19 +76,18 @@ class SelectionMap extends Component {
updatePosition() { updatePosition() {
const { lat, lng } = this.marker.leafletElement.getLatLng(); const { lat, lng } = this.marker.leafletElement.getLatLng();
// console.log(`New marker lat ${lat} and lng ${lng}`);
const currentDistance = this.state.distance; const currentDistance = this.state.distance;
this.setState({ this.setState(update(this.state, { $merge: { marker: [lat, lng] } }));
marker: [lat, lng],
modified: true
});
console.log(currentDistance);
this.props.onSelection({ lat, lng, currentDistance }); this.props.onSelection({ lat, lng, currentDistance });
this.fit(); this.fit();
} }
fit() { fit() {
// console.log("fit!"); // console.log("fit!");
this.getMap().fitBounds(this.distanceCircle.leafletElement.getBounds(), [70, 70]); if (this.selectionMap && this.distanceCircle) {
this.getMap().fitBounds(this.distanceCircle.leafletElement.getBounds(), [70, 70]);
}
} }
addScale() { addScale() {
@ -91,69 +108,80 @@ class SelectionMap extends Component {
); );
} }
isValidState() {
return this.state.center && this.state.center[0] && this.state.distance;
}
render() { render() {
this.state.center = !this.state.modified && this.props.lat? [this.props.lat, this.props.lng]: this.state.center; // console.log('render map called');
this.state.marker = !this.state.modified && this.props.lat? [this.props.lat, this.props.lng]: this.state.marker;
this.state.distance = !this.state.modified? this.props.distance: this.state.distance;
this.state.modified = false;
return ( return (
<div> <div>
{ this.state && this.state.center && { this.isValidState() &&
<Map center={this.state.center} zoom={this.state.zoom} <Map
ref={(map) => { this.selectionMap = map; }} center={this.state.center}
sleep={window.location.pathname === '/'} zoom={this.state.zoom}
sleepTime={10750} ref={(map) => { this.selectionMap = map; }}
wakeTime={750} sleep={window.location.pathname === '/'}
sleepNote={true} sleepTime={10750}
hoverToWake={true} wakeTime={750}
wakeMessage={this.props.t('Pulsa para activar')} sleepNote
sleepOpacity={.6}> hoverToWake
<TileLayer wakeMessage={this.props.t('Pulsa para activar')}
attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors" sleepOpacity={0.6}
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" >
/> <TileLayer
<Marker attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
draggable={this.state.draggable} url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
onDragend={this.updatePosition} />
position={this.state.marker} <Marker
icon={positionIcon} draggable={this.state.draggable}
title={this.props.t("Arrastrar para seleccionar otro punto")} onDragend={this.updatePosition}
ref={(ref) => { this.marker = ref; }}> position={this.state.marker}
</Marker> icon={positionIcon}
<CircleMarker title={this.props.t('Arrastrar para seleccionar otro punto')}
center={this.state.marker} color="red" ref={(ref) => { this.marker = ref; }}
stroke={false} />
fillOpacity="1" <CircleMarker
fill={true} center={this.state.marker}
radius={3} /> color="red"
<Circle center={this.state.marker} stroke={false}
fillOpacity="1"
fill
radius={3}
/>
<Circle
center={this.state.marker}
ref={(ref) => { this.distanceCircle = ref; }} ref={(ref) => { this.distanceCircle = ref; }}
color="#145A32" color="#145A32"
fillColor="green" fillColor="green"
fillOpacity={.1} fillOpacity={0.1}
radius={this.state.distance * 1000} /> radius={this.state.distance * 1000}
<Control position="topright" > />
<ButtonToolbar> <Control position="topright" >
<Button bsStyle="success" onClick={(event) => this.doSubs(event)}> <ButtonToolbar>
{this.props.t("Subscribirme a fuegos en este rádio")} <Button
</Button> bsStyle="success"
</ButtonToolbar> onClick={event => this.doSubs(event)}
</Control> >
</Map> } {this.props.t('Subscribirme a fuegos en este rádio')}
</Button>
</ButtonToolbar>
</Control>
</Map> }
</div> </div>
); );
} }
} }
SelectionMap.defaultProps = {
distance: 10
};
SelectionMap.propTypes = { SelectionMap.propTypes = {
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
lat: PropTypes.number, t: PropTypes.func.isRequired,
lng: PropTypes.number, center: PropTypes.array,
distance: PropTypes.number, distance: PropTypes.number,
onSelection: PropTypes.func.isRequired onSelection: PropTypes.func.isRequired
}; };
export default translate([], { wait: true })(SelectionMap); export default translate([], { wait: true })(withTracker(props => ({
center: props.center[0] ? props.center : geolocation.get(),
distance: props.distance
}))(SelectionMap));

View file

@ -67,8 +67,7 @@ class FireSubscription extends React.Component {
</Row> </Row>
<Row className="align-items-center justify-content-center"> <Row className="align-items-center justify-content-center">
<SelectionMap <SelectionMap
lat={this.state.lat} center={[this.state.lat, this.state.lng]}
lng={this.state.lng}
distance={this.state.distance} distance={this.state.distance}
history={this.props.history} history={this.props.history}
onSelection={(state) => this.onSelection(state)} onSelection={(state) => this.onSelection(state)}

View file

@ -9,10 +9,10 @@ class SubsAutocomplete extends React.Component {
super(props); super(props);
this.state = { this.state = {
address: '', address: '',
} };
} }
onChange = (address) => { this.setState({ address }) } onChange = (address) => { this.setState({ address }); }
handleSelect = (address) => { handleSelect = (address) => {
const self = this; const self = this;