@@ -69,7 +79,6 @@ FireIconMark.propTypes = {
lat: PropTypes.number.isRequired,
lon: PropTypes.number.isRequired,
scan: PropTypes.number,
- track: PropTypes.number,
nasa: PropTypes.bool,
falsePositives: PropTypes.bool.isRequired,
industries: PropTypes.bool.isRequired,
diff --git a/imports/ui/components/Maps/FireListUnion.js b/imports/ui/components/Maps/FireListUnion.js
deleted file mode 100644
index 3b094c0..0000000
--- a/imports/ui/components/Maps/FireListUnion.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* eslint-disable import/no-absolute-path */
-/* eslint-disable react/jsx-indent-props */
-/* eslint-disable react/jsx-indent */
-import React from 'react';
-import PropTypes from 'prop-types';
-import FirePolygonMark from '/imports/ui/components/Maps/FirePolygonMark';
-
-export default function FireListUnion(props) {
- const {
- firesUnion, nasa, t, history
- } = props;
- /* console.log(`Using marks: ${useMarks}, using pixels: ${usePixel}`); */
- const items = firesUnion.map(({ _id, ...otherProps }) => (
));
- return (
{items}
);
-}
-
-FireListUnion.propTypes = {
- firesUnion: PropTypes.array.isRequired,
- nasa: PropTypes.bool.isRequired,
- history: PropTypes.object.isRequired,
- t: PropTypes.func.isRequired
-};
diff --git a/imports/ui/components/Maps/FirePixel.js b/imports/ui/components/Maps/FirePixel.js
index 4efcabe..c81b547 100644
--- a/imports/ui/components/Maps/FirePixel.js
+++ b/imports/ui/components/Maps/FirePixel.js
@@ -3,32 +3,31 @@
import React from 'react';
import { CircleMarker } from 'react-leaflet';
import PropTypes from 'prop-types';
-import { translate } from 'react-i18next';
import FirePopup from './FirePopup';
+import { translate } from 'react-i18next';
/* Less acurate (1 pixel per fire) but faster */
const FirePixel = ({
- lat, lon, nasa, id, when, t, history, track
+ lat, lon, nasa, id, when, t, history
}) => (
);
+
FirePixel.propTypes = {
lat: PropTypes.number.isRequired,
lon: PropTypes.number.isRequired,
id: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
- scan: PropTypes.number,
- track: PropTypes.number,
when: PropTypes.instanceOf(Date),
nasa: PropTypes.bool.isRequired,
t: PropTypes.func.isRequired
diff --git a/imports/ui/components/Maps/FirePolygonMark.js b/imports/ui/components/Maps/FirePolygonMark.js
deleted file mode 100644
index 92e3640..0000000
--- a/imports/ui/components/Maps/FirePolygonMark.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import React, { Component } from 'react';
-import { GeoJSON } from 'react-leaflet';
-import PropTypes from 'prop-types';
-import { onMarkClick } from './MarkListeners';
-import FirePopup from './FirePopup';
-
-class FirePolygonMark extends Component {
- constructor(props) {
- super(props);
- this.t = props.t;
- this.onClick = this.onClick.bind(this);
- }
-
- onClick() {
- const { history, nasa, id } = this.props;
- onMarkClick(history, nasa, id);
- }
-
- render() {
- const {
- nasa,
- id,
- shape,
- centerid,
- history,
- when,
- t
- } = this.props;
- const lon = centerid.coordinates[0];
- const lat = centerid.coordinates[1];
- return (
-
- );
- /*
*/
- }
-}
-
-FirePolygonMark.propTypes = {
- id: PropTypes.object.isRequired,
- nasa: PropTypes.bool.isRequired,
- shape: PropTypes.object.isRequired,
- centerid: PropTypes.object.isRequired,
- history: PropTypes.object.isRequired,
- when: PropTypes.instanceOf(Date).isRequired,
- t: PropTypes.func.isRequired
-};
-
-export default FirePolygonMark;
diff --git a/imports/ui/components/Maps/SubsUnion/SubsUnion.js b/imports/ui/components/Maps/SubsUnion/SubsUnion.js
index 41a4d81..dab127a 100644
--- a/imports/ui/components/Maps/SubsUnion/SubsUnion.js
+++ b/imports/ui/components/Maps/SubsUnion/SubsUnion.js
@@ -33,7 +33,8 @@ const subsUnion = (union, options) => {
options.map.leafletElement.fitBounds(L.latLngBounds(bounds._northEast, bounds._southWest));
}
} else if (options.subs.length > 0) {
- const result = calcUnion(L, options.subs, sub => sub, true);
+ const unionGroup = new L.FeatureGroup();
+ const result = calcUnion(options.subs, unionGroup, sub => sub);
const unionJson = result[0];
const bounds = result[1];
diff --git a/imports/ui/components/Maps/SubsUnion/Unify.js b/imports/ui/components/Maps/SubsUnion/Unify.js
index 873dcbf..46586b7 100644
--- a/imports/ui/components/Maps/SubsUnion/Unify.js
+++ b/imports/ui/components/Maps/SubsUnion/Unify.js
@@ -1,9 +1,48 @@
-import { calcUnion as calcUnionWoBounds } from 'map-common-utils';
+import { check } from 'meteor/check';
+import LGeo from 'leaflet-geodesy';
+import tunion from '@turf/union';
+import ttrunc from '@turf/truncate';
-const calcUnion = (L, subs, decorated, typeCircle) => {
- const unionJson = calcUnionWoBounds(subs, decorated, typeCircle);
- // return [unionJson, L.geoJSON(unionJson).getBounds()];
- return [unionJson, unionJson === null ? null : L.geoJSON(unionJson).getBounds()];
+// https://stackoverflow.com/questions/35394577/leaflet-js-union-merge-circles
+const truncOptions = { precision: 6, coordinates: 2 };
+
+const unify = (polyList) => {
+ let unionTemp;
+ for (let i = 0; i < polyList.length; i += 1) {
+ const pol = polyList[i].toGeoJSON();
+ const cleanPol = ttrunc(pol, truncOptions);
+ if (i === 0) {
+ unionTemp = cleanPol;
+ } else {
+ unionTemp = ttrunc(tunion(unionTemp, cleanPol), truncOptions);
+ }
+ }
+ return unionTemp;
+};
+
+const calcUnion = (subs, group, decorated) => {
+ const unionGroup = group;
+ const copts = {
+ parts: 144
+ };
+ subs.forEach((osub) => {
+ try {
+ if (osub.location && osub.location.lat && osub.location.lon && osub.distance) {
+ check(osub.location.lon, Number);
+ check(osub.location.lat, Number);
+ check(osub.distance, Number);
+ const dsub = decorated(osub);
+ const circle = LGeo.circle([dsub.location.lat, dsub.location.lon], dsub.distance * 1000, copts);
+ circle.addTo(unionGroup);
+ } else {
+ console.info(`Wrong subscription ${JSON.stringify(osub)}`);
+ }
+ } catch (e) {
+ console.error(e, `Wrong subscription trying to make union ${JSON.stringify(osub)}`);
+ }
+ });
+ const unionJson = unify(unionGroup.getLayers());
+ return [unionJson, unionGroup.getBounds()];
};
export default calcUnion;
diff --git a/imports/ui/components/NotificationsObserver/NotificationsObserver.js b/imports/ui/components/NotificationsObserver/NotificationsObserver.js
index ac374b5..e68b1ef 100644
--- a/imports/ui/components/NotificationsObserver/NotificationsObserver.js
+++ b/imports/ui/components/NotificationsObserver/NotificationsObserver.js
@@ -12,7 +12,7 @@ import { trim } from './util.js';
function process(notif) {
// No already notified
if (Push.Permission.has()) {
- if (!notif.notified && notif.type === 'web') {
+ if (!notif.webNotified) {
Push.create(i18n.t('AppName'), {
body: `${trim(notif.content)} (${i18n.t('fireDetected', { when: dateFromNow(notif.when) })})`,
icon: '/n-fire-marker.png',
@@ -47,7 +47,7 @@ Meteor.startup(() => {
if (Meteor.userId()) {
Meteor.subscribe('mynotifications');
// Check for notifications not processed at startup
- Notifications.find({ notified: null, type: 'web' }).forEach((notif) => {
+ Notifications.find({ webNotified: null }).forEach((notif) => {
process(notif);
});
}
diff --git a/imports/ui/layouts/App/App.js b/imports/ui/layouts/App/App.js
index 4aeef3a..d991262 100644
--- a/imports/ui/layouts/App/App.js
+++ b/imports/ui/layouts/App/App.js
@@ -98,66 +98,66 @@ const App = props => (
/* https://react.i18next.com/components/i18nextprovider.html */
{props.i18nReady.get() &&
-
-
-
-
-
- { !props.loading &&
-
-
-
- {i18n.t('AppName')}
-
-
-
-
-
-
+
+
+
+
+
+ { !props.loading &&
+
+
+
+ {i18n.t('AppName')}
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
- {props.i18nReady.get() && }
- }
-
-
-
-
- }
+
+
+
+
+
+
+ {props.i18nReady.get() &&
}
+
}
+
+
+
+
+ }
);
@@ -186,9 +186,7 @@ export default withTracker(() => {
const loading = !Roles.subscription.ready() || !i18nReady.get();
const name = user && user.profile && user.profile.name && getUserName(user.profile.name);
const emailAddress = user && user.emails && user.emails[0].address;
- Meteor.autorun(() => {
- console.log(`i18n ready?: ${i18nReady.get()}`);
- });
+ // console.log(`i18n ready?: ${i18nReady.get()}`);
return {
loading,
loggingIn,
diff --git a/imports/ui/pages/Fires/Fires.js b/imports/ui/pages/Fires/Fires.js
index 2647992..0e4271a 100644
--- a/imports/ui/pages/Fires/Fires.js
+++ b/imports/ui/pages/Fires/Fires.js
@@ -10,8 +10,7 @@ import { Row, Col, Alert, FormGroup } from 'react-bootstrap';
import { Meteor } from 'meteor/meteor';
import { Bert } from 'meteor/themeteorchef:bert';
import { Helmet } from 'react-helmet';
-import { Map, GeoJSON } from 'react-leaflet';
-import { rectangleAround } from 'map-common-utils';
+import { Map, Circle } from 'react-leaflet';
import Blaze from 'meteor/gadicc:blaze-react-component';
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
import NotFound from '/imports/ui/pages/NotFound/NotFound';
@@ -116,9 +115,8 @@ class Fire extends React.Component {
t('Información adicional sobre fuego detectado en {{where}} el {{when}}', { where: fire.address, when: this.dateLongFormat }) :
t('Información adicional sobre fuego detectado el {{when}}', { when: this.dateLongFormat });
}
- const ready = fire && !loading;
- const rect = ready ? rectangleAround({ lat: fire.lat, lon: fire.lon }, fire.track, fire.track) : null;
- return (ready ? (
+
+ return (fire && !loading ? (
{t('AppName')}: {t('Información adicional sobre fuego')}
@@ -139,13 +137,14 @@ class Fire extends React.Component {
zoom={13}
>
- { this.circle = circle; this.handleLeafletCircleLoad(circle); }}
- data={rect}
+ { this.circle = circle; this.handleLeafletCircleLoad(circle); }}
/>
{ (this.props.activefires.length + this.props.firealerts.length) === 0 ?
No hay fuegos activos en esta zona del mapa. {{ countTotal: this.props.activefirestotal }} fuegos activos en el mundo. :
- En rojo, {{ count: this.props.activefiresunion.length + this.props.firealerts.length }} fuegos activos. {{ countTotal: this.props.activefirestotal }} fuegos activos en el mundo.
+ En rojo, {{ count: this.props.activefires.length + this.props.firealerts.length }} fuegos activos. {{ countTotal: this.props.activefirestotal }} fuegos activos en el mundo.
}
{isNotHomeAndMobile() && this.props.firealerts.length > 0 &&
@@ -297,14 +307,6 @@ class FiresMap extends React.Component {
neighbour={false}
industries={false}
/>
- { Meteor.isDevelopment &&
-
- }
{
// console.log(`With industries: ${withIndustries}`);
let subscription;
- let subscriptionUnion;
let alertSubscription;
const centerStored = store.get('firesmap_center');
@@ -423,14 +422,6 @@ export default translate([], { wait: true })(withTracker(() => {
mapSize.get()[1].lat,
marks.get() && zoom.get() >= MAXZOOM
);
- subscriptionUnion = Meteor.subscribe(
- 'activefiresunionmyloc',
- mapSize.get()[0].lng,
- mapSize.get()[0].lat,
- mapSize.get()[1].lng,
- mapSize.get()[1].lat,
- false
- );
alertSubscription = Meteor.subscribe(
'fireAlerts',
mapSize.get()[0].lng,
@@ -451,7 +442,6 @@ export default translate([], { wait: true })(withTracker(() => {
});
Meteor.subscribe('activefirestotal');
- Meteor.subscribe('activefiresuniontotal');
const settingsSubs = Meteor.subscribe('settings');
const lastCheck = SiteSettings.findOne({ name: 'last-fire-check' });
@@ -463,15 +453,13 @@ export default translate([], { wait: true })(withTracker(() => {
const lastFireDetected = ActiveFiresCollection.findOne({}, { sort: { when: -1 } });
return {
- loading: Meteor.status().status !== 'connected' || !subscription ? true : !(subscription.ready() && settingsSubs.ready() && alertSubscription.ready() && settingsSubs.ready() && subscriptionUnion.ready()),
+ loading: Meteor.status().status !== 'connected' || !subscription ? true : !(subscription.ready() && settingsSubs.ready() && alertSubscription.ready()),
userSubs: userSubs ? userSubs.value : null,
userSubsBounds: userSubs ? userSubsBounds.value : null,
subsready: settingsSubs.ready(),
// Not reactive query depending on zoom level
activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
- activefiresunion: ActiveFiresUnion.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
activefirestotal: Counter.get('countActiveFires') + fireAlerts.length,
- activefiresuniontotal: Counter.get('countActiveFiresUnion') + fireAlerts.length,
firealerts: fireAlerts,
falsePositives,
industries,
diff --git a/imports/ui/pages/Index/Index.js b/imports/ui/pages/Index/Index.js
index 9986fba..5d6b130 100644
--- a/imports/ui/pages/Index/Index.js
+++ b/imports/ui/pages/Index/Index.js
@@ -11,7 +11,6 @@ import PropTypes from 'prop-types';
// import { Link } from 'react-router-dom';
// https://www.npmjs.com/package/react-resize-detector
import ReactResizeDetector from 'react-resize-detector';
-import MobileStoreButton from 'react-mobile-store-button';
import _ from 'lodash';
import 'html5-device-mockups/dist/device-mockups.min.css';
import 'bootstrap-carousel-swipe/carousel-swipe';
@@ -21,6 +20,7 @@ import SubscriptionsMap from '/imports/ui/pages/Subscriptions/SubscriptionsMap';
import ShareIt from '/imports/ui/components/ShareIt/ShareIt';
import getFallbackLang from '/imports/modules/lang-fallback';
import FiresMap from '../FiresMap/FiresMap';
+
import './Index.scss';
import './Index-custom.scss';
@@ -102,7 +102,6 @@ class Index extends Component {
render() {
const { t } = this.props;
const title = `${t('AppName')}: ${t('Inicio')}`;
- const androidUrl = 'https://play.google.com/store/apps/details?id=org.comunes.fires';
return (
@@ -182,9 +181,6 @@ class Index extends Component {
Siempre alerta a los fuegos en nuestro vecindario
{/* {this.props.t('Participa')} */}
-
-
-
diff --git a/imports/ui/pages/Index/Index.scss b/imports/ui/pages/Index/Index.scss
index 527aa93..3fb18b4 100644
--- a/imports/ui/pages/Index/Index.scss
+++ b/imports/ui/pages/Index/Index.scss
@@ -77,7 +77,3 @@
}
}
}
-
-.android-btn > div {
- height: 50px !important;
-}
diff --git a/imports/ui/pages/Profile/Profile.js b/imports/ui/pages/Profile/Profile.js
index 6d9b24b..665e9d7 100644
--- a/imports/ui/pages/Profile/Profile.js
+++ b/imports/ui/pages/Profile/Profile.js
@@ -9,17 +9,15 @@ import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Bert } from 'meteor/themeteorchef:bert';
import { testId } from '/imports/ui/components/Utils/TestUtils';
-import { translate } from 'react-i18next';
-import { T9n } from 'meteor-accounts-t9n';
-import { withTracker } from 'meteor/react-meteor-data';
import Col from '../../components/Col/Col';
+import { withTracker } from 'meteor/react-meteor-data';
import InputHint from '../../components/InputHint/InputHint';
import validate from '../../../modules/validate';
+import { translate } from 'react-i18next';
+import { T9n } from 'meteor-accounts-t9n';
import './Profile.scss';
-// List of languages: https://github.com/i18next/i18next/issues/1068
-
class Profile extends React.Component {
constructor(props) {
super(props);
@@ -157,7 +155,6 @@ class Profile extends React.Component {
renderPasswordUser(loading, user) {
const { t, i18n } = this.props;
- const enabledLangs = ['en', 'es', 'gl'];
const langName = {
en: 'English', es: 'Español', gl: 'Galego', ast: 'Asturianu', ca: 'Català'
};
@@ -205,7 +202,7 @@ class Profile extends React.Component {
{langName[i18n.language]}
- {enabledLangs.map(lang => (
+ {i18n.languages.map(lang => (