diff --git a/imports/api/ActiveFires/server/publications.js b/imports/api/ActiveFires/server/publications.js
index d0cf1eb..ac2ff81 100644
--- a/imports/api/ActiveFires/server/publications.js
+++ b/imports/api/ActiveFires/server/publications.js
@@ -1,15 +1,17 @@
/* global Counter */
/* eslint-disable import/no-absolute-path */
+/* eslint-disable prefer-arrow-callback */
import { Meteor } from 'meteor/meteor';
import { check, Match } from 'meteor/check';
-import IPGeocoder from '/imports/startup/server/IPGeocoder';
+import { localize } from '/imports/startup/server/IPGeocoder';
import ActiveFires from '../ActiveFires';
const counter = new Counter('countActiveFires', ActiveFires.find({}));
-
-Meteor.publish('activefirestotal', () => counter);
+Meteor.publish('activefirestotal', function total() {
+ return counter;
+});
const validZoom = Match.Where((zoom) => {
// http://wiki.openstreetmap.org/wiki/Zoom_levels
@@ -54,9 +56,9 @@ const activefires = (zoom, lat, lng, height, width) => {
const distUnt = resolution * Math.max(height, width);
const distance = Math.trunc(distUnt);
// console.log(`so ${height}x${width} gives ${Math.trunc(resolution*height/1000)} x ${Math.trunc(resolution*width/1000)} km, so looking in ${distance}`);
- console.log(`so ${height}x${width} gives ${resolution} of resolution, so looking in ${distance}`);
+ console.log(`So ${height}x${width} gives ${Math.trunc(resolution)} of resolution, so looking in ${Math.trunc(distance / 1000)}km`);
- return ActiveFires.find({
+ const fires = ActiveFires.find({
ourid: {
$near: {
$geometry: {
@@ -74,9 +76,42 @@ const activefires = (zoom, lat, lng, height, width) => {
scan: 1
}
});
+ console.log(`Fires total: ${fires.count()}`);
+ return fires;
};
-Meteor.publish('activefiresmyloc', (zoom, lat, lng, height, width) => {
+
+Meteor.publish('allActiveFires', function allActive() {
+ // latitude -90 and 90 and the longitude between -180 and 180
+
+ const { latitude, longitude } = localize().location;
+ console.log(`${latitude}, ${longitude}`);
+ check(latitude, NumberBetween(-90, 90));
+ check(longitude, NumberBetween(-180, 180));
+ // https://docs.meteor.com/api/collections.html#Mongo-Collection-find
+ return ActiveFires.find({
+ ourid: {
+ $near: {
+ $geometry: {
+ type: 'Point',
+ coordinates: [longitude, latitude]
+ },
+ $minDistance: 0,
+ $maxDistance: 1000 // 156412000
+ }
+ }
+ }, {
+ fields: {
+ _id: 0,
+ lat: 1,
+ lon: 1,
+ scan: 1
+ },
+ maxTimeMs: 30000
+ });
+});
+
+Meteor.publish('activefiresmyloc', function activeInMyLoc(zoom, lat, lng, height, width) {
check(zoom, validZoom);
check(lat, NullOr(Number));
check(lng, NullOr(Number));
@@ -84,19 +119,8 @@ Meteor.publish('activefiresmyloc', (zoom, lat, lng, height, width) => {
check(width, NullOr(Number));
console.log(`Check active fires in ${lat},${lng} with zoom ${zoom} pixels in ${height}x${width} map`);
if (lat === null || lng === null) {
- let clientIP;
- if (this.connection && this.connection.clientAddress) {
- clientIP = this.connection.clientAddress;
- } else {
- console.warn('We cannot get this meteor connection IP');
- clientIP = '127.0.0.1';
- }
- if (clientIP === '127.0.0.1') {
- clientIP = '80.58.61.250'; // Some Spain IP address
- }
- // https://www.npmjs.com/package/maxmind
- const location = IPGeocoder.get(clientIP);
- console.log(location);
+ const location = localize();
+ console.log(`${location.latitude}, ${location.longitude}`);
return activefires(zoom, location.latitude, location.longitude, height, width);
}
return activefires(zoom, lat, lng, height, width);
diff --git a/imports/startup/server/IPGeocoder.js b/imports/startup/server/IPGeocoder.js
index cf0daa5..6cae62b 100644
--- a/imports/startup/server/IPGeocoder.js
+++ b/imports/startup/server/IPGeocoder.js
@@ -1,6 +1,13 @@
+/* eslint-disable prefer-arrow-callback */
+
import { Meteor } from 'meteor/meteor';
import maxmind from 'maxmind';
+process.env.HTTP_FORWARDED_COUNT = Meteor.settings.private.proxies_count;
+if (!Meteor.isDevelopment) {
+ console.log(`Number or proxies (needed for client IP lookup): ${process.env.HTTP_FORWARDED_COUNT}`);
+}
+
// https://stackoverflow.com/questions/13969655/how-do-you-check-whether-the-given-ip-is-internal-or-not
function isPrivateIP(ip) {
const parts = ip.split('.');
@@ -13,22 +20,30 @@ function isPrivateIP(ip) {
const IPGeocoder = maxmind.openSync(`${process.env.PWD}/private/GeoLite2-City.mmdb`);
export default IPGeocoder;
+// Warning: Meteor cannot access to this.connection with arrow functions
+export function localize() {
+ // https://stackoverflow.com/questions/14843232/how-to-get-the-user-ip-address-in-meteor-server/22657421#22657421
+ let clientIP;
+ if (this.connection && this.connection.clientAddress) {
+ clientIP = this.connection.clientAddress;
+ } else {
+ console.warn(`We cannot get this meteor connection IP for this connection (${this.connection})`);
+ clientIP = '127.0.0.1';
+ }
+ if (isPrivateIP(clientIP)) {
+ clientIP = '80.58.61.250'; // Some Spain IP address
+ }
+ // console.log(`Geolocating ${clientIP}`);
+
+ // TODO: cron download GeoLite-City
+ // http://dev.maxmind.com/geoip/geoip2/geolite2/
+ const location = IPGeocoder.get(clientIP);
+ // console.log(location);
+ return location;
+}
+
Meteor.methods({
- geo() {
- // https://stackoverflow.com/questions/14843232/how-to-get-the-user-ip-address-in-meteor-server/22657421#22657421
- let clientIP = this.connection.clientAddress;
-
- if (isPrivateIP(clientIP)) {
- clientIP = '80.58.61.250'; // Some Spain IP address
- }
- // console.log(`Geolocating ${clientIP}`);
-
- // TODO: cron download GeoLite-City
- // http://dev.maxmind.com/geoip/geoip2/geolite2/
- const location = IPGeocoder.get(clientIP);
- // console.log(location);
- return location;
- },
+ geo: localize,
getMapKey() {
// http://meteorpedia.com/read/Environment_Variables
// https://developers.google.com/maps/documentation/javascript/get-api-key
diff --git a/imports/ui/components/Maps/FireList.js b/imports/ui/components/Maps/FireList.js
index 3616ade..60d8b3e 100644
--- a/imports/ui/components/Maps/FireList.js
+++ b/imports/ui/components/Maps/FireList.js
@@ -11,15 +11,17 @@ export default function FireList(props) {
const {
fires, scale, useMarkers, nasa
} = props;
- const items = fires.map(({ _id, ...otherProps }) => {
- if (useMarkers && scale) {
- return ();
- }
- if (!nasa && !scale) {
- return ();
- }
- return ();
- });
+ const useMarks = useMarkers && scale;
+ const usePixel = !nasa || !scale;
+ /* console.log(`Using marks: ${useMarks}, using pixels: ${usePixel}`); */
+ let items;
+ if (useMarks) {
+ items = fires.map(({ _id, ...otherProps }) => ());
+ } else if (usePixel) {
+ items = fires.map(({ _id, ...otherProps }) => ());
+ } else {
+ items = fires.map(({ _id, ...otherProps }) => ());
+ }
return (
{items}
);
}
diff --git a/imports/ui/components/Maps/FirePixel.js b/imports/ui/components/Maps/FirePixel.js
index e480d33..57f2092 100644
--- a/imports/ui/components/Maps/FirePixel.js
+++ b/imports/ui/components/Maps/FirePixel.js
@@ -1,10 +1,19 @@
+/* eslint-disable react/jsx-indent-props */
+
import React from 'react';
import { CircleMarker } from 'react-leaflet';
import PropTypes from 'prop-types';
/* Less acurate (1 pixel per fire) but faster */
const FirePixel = ({ lat, lon, nasa }) => (
-
+
);
diff --git a/imports/ui/components/Navigation/Navigation.js b/imports/ui/components/Navigation/Navigation.js
index 033d76c..bf34328 100644
--- a/imports/ui/components/Navigation/Navigation.js
+++ b/imports/ui/components/Navigation/Navigation.js
@@ -13,38 +13,38 @@ import './Navigation.scss';
const Navigation = props => (
);
diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js
index b8683ab..bcd8916 100644
--- a/imports/ui/pages/FiresMap/FiresMap.js
+++ b/imports/ui/pages/FiresMap/FiresMap.js
@@ -31,13 +31,11 @@ import './FiresMap.scss';
const { BaseLayer } = LayersControl;
const MAXZOOM = 6;
+const MAXZOOMREACTIVE = 6;
const zoom = new ReactiveVar(8);
-const lat = new ReactiveVar();
-const lng = new ReactiveVar();
-const height = new ReactiveVar(400);
-const width = new ReactiveVar(400);
+const center = new ReactiveVar([null, null]);
+const mapSize = new ReactiveVar([400, 400]);
-// TODO share only the used part of fires data
// Remove map in subscription
class FiresMap extends React.Component {
constructor(props) {
@@ -62,11 +60,26 @@ class FiresMap extends React.Component {
Gkeys.load((err, key) => {
self.setState({ gkey: key });
});
- height.set(this.divElement.clientHeight);
- width.set(this.divElement.clientWidth);
+ mapSize.set([this.divElement.clientHeight, this.divElement.clientWidth]);
this.addScale();
}
+ /* componentWillReceiveProps(nextProps) {
+ * if (nextProps.loading) {
+ * // console.log('Loading new fires');
+ * }
+ * // this.setState({ loading: nextProps.loading });
+ * }
+ */
+
+ /* shouldComponentUpdate(nextProps, nextState) {
+ * if (nextProps.loading) {
+ * return true; // false;
+ * }
+ * return true;
+ * }
+ */
+
onViewportChanged(viewport) {
this.debounceView(viewport);
}
@@ -81,7 +94,6 @@ class FiresMap extends React.Component {
}
setShowSubsUnion(show) {
- this.setState({ showSubsUnion: show });
this.showSubsUnion(show);
}
@@ -115,35 +127,38 @@ class FiresMap extends React.Component {
handleViewportChange(viewport) {
console.log(`Viewport changed: ${JSON.stringify(viewport)}`);
+ if (viewport.center === this.state.viewport.center &&
+ viewport.zoom === this.state.viewport.zoom) {
+ // Do nothing, in same point
+ return;
+ }
zoom.set(viewport.zoom);
- lat.set(viewport.center[0]);
- lng.set(viewport.center[1]);
+ center.set(viewport.center);
this.setState({ viewport });
- /* this.state.viewport = viewport;
- * this.state.modified = true; */
if (this.props.subsready && this.fireMap) {
this.showSubsUnion(this.state.showSubsUnion);
}
}
centerOnUserLocation(viewport) {
- this.handleViewportChange(viewport);
+ this.setState({ viewport });
+ // this.handleViewportChange(viewport);
}
useMarkers(use) {
this.setState({ useMarkers: use });
- // this.state.useMarkers = use;
- // this.forceUpdate();
}
addScale() {
- // https://www.npmjs.com/package/leaflet-graphicscale
- const map = this.getMap();
- const options = {
- fill: 'fill',
- showSubunits: true
- };
- L.control.graphicScale([options]).addTo(map);
+ if (this.fireMap) {
+ // https://www.npmjs.com/package/leaflet-graphicscale
+ const map = this.getMap();
+ const options = {
+ fill: 'fill',
+ showSubunits: true
+ };
+ L.control.graphicScale([options]).addTo(map);
+ }
}
render() {
@@ -151,7 +166,7 @@ class FiresMap extends React.Component {
// Show union of users
this.showSubsUnion(this.state.showSubsUnion);
}
- console.log('Rendering map');
+ console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length} of ${this.props.activefirestotal} total. Subs users ready ${this.props.subsready}, reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
const { t } = this.props;
const osmlayer = (
@@ -175,10 +190,10 @@ class FiresMap extends React.Component {
- { this.props.activefires.length === 0 ?
- No hay fuegos activos en esta zona del mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo. :
- En rojo, {{ count: this.props.activefires.length }} fuegos activos en el mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo por la NASA.
- }
+ { this.props.activefires.length === 0 ?
+ No hay fuegos activos en esta zona del mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo. :
+ En rojo, {{ count: this.props.activefires.length }} fuegos activos en el mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo por la NASA.
+ }
En naranja, los fuegos notificados por nuestros usuarios/as recientemente.
@@ -188,17 +203,25 @@ class FiresMap extends React.Component {
{(this.state.viewport.zoom >= MAXZOOM) &&
this.useMarkers(e.target.checked)}>
- Resaltar los fuegos con un marcador
+ Resaltar los fuegos con un marcador}
this.centerOnUserLocation(viewport)} />
+
+ { this.state.viewport.zoom >= MAXZOOMREACTIVE ?
+ Los fuegos activos se actualizan en tiempo real. :
+ Haga zoom en una zona de su interés si quiere que los fuegos se actualicen en tiempo real.
+ }
+
+