Fire industries marks
This commit is contained in:
parent
eca58df6c2
commit
735dd55531
10 changed files with 126 additions and 19 deletions
59
imports/api/FalsePositives/server/publications.js
Normal file
59
imports/api/FalsePositives/server/publications.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* global Counter */
|
||||
/* eslint-disable import/no-absolute-path */
|
||||
/* eslint-disable prefer-arrow-callback */
|
||||
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { check } from 'meteor/check';
|
||||
import { NumberBetween } from '/imports/modules/server/other-checks';
|
||||
import FalsePositives from '../FalsePositives';
|
||||
|
||||
const counter = new Counter('countFalsePositives', FalsePositives.find({}));
|
||||
|
||||
Meteor.publish('falsePositivesTotal', function total() {
|
||||
return counter;
|
||||
});
|
||||
|
||||
const falsePositives = (northEastLng, northEastLat, southWestLng, southWestLat) => {
|
||||
const fires = FalsePositives.find({
|
||||
geo: {
|
||||
$geoWithin: {
|
||||
$box: [
|
||||
[southWestLng, southWestLat],
|
||||
[northEastLng, northEastLat]
|
||||
]
|
||||
}
|
||||
}
|
||||
}, {
|
||||
fields: {
|
||||
geo: 1,
|
||||
// type: 1,
|
||||
// when: 1,
|
||||
fireId: 1
|
||||
}
|
||||
}).serverTransform(function transformDoc(odoc) {
|
||||
const doc = odoc;
|
||||
// Destructuring gives me an error: "Cannot destructure property `geo` of 'undefined'"
|
||||
const geo = doc.geo;
|
||||
if (geo) {
|
||||
doc.lat = geo.coordinates[1];
|
||||
doc.lon = geo.coordinates[0];
|
||||
}
|
||||
doc._id = doc.fireId;
|
||||
doc.id = doc.fireId;
|
||||
delete doc.geo;
|
||||
// console.log(doc);
|
||||
return doc;
|
||||
});
|
||||
// console.log(`Fires total: ${fires.count()}`);
|
||||
return fires;
|
||||
};
|
||||
|
||||
Meteor.publishTransformed('falsePositivesMyloc', function falsePositivesInMyLoc(northEastLng, northEastLat, southWestLng, southWestLat) {
|
||||
// latitude -90 and 90 and the longitude between -180 and 180
|
||||
check(northEastLng, NumberBetween(-180, 180));
|
||||
check(southWestLat, NumberBetween(-90, 90));
|
||||
check(southWestLng, NumberBetween(-180, 180));
|
||||
check(northEastLat, NumberBetween(-90, 90));
|
||||
|
||||
return falsePositives(northEastLng, northEastLat, southWestLng, southWestLat);
|
||||
});
|
||||
|
|
@ -26,3 +26,4 @@ import '../../api/SiteSettings/methods';
|
|||
import '../../api/SiteSettings/server/publications';
|
||||
|
||||
import '../../api/FalsePositives/methods';
|
||||
import '../../api/FalsePositives/server/publications';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import React from 'react';
|
||||
import { CircleMarker, Marker } from 'react-leaflet';
|
||||
import PropTypes from 'prop-types';
|
||||
import { fireIcon, nFireIcon } from '/imports/ui/components/Maps/Icons';
|
||||
import { fireIcon, nFireIcon, industryIcon } from '/imports/ui/components/Maps/Icons';
|
||||
import { translate } from 'react-i18next';
|
||||
import FirePopup from './FirePopup';
|
||||
|
||||
|
|
@ -12,16 +12,24 @@ const FireIconMark = ({
|
|||
nasa,
|
||||
id,
|
||||
history,
|
||||
falsePositives,
|
||||
when,
|
||||
t
|
||||
}) => (
|
||||
<div>
|
||||
{ !falsePositives &&
|
||||
<Marker position={[lat, lon]} icon={nasa ? fireIcon : nFireIcon}>
|
||||
<FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} />
|
||||
</Marker> }
|
||||
{ falsePositives &&
|
||||
<Marker position={[lat, lon]} icon={industryIcon}>
|
||||
{ /* disabled because was a past fire (and can be marked multiple times) */ false && <FirePopup t={t} history={history} id={id} lat={lat} lon={lon} /> }
|
||||
</Marker>
|
||||
}
|
||||
{ !falsePositives &&
|
||||
<CircleMarker center={[lat, lon]} color={nasa ? 'red' : '#D35400'} stroke={false} fillOpacity="1" fill radius={1}>
|
||||
<FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} />
|
||||
</CircleMarker>
|
||||
</CircleMarker> }
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
@ -29,10 +37,11 @@ FireIconMark.propTypes = {
|
|||
// https://github.com/PaulLeCam/react-leaflet/tree/master/src/propTypes
|
||||
lat: PropTypes.number.isRequired,
|
||||
lon: PropTypes.number.isRequired,
|
||||
nasa: PropTypes.bool.isRequired,
|
||||
nasa: PropTypes.bool,
|
||||
falsePositives: PropTypes.bool.isRequired,
|
||||
id: PropTypes.object.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
when: PropTypes.instanceOf(Date).isRequired,
|
||||
when: PropTypes.instanceOf(Date),
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,17 +9,17 @@ import FirePixel from '/imports/ui/components/Maps/FirePixel';
|
|||
|
||||
export default function FireList(props) {
|
||||
const {
|
||||
fires, scale, useMarkers, nasa, t, history
|
||||
fires, scale, useMarkers, nasa, t, history, falsePositives
|
||||
} = props;
|
||||
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 }) => (<FireIconMark t={t} history={history} id={_id} key={_id} nasa={nasa} {...otherProps} />));
|
||||
} else if (usePixel) {
|
||||
items = fires.map(({ _id, ...otherProps }) => (<FireIconMark t={t} history={history} id={_id} key={_id} nasa={nasa} falsePositives={falsePositives} {...otherProps} />));
|
||||
} else if (usePixel && !falsePositives) {
|
||||
items = fires.map(({ _id, ...otherProps }) => (<FirePixel key={_id} nasa={nasa} {...otherProps} />));
|
||||
} else {
|
||||
} else if (!falsePositives) {
|
||||
items = fires.map(({ _id, ...otherProps }) => (<FireCircleMark t={t} history={history} id={_id} key={_id} nasa={nasa} {...otherProps} />));
|
||||
}
|
||||
return (<div style={{ display: 'none' }}>{items}</div>);
|
||||
|
|
@ -30,6 +30,7 @@ FireList.propTypes = {
|
|||
scale: PropTypes.bool.isRequired,
|
||||
useMarkers: PropTypes.bool.isRequired,
|
||||
nasa: PropTypes.bool.isRequired,
|
||||
falsePositives: PropTypes.bool.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ const FirePopup = ({
|
|||
<Popup className="fire-popup">
|
||||
<Fragment>
|
||||
<span>{t('Coordenadas:')} {lat}, {lon}</span><br />
|
||||
<span>{t('Fuente')}: {t(nasa ? 'NASA' : 'nuestros usuarios/as')}</span><br />
|
||||
<span>{t('Detectado')}: {moment(when).fromNow()}</span><br />
|
||||
{nasa && <Fragment><span>{t('Fuente')}: {t(nasa ? 'NASA' : 'nuestros usuarios/as')}</span><br /></Fragment> }
|
||||
{when && <Fragment><span>{t('Detectado')}: {moment(when).fromNow()}</span><br /></Fragment> }
|
||||
<span>
|
||||
<a href="#" onClick={() => history.push(`/fire/active/${id}`)}>{t('Más información sobre este fuego')}</a>
|
||||
{ /* if nasa === null means that the is a false positive fire */ }
|
||||
<a href="#" onClick={() => history.push(`/fire/${nasa ? 'active' : 'archive'}/${id}`)}>{t('Más información sobre este fuego')}</a>
|
||||
</span>
|
||||
</Fragment>
|
||||
</Popup>
|
||||
|
|
@ -33,10 +34,10 @@ FirePopup.propTypes = {
|
|||
// https://github.com/PaulLeCam/react-leaflet/tree/master/src/propTypes
|
||||
lat: PropTypes.number.isRequired,
|
||||
lon: PropTypes.number.isRequired,
|
||||
nasa: PropTypes.bool.isRequired,
|
||||
nasa: PropTypes.bool,
|
||||
id: PropTypes.object.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
when: PropTypes.instanceOf(Date).isRequired,
|
||||
when: PropTypes.instanceOf(Date),
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ export const fireIcon = new Leaflet.Icon({
|
|||
* popupAnchor: [-3, -76]// point from which the popup should open relative to the iconAnchor */
|
||||
});
|
||||
|
||||
export const industryIcon = new Leaflet.Icon({
|
||||
iconUrl: '/industry-marker.png',
|
||||
iconSize: [32, 37],
|
||||
iconAnchor: [16, 20]
|
||||
});
|
||||
|
||||
export const nFireIcon = new Leaflet.Icon({
|
||||
iconUrl: '/n-fire-marker.png',
|
||||
iconSize: [16, 24], // size of the icon
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import FromNow from '/imports/ui/components/FromNow/FromNow';
|
|||
import Loading from '/imports/ui/components/Loading/Loading';
|
||||
import ActiveFiresCollection from '/imports/api/ActiveFires/ActiveFires';
|
||||
import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts';
|
||||
import FalsePositivesCollection from '/imports/api/FalsePositives/FalsePositives';
|
||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
||||
import { isNotHomeAndMobile, isChrome } from '/imports/ui/components/Utils/isMobile';
|
||||
|
|
@ -134,7 +135,10 @@ class FiresMap extends React.Component {
|
|||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length + this.props.firealerts.length} of ${this.props.activefirestotal} total. Subs users ready ${this.props.subsready} (${this.props.userSubs.length}), reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
|
||||
console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length + this.props.firealerts.length} of ${this.props.activefirestotal} total. False positives: ${this.props.falsePositives.length}. Subs users ready ${this.props.subsready} (${this.props.userSubs.length}), reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
|
||||
if (Meteor.isDevelopment) {
|
||||
console.log(`False positives total: ${this.props.falsePositivesTotal}`);
|
||||
}
|
||||
return (
|
||||
/* Large number of markers:
|
||||
https://stackoverflow.com/questions/43015854/large-dataset-of-markers-or-dots-in-leaflet/43019740#43019740 */
|
||||
|
|
@ -210,6 +214,15 @@ class FiresMap extends React.Component {
|
|||
{/* http://wiki.openstreetmap.org/wiki/Tile_servers */}
|
||||
{!this.props.loading &&
|
||||
<Fragment>
|
||||
<FireList
|
||||
t={t}
|
||||
history={this.props.history}
|
||||
fires={this.props.falsePositives}
|
||||
scale={this.state.viewport.zoom >= MAXZOOM}
|
||||
useMarkers={this.state.useMarkers}
|
||||
nasa={false}
|
||||
falsePositives
|
||||
/>
|
||||
<FireList
|
||||
t={t}
|
||||
history={this.props.history}
|
||||
|
|
@ -217,6 +230,7 @@ class FiresMap extends React.Component {
|
|||
scale={this.state.viewport.zoom >= MAXZOOM}
|
||||
useMarkers={this.state.useMarkers}
|
||||
nasa
|
||||
falsePositives={false}
|
||||
/>
|
||||
<FireList
|
||||
t={t}
|
||||
|
|
@ -225,6 +239,7 @@ class FiresMap extends React.Component {
|
|||
scale={false}
|
||||
useMarkers={this.state.useMarkers}
|
||||
nasa={false}
|
||||
falsePositives={false}
|
||||
/>
|
||||
</Fragment> }
|
||||
<DefMapLayers />
|
||||
|
|
@ -250,6 +265,8 @@ FiresMap.propTypes = {
|
|||
userSubs: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
activefires: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
firealerts: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
falsePositives: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
falsePositivesTotal: PropTypes.number.isRequired,
|
||||
lastCheck: PropTypes.instanceOf(Date),
|
||||
activefirestotal: PropTypes.number.isRequired,
|
||||
center: PropTypes.arrayOf(PropTypes.number),
|
||||
|
|
@ -283,14 +300,23 @@ export default translate([], { wait: true })(withTracker(() => {
|
|||
mapSize.get()[1].lng,
|
||||
mapSize.get()[1].lat
|
||||
);
|
||||
Meteor.subscribe(
|
||||
'falsePositivesMyloc',
|
||||
mapSize.get()[0].lng,
|
||||
mapSize.get()[0].lat,
|
||||
mapSize.get()[1].lng,
|
||||
mapSize.get()[1].lat
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.subscribe('activefirestotal');
|
||||
Meteor.subscribe('falsePositivesTotal');
|
||||
Meteor.subscribe('settings');
|
||||
const userSubs = Meteor.subscribe('userSubsToFires');
|
||||
const lastCheck = SiteSettings.findOne({ name: 'last-fire-check' });
|
||||
const fireAlerts = FireAlertsCollection.find().fetch();
|
||||
const falsePositives = FalsePositivesCollection.find().fetch();
|
||||
return {
|
||||
loading: !subscription ? true : !subscription.ready(),
|
||||
userSubs: UserSubsToFiresCollection.find().fetch(),
|
||||
|
|
@ -298,7 +324,9 @@ export default translate([], { wait: true })(withTracker(() => {
|
|||
// Not reactive query depending on zoom level
|
||||
activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
|
||||
activefirestotal: Counter.get('countActiveFires') + fireAlerts.length,
|
||||
falsePositivesTotal: Counter.get('countFalsePositives') + fireAlerts.length,
|
||||
firealerts: fireAlerts,
|
||||
falsePositives,
|
||||
lastCheck: lastCheck ? lastCheck.value : null,
|
||||
center: geolocation.get(),
|
||||
zoom: zoom.get()
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ We acknowledge the use of data and imagery from LANCE FIRMS operated by the NASA
|
|||
* Home slide secondary 2: Smog over Almaty city, Kazakhstan, January 2014, photo by Igors Jefimovs, CC-BY 3.0, [source](https://commons.wikimedia.org/wiki/File:Smog_over_Almaty.jpg)
|
||||
* Wildfire home photo: [California Wildfires, October 23th 2007](https://commons.wikimedia.org/wiki/File:California_Wildfires_October_23_2007.jpg), [fuente](http://www.nasa.gov/vision/earth/lookingatearth/socal_wildfires_oct07.html).
|
||||
* Default avatar: A colored Emoji from Noto project, released under Apache license, [source](https://commons.wikimedia.org/wiki/File:Emoji_u1f469_1f3fd_200d_1f692.svg).
|
||||
* Industry fire marker by Nicolas Mollet, released under CC-BY-SA 3.0, [source](https://mapicons.mapsmarker.com/category/markers/industry/).
|
||||
|
||||
**Others**
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Reconocemos el uso de datos e imágenes de LANCE FIRMS operadas por NASA/GSFC/Ea
|
|||
* Diapositiva secundaria 2 del Inicio: Polución en la ciudad de Almaty, Kazakhstan, enero de 2014, foto de Igors Jefimovs, CC-BY 3.0, [source](https://commons.wikimedia.org/wiki/File:Smog_over_Almaty.jpg)
|
||||
* Foto de inicio de fuego forestal: [Incendios forestales de California, 23 de octubre de 2007](https://commons.wikimedia.org/wiki/File:California_Wildfires_October_23_2007.jpg), [fuente](http://www.nasa.gov/vision/earth/lookingatearth/socal_wildfires_oct07.html).
|
||||
* Avatar predeterminado: un Emoji coloreado del proyecto Noto, publicado bajo licencia Apache, [fuente](https://commons.wikimedia.org/wiki/File:Emoji_u1f469_1f3fd_200d_1f692.svg).
|
||||
* Marcador de industia por Nicolas Mollet, publicado bajo CC-BY-SA 3.0, [fuente](https://mapicons.mapsmarker.com/category/markers/industry/).
|
||||
|
||||
**Otros**
|
||||
|
||||
|
|
|
|||
BIN
public/industry-marker.png
Normal file
BIN
public/industry-marker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 339 B |
Loading…
Add table
Add a link
Reference in a new issue