Compare commits
No commits in common. "tcef-master" and "2.10.2" have entirely different histories.
tcef-maste
...
2.10.2
38 changed files with 824 additions and 999 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -12,8 +12,3 @@ public/locales/undefined/
|
||||||
.screenshots
|
.screenshots
|
||||||
.vscode
|
.vscode
|
||||||
output.json
|
output.json
|
||||||
|
|
||||||
# fase-0 higiene: variantes de settings con secretos (no versionar)
|
|
||||||
settings-production-*.json
|
|
||||||
settings-tests.json
|
|
||||||
*.json~
|
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,11 @@ TEST_PORT=3000 TEST_WATCH=1 TEST_CLIENT=0 MONGO_URL=mongodb://localhost:27017/fu
|
||||||
|
|
||||||
# and
|
# and
|
||||||
|
|
||||||
node_modules/.bin/chimp --watch --ddp=http://localhost:3000 --path=cucumber
|
chimp --watch --ddp=http://localhost:3000 --path=cucumber
|
||||||
|
|
||||||
# and
|
# and
|
||||||
|
|
||||||
node_modules/.bin/chimp --ddp=http://localhost:3000 --path=cucumber
|
chimp --ddp=http://localhost:3000 --path=cucumber
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
// - - - - CHIMP - - - -
|
|
||||||
/* watch: false,
|
|
||||||
* watchTags: '@watch',
|
|
||||||
* offline: false,
|
|
||||||
*/
|
|
||||||
// - - - - CUCUMBER - - - -
|
|
||||||
/* path: './features',
|
|
||||||
* jsonOutput: 'output.json', */
|
|
||||||
|
|
||||||
// '- - - - DEBUGGING - - - -
|
|
||||||
log: 'info',
|
|
||||||
debug: false,
|
|
||||||
seleniumDebug: false,
|
|
||||||
webdriverLogLevel: false,
|
|
||||||
// debugBrkCucumber: 5858,
|
|
||||||
// - - - - WEBDRIVER-IO - - - -
|
|
||||||
webdriverio: {
|
|
||||||
waitforTimeout: 10000,
|
|
||||||
waitforInterval: 250, // KEEP SMALL (!!!) this is the INTERVAL in which waitFor* is looped fo
|
|
||||||
desiredCapabilities: {
|
|
||||||
chromeOptions: {
|
|
||||||
// args: ["headless", "disable-gpu"]
|
|
||||||
args: ['--disable-gpu', '--no-sandbox', '--headless']
|
|
||||||
},
|
|
||||||
isHeadless: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -40,6 +40,7 @@ Feature: Test all secundary pages
|
||||||
| fire/Fe26.2**1a0361ed0384f741403682e26b4bbc3850bee24e775da13c9782b22365ea895f*r_3gmVad5vzkeyqPpo6UcA*1s5fFz3iDGKTYP2RCvXMshof00QCHf4ErDl9K2dxoX0u-J-t6scyOWG8pGp3ehg_FfEtyR_kYcEKU3rE0jaSlZbD09TIvhiIJeS3C6Uc8YD-rit0XBrgsVKfYSxKzTRoOYiYFJ8JYd298hMtfiASePjS05Z58hhicyCcJYYRlarqDScG3LiVY3lL5y2nfcdIMNuSjCiKOJWuMkxwd9nR1UHMudLl0hEoy56mPdnHpDYtP9IYUlIOk1LlWBxcmHKifbXeqHu94p8j13Kk20dh2R49Hw3KsSoE9UbWmGQA9wAZXT82301i3rGF5GPAKjlTlRYcWisQurnPwHSVmx3DhUdiYwKGxt4KeaM5QVI4BE9octvE41OOprB_-Il105diQEh2Y9vdvX51ZVWIRfCboICPM6rJb0Oin7U7F1iM-oD_5s3DGnelfM5LGBcKwiB5paMo5M5vdBMaO-zR216cW9yGVXw9IZqHx8xDQWnoHAZjt8NLHeiGF2QOmIGtEUH7qnwhGpkcvszajmAZzR8saZgoH1qfBfvpVA41YfV14gU**4d030f05e23ad75409cebc609107467fc60be5077d52cf041087cd024fc4dc45*GY97aGFc1MyAsoO3Qxqtgwk9j-MbAPdEGBmEHq6r8VU | Additional information | false |
|
| fire/Fe26.2**1a0361ed0384f741403682e26b4bbc3850bee24e775da13c9782b22365ea895f*r_3gmVad5vzkeyqPpo6UcA*1s5fFz3iDGKTYP2RCvXMshof00QCHf4ErDl9K2dxoX0u-J-t6scyOWG8pGp3ehg_FfEtyR_kYcEKU3rE0jaSlZbD09TIvhiIJeS3C6Uc8YD-rit0XBrgsVKfYSxKzTRoOYiYFJ8JYd298hMtfiASePjS05Z58hhicyCcJYYRlarqDScG3LiVY3lL5y2nfcdIMNuSjCiKOJWuMkxwd9nR1UHMudLl0hEoy56mPdnHpDYtP9IYUlIOk1LlWBxcmHKifbXeqHu94p8j13Kk20dh2R49Hw3KsSoE9UbWmGQA9wAZXT82301i3rGF5GPAKjlTlRYcWisQurnPwHSVmx3DhUdiYwKGxt4KeaM5QVI4BE9octvE41OOprB_-Il105diQEh2Y9vdvX51ZVWIRfCboICPM6rJb0Oin7U7F1iM-oD_5s3DGnelfM5LGBcKwiB5paMo5M5vdBMaO-zR216cW9yGVXw9IZqHx8xDQWnoHAZjt8NLHeiGF2QOmIGtEUH7qnwhGpkcvszajmAZzR8saZgoH1qfBfvpVA41YfV14gU**4d030f05e23ad75409cebc609107467fc60be5077d52cf041087cd024fc4dc45*GY97aGFc1MyAsoO3Qxqtgwk9j-MbAPdEGBmEHq6r8VU | Additional information | false |
|
||||||
Then I check that all page urls works properly
|
Then I check that all page urls works properly
|
||||||
|
|
||||||
|
@watch
|
||||||
Scenario: Check that other non visible pages work well
|
Scenario: Check that other non visible pages work well
|
||||||
Given I logout if logged
|
Given I logout if logged
|
||||||
And a list of non visible pages ids and contents
|
And a list of non visible pages ids and contents
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
/* eslint-disable consistent-return */
|
/* eslint-disable consistent-return */
|
||||||
|
|
||||||
import { Meteor } from 'meteor/meteor';
|
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import SimpleSchema from 'simpl-schema';
|
import SimpleSchema from 'simpl-schema';
|
||||||
import firesCommonSchema from '../Common/FiresSchema';
|
import firesCommonSchema from '../Common/FiresSchema';
|
||||||
|
|
@ -19,11 +18,8 @@ ActiveFires.deny({
|
||||||
remove: () => true
|
remove: () => true
|
||||||
});
|
});
|
||||||
|
|
||||||
const activeFiresSchema = firesCommonSchema;
|
|
||||||
|
|
||||||
activeFiresSchema.fireUnion = { type: Meteor.Collection.ObjectID, optional: true, blackbox: true };
|
ActiveFires.schema = new SimpleSchema(firesCommonSchema);
|
||||||
|
|
||||||
ActiveFires.schema = new SimpleSchema(activeFiresSchema);
|
|
||||||
|
|
||||||
ActiveFires.attachSchema(ActiveFires.schema);
|
ActiveFires.attachSchema(ActiveFires.schema);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,7 @@ const findFiresInRegion = (zone) => {
|
||||||
export const countRealFires = (firesCursor) => {
|
export const countRealFires = (firesCursor) => {
|
||||||
const realFires = [];
|
const realFires = [];
|
||||||
firesCursor.forEach((fire) => {
|
firesCursor.forEach((fire) => {
|
||||||
if (debug) console.log(`${JSON.stringify(fire)} -----`);
|
|
||||||
const union = firesUnion([fire]);
|
const union = firesUnion([fire]);
|
||||||
if (debug) console.log(`${JSON.stringify(union)} -----`);
|
|
||||||
const falsePos = whichAreFalsePositives(FalsePositives, union);
|
const falsePos = whichAreFalsePositives(FalsePositives, union);
|
||||||
const industries = whichAreFalsePositives(Industries, union);
|
const industries = whichAreFalsePositives(Industries, union);
|
||||||
if (falsePos.count() === 0 && industries.count() === 0) {
|
if (falsePos.count() === 0 && industries.count() === 0) {
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@ const activefires = (northEastLng, northEastLat, southWestLng, southWestLat, wit
|
||||||
lat: 1,
|
lat: 1,
|
||||||
lon: 1,
|
lon: 1,
|
||||||
when: 1,
|
when: 1,
|
||||||
scan: 1,
|
scan: 1
|
||||||
track: 1
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
/* eslint-disable consistent-return */
|
|
||||||
/* eslint-disable import/no-absolute-path */
|
|
||||||
|
|
||||||
import { Mongo } from 'meteor/mongo';
|
|
||||||
import SimpleSchema from 'simpl-schema';
|
|
||||||
import LocationSchema from '/imports/api/Utility/LocationSchema.js';
|
|
||||||
import { defaultCreatedAt, defaultUpdateAt } from '/imports/api/Utility/Utils.js';
|
|
||||||
|
|
||||||
const ActiveFiresUnion = new Mongo.Collection('activefiresunion', { idGeneration: 'MONGO' });
|
|
||||||
|
|
||||||
/* Sample:
|
|
||||||
*
|
|
||||||
* TODO
|
|
||||||
*
|
|
||||||
* */
|
|
||||||
|
|
||||||
// We have to store polygons and their centroids
|
|
||||||
// {"type":"Polygon","coordinates":[[[-5.8645,43.5524],[-5.8621,43.5524],[-5.8621,43.5546],[-5.8645,43.5546],[-5.8645,43.5524]]]}
|
|
||||||
|
|
||||||
ActiveFiresUnion.allow({
|
|
||||||
insert: () => false,
|
|
||||||
update: () => false,
|
|
||||||
remove: () => false
|
|
||||||
});
|
|
||||||
|
|
||||||
ActiveFiresUnion.deny({
|
|
||||||
insert: () => true,
|
|
||||||
update: () => true,
|
|
||||||
remove: () => true
|
|
||||||
});
|
|
||||||
|
|
||||||
// https://www.npmjs.com/package/simpl-schema
|
|
||||||
const GeoJsonSchema = new SimpleSchema({
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
allowedValues: ['Polygon']
|
|
||||||
},
|
|
||||||
coordinates: {
|
|
||||||
type: Array
|
|
||||||
},
|
|
||||||
'coordinates.$': {
|
|
||||||
type: Array
|
|
||||||
},
|
|
||||||
'coordinates.$.$': {
|
|
||||||
type: Array
|
|
||||||
},
|
|
||||||
'coordinates.$.$.$': {
|
|
||||||
type: Number
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const firesUnionSchema = {
|
|
||||||
centerid: LocationSchema,
|
|
||||||
|
|
||||||
// https://docs.mongodb.com/manual/reference/geojson/
|
|
||||||
// <field>: { type: <GeoJSON type> , coordinates: <coordinates> }
|
|
||||||
shape: GeoJsonSchema,
|
|
||||||
history: { type: Array, optional: true },
|
|
||||||
'history.$': GeoJsonSchema,
|
|
||||||
|
|
||||||
when: Date, // First date
|
|
||||||
|
|
||||||
createdAt: defaultCreatedAt,
|
|
||||||
updatedAt: defaultUpdateAt
|
|
||||||
};
|
|
||||||
|
|
||||||
ActiveFiresUnion.schema = new SimpleSchema(firesUnionSchema);
|
|
||||||
|
|
||||||
ActiveFiresUnion.attachSchema(ActiveFiresUnion.schema);
|
|
||||||
|
|
||||||
export default ActiveFiresUnion;
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
/* 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 { whichAreFalsePositives, firesUnion } from '/imports/api/FalsePositives/server/publications';
|
|
||||||
// import FalsePositives from '/imports/api/FalsePositives/FalsePositives';
|
|
||||||
// import Industries from '/imports/api/Industries/Industries';
|
|
||||||
import ActiveFiresUnion from '../ActiveFiresUnion';
|
|
||||||
|
|
||||||
const counter = new Counter('countActiveFiresUnion', ActiveFiresUnion.find({}));
|
|
||||||
|
|
||||||
Meteor.publish('activefiresuniontotal', function total() {
|
|
||||||
return counter;
|
|
||||||
});
|
|
||||||
|
|
||||||
const activeFiresUnion = (b1, b2, c1, c2, withMarks) => {
|
|
||||||
// a --- b
|
|
||||||
// c --- d
|
|
||||||
const geometry = {
|
|
||||||
$geometry: {
|
|
||||||
type: 'Polygon',
|
|
||||||
coordinates: [[
|
|
||||||
[c1, c2],
|
|
||||||
[c1, b2],
|
|
||||||
[b1, b2],
|
|
||||||
[b1, c2],
|
|
||||||
[c1, c2]
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// console.log(JSON.stringify(geometry));
|
|
||||||
const fires = ActiveFiresUnion.find({
|
|
||||||
shape: {
|
|
||||||
$geoIntersects: geometry
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
fields: {
|
|
||||||
shape: 1,
|
|
||||||
centerid: 1,
|
|
||||||
when: 1,
|
|
||||||
createdAt: 1,
|
|
||||||
updatedAt: 1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Meteor.isDevelopment) console.log(`Active fires union total: ${fires.count()}`);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (withMarks && fires.fetch().length > 0) {
|
|
||||||
const union = firesUnion(fires);
|
|
||||||
const falsePos = whichAreFalsePositives(FalsePositives, union);
|
|
||||||
const industries = whichAreFalsePositives(Industries, union);
|
|
||||||
return [fires, falsePos, industries];
|
|
||||||
} */
|
|
||||||
|
|
||||||
return fires;
|
|
||||||
};
|
|
||||||
|
|
||||||
Meteor.publish('activefiresunionmyloc', function activeInMyLoc(northEastLng, northEastLat, southWestLng, southWestLat, withMarks) {
|
|
||||||
// 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));
|
|
||||||
check(withMarks, Boolean);
|
|
||||||
|
|
||||||
// I use this for fire stats
|
|
||||||
// if (!Meteor.isDevelopment) return this.ready(); // empty
|
|
||||||
return activeFiresUnion(northEastLng, northEastLat, southWestLng, southWestLat, withMarks);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Warning: this increase always by one the fire stats
|
|
||||||
Meteor.publish('lastFireUnionDetected', function lastFireDetected() {
|
|
||||||
// I use this for fire stats
|
|
||||||
// if (!Meteor.isDevelopment) return this.ready(); // empty
|
|
||||||
return ActiveFiresUnion.find({}, { limit: 1, sort: { when: -1 } });
|
|
||||||
});
|
|
||||||
|
|
@ -5,8 +5,7 @@
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import { NumberBetween } from '/imports/modules/server/other-checks';
|
import { NumberBetween } from '/imports/modules/server/other-checks';
|
||||||
import '/imports/startup/server/leaflet-workaround.js';
|
import L from 'leaflet-headless';
|
||||||
import L from 'leaflet';
|
|
||||||
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
||||||
import Industries from '/imports/api/Industries/Industries';
|
import Industries from '/imports/api/Industries/Industries';
|
||||||
import FalsePositives from '../FalsePositives';
|
import FalsePositives from '../FalsePositives';
|
||||||
|
|
@ -23,13 +22,11 @@ export const firesUnion = (fires) => {
|
||||||
const isNASA = doc.type === 'modis' || doc.type === 'viirs';
|
const isNASA = doc.type === 'modis' || doc.type === 'viirs';
|
||||||
const pixelSize = doc.type === 'viirs' ? 0.375 : 1; // viirs has 375m pixel size, modis 1000m
|
const pixelSize = doc.type === 'viirs' ? 0.375 : 1; // viirs has 375m pixel size, modis 1000m
|
||||||
// default 1 km for neightbor alerts
|
// default 1 km for neightbor alerts
|
||||||
const map = {
|
return {
|
||||||
location: { lat: doc.lat, lon: doc.lon },
|
location: { lat: doc.lat, lon: doc.lon },
|
||||||
distance: isNASA ? doc.scan * pixelSize : 1,
|
distance: isNASA ? doc.scan * pixelSize : 1,
|
||||||
distanceY: isNASA ? doc.track * pixelSize : 1
|
distanceY: isNASA ? doc.track * pixelSize : 1
|
||||||
};
|
};
|
||||||
// console.log(map);
|
|
||||||
return map;
|
|
||||||
});
|
});
|
||||||
const union = calcUnion(L, remap, sub => sub, false);
|
const union = calcUnion(L, remap, sub => sub, false);
|
||||||
return union;
|
return union;
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,7 @@ Meteor.publish('fireAlerts', function fireAlerts(northEastLng, northEastLat, sou
|
||||||
fields: {
|
fields: {
|
||||||
lat: 1,
|
lat: 1,
|
||||||
lon: 1,
|
lon: 1,
|
||||||
scan: 1,
|
scan: 1
|
||||||
track: 1
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (Meteor.isDevelopment) console.log(`Neighbour alerts total: ${fires.count()}`);
|
if (Meteor.isDevelopment) console.log(`Neighbour alerts total: ${fires.count()}`);
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ export function fireFromHash(fireEnc, params) {
|
||||||
// const unsealed = Promise.await(urlEnc.decrypt(fireEnc));
|
// const unsealed = Promise.await(urlEnc.decrypt(fireEnc));
|
||||||
const unsealed = Promise.await(unsealW(fireEnc));
|
const unsealed = Promise.await(unsealW(fireEnc));
|
||||||
if (unsealed === undefined) {
|
if (unsealed === undefined) {
|
||||||
throw Error(`Fail to unseal '${fireEnc}'`);
|
throw Error('Undefined unsealed');
|
||||||
}
|
}
|
||||||
const w = unsealed.when;
|
const w = unsealed.when;
|
||||||
unsealed.when = new Date(w);
|
unsealed.when = new Date(w);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import { Random } from 'meteor/random';
|
||||||
import { subscriptionsInsert } from '/imports/api/Subscriptions/methods.js';
|
import { subscriptionsInsert } from '/imports/api/Subscriptions/methods.js';
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { upsertFalsePositive } from '/imports/api/FalsePositives/methods.js';
|
import { upsertFalsePositive } from '/imports/api/FalsePositives/methods.js';
|
||||||
|
|
||||||
const debug = false;
|
const debug = false;
|
||||||
|
|
||||||
const uptime = new Date();
|
const uptime = new Date();
|
||||||
|
|
@ -158,13 +157,11 @@ if (!Meteor.settings.private.internalApiToken) {
|
||||||
lon: 1,
|
lon: 1,
|
||||||
when: 1,
|
when: 1,
|
||||||
type: 1, // modis, viirs, vecinal
|
type: 1, // modis, viirs, vecinal
|
||||||
scan: 1,
|
scan: 1
|
||||||
track: 1
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = { total: fires.count(), real: countRealFires(fires) };
|
const result = { total: fires.count(), real: countRealFires(fires) };
|
||||||
if (debug) console.log(`Query for fires in ${lat}, ${lng} in ${km} km radius ${result}`);
|
|
||||||
|
|
||||||
if (!full) {
|
if (!full) {
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ if (!(Meteor.settings.private.fcmApiToken && Meteor.settings.private.fcmApiToken
|
||||||
validFcmSender = false;
|
validFcmSender = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fcmSender = new gcm.Sender(Meteor.settings.private.fcmApiToken);
|
||||||
|
|
||||||
// https://www.npmjs.com/package/google-maps-image-api-url
|
// https://www.npmjs.com/package/google-maps-image-api-url
|
||||||
// https://stackoverflow.com/questions/24355007/is-there-no-way-to-embed-a-google-map-into-an-html-email
|
// https://stackoverflow.com/questions/24355007/is-there-no-way-to-embed-a-google-map-into-an-html-email
|
||||||
// https://developers.google.com/maps/documentation/static-maps/intro
|
// https://developers.google.com/maps/documentation/static-maps/intro
|
||||||
|
|
@ -43,20 +45,8 @@ function imgUrl(lat, lng) {
|
||||||
return `<img src="${imgUrl(lat, lng)}" width="640" height="480"/>`;
|
return `<img src="${imgUrl(lat, lng)}" width="640" height="480"/>`;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
// Cutover flag (fase 1a): channels listed in
|
|
||||||
// Meteor.settings.private.notifDisabledChannels (e.g. ['mobile','web']) are
|
|
||||||
// handled by the tcef-notifications microservice, so the old observer/cron must
|
|
||||||
// NOT send them. Mutual exclusion per channel — reversible by editing settings,
|
|
||||||
// no code deploy needed. ES5-compatible on purpose (Meteor 1.6 / Node 8).
|
|
||||||
const notifDisabledChannels = (Meteor.settings.private && Meteor.settings.private.notifDisabledChannels) || [];
|
|
||||||
|
|
||||||
const processNotif = (notif) => {
|
const processNotif = (notif) => {
|
||||||
if (notifDisabledChannels.indexOf(notif.type) !== -1) {
|
if (isMailServerMaster && notif.type === 'mobile' && notif.notified !== true) {
|
||||||
// This channel was migrated to tcef-notifications; do nothing here.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isMailServerMaster && validFcmSender && notif.type === 'mobile' && notif.notified !== true) {
|
|
||||||
const fcmSender = new gcm.Sender(Meteor.settings.private.fcmApiToken);
|
|
||||||
const user = Meteor.users.findOne({ _id: notif.userId });
|
const user = Meteor.users.findOne({ _id: notif.userId });
|
||||||
moment.locale(user.lang);
|
moment.locale(user.lang);
|
||||||
// duplicate code below
|
// duplicate code below
|
||||||
|
|
@ -146,7 +136,8 @@ const processNotif = (notif) => {
|
||||||
} else {
|
} else {
|
||||||
// Not email or not verified -> remove notif so we don't retry to send it
|
// Not email or not verified -> remove notif so we don't retry to send it
|
||||||
Notifications.remove({ _id: notif._id });
|
Notifications.remove({ _id: notif._id });
|
||||||
}
|
}gn
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import '../../api/Users/server/publications';
|
||||||
import '../../api/Utility/server/methods';
|
import '../../api/Utility/server/methods';
|
||||||
|
|
||||||
import '../../api/ActiveFires/server/publications';
|
import '../../api/ActiveFires/server/publications';
|
||||||
import '../../api/ActiveFiresUnion/server/publications';
|
|
||||||
import '../../api/FireAlerts/server/publications';
|
import '../../api/FireAlerts/server/publications';
|
||||||
|
|
||||||
import '../../api/Subscriptions/methods';
|
import '../../api/Subscriptions/methods';
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,5 @@ import './prerender';
|
||||||
import './feedback';
|
import './feedback';
|
||||||
import './cron';
|
import './cron';
|
||||||
import './isMaster';
|
import './isMaster';
|
||||||
|
import './segfaults';
|
||||||
import './rest';
|
import './rest';
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
// imports/startup/server/leaflet-workaround.js
|
|
||||||
global.window = {
|
|
||||||
screen: {
|
|
||||||
deviceXDPI: 1,
|
|
||||||
logicalXDPI: 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
global.document = {
|
|
||||||
documentElement: {
|
|
||||||
style: {}
|
|
||||||
},
|
|
||||||
createElement: () => {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
global.navigator = {
|
|
||||||
userAgent: 'foo',
|
|
||||||
platform: 'bar'
|
|
||||||
};
|
|
||||||
|
|
@ -10,7 +10,6 @@ import FalsePositives from '/imports/api/FalsePositives/FalsePositives';
|
||||||
import Industries from '/imports/api/Industries/Industries';
|
import Industries from '/imports/api/Industries/Industries';
|
||||||
import IndustryRegistries from '/imports/api/Industries/IndustryRegistries';
|
import IndustryRegistries from '/imports/api/Industries/IndustryRegistries';
|
||||||
import Notifications from '/imports/api/Notifications/Notifications';
|
import Notifications from '/imports/api/Notifications/Notifications';
|
||||||
import ActiveFiresUnion from '/imports/api/ActiveFiresUnion/ActiveFiresUnion';
|
|
||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
|
|
||||||
Meteor.startup(() => {
|
Meteor.startup(() => {
|
||||||
|
|
@ -241,18 +240,6 @@ Meteor.startup(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Migrations.add({
|
|
||||||
version: 18,
|
|
||||||
up: () => {
|
|
||||||
const raw = ActiveFiresUnion.rawCollection();
|
|
||||||
raw.createIndex({ centerid: '2dsphere' });
|
|
||||||
raw.createIndex({ shape: '2dsphere' });
|
|
||||||
raw.createIndex({ when: 1 });
|
|
||||||
raw.createIndex({ createdAt: 1 });
|
|
||||||
raw.createIndex({ updatedAt: 1 });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set createdAt in users & subs
|
// Set createdAt in users & subs
|
||||||
Migrations.migrateTo('latest');
|
Migrations.migrateTo('latest');
|
||||||
|
|
||||||
|
|
|
||||||
25
imports/startup/server/segfaults.js
Normal file
25
imports/startup/server/segfaults.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import SegfaultHandler from 'segfault-handler';
|
||||||
|
import moment from 'moment';
|
||||||
|
// import ravenLogger from './ravenLogger';
|
||||||
|
|
||||||
|
// https://github.com/ddopson/node-segfault-handler
|
||||||
|
|
||||||
|
const dateFileFormat = moment().format('YYYYMMDD_HH:mm:ss');
|
||||||
|
|
||||||
|
SegfaultHandler.registerHandler(`/var/tmp/tcef-stacktrace-${dateFileFormat}.log`);
|
||||||
|
|
||||||
|
|
||||||
|
// This callaback does not work:
|
||||||
|
// https://github.com/ddopson/node-segfault-handler/issues/49
|
||||||
|
|
||||||
|
/* SegfaultHandler.registerHandler('/var/tmp/tcef-crash.log', (signal, address, stack) => {
|
||||||
|
* // Do what you want with the signal, address, or stack (array)
|
||||||
|
* // This callback will execute before the signal is forwarded on.
|
||||||
|
* ravenLogger.log(stack, signal);
|
||||||
|
* }); */
|
||||||
|
|
||||||
|
// Only uncomment for segv tests
|
||||||
|
// SegfaultHandler.causeSegfault();
|
||||||
|
|
||||||
|
// Or this for normal error (should go to raven in configured)
|
||||||
|
// throw new Error('This is just a test of error in server');
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
import Fires from '/imports/api/Fires/Fires';
|
import Fires from '/imports/api/Fires/Fires';
|
||||||
// import Comments from '/imports/api/Comments/Comments';
|
// import Comments from '/imports/api/Comments/Comments';
|
||||||
|
|
||||||
const firesMapEnabled = false;
|
|
||||||
|
|
||||||
sitemaps.add('/sitemap.xml', () => {
|
sitemaps.add('/sitemap.xml', () => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
|
|
||||||
|
|
@ -22,23 +20,21 @@ sitemaps.add('/sitemap.xml', () => {
|
||||||
|
|
||||||
// When user has public page
|
// When user has public page
|
||||||
/* const users = Meteor.users.find().fetch();
|
/* const users = Meteor.users.find().fetch();
|
||||||
_.each(users, function(user) {
|
_.each(users, function(user) {
|
||||||
out.push({
|
out.push({
|
||||||
page: '/persona/' + user.username,
|
page: '/persona/' + user.username,
|
||||||
lastmod: user.updatedAt
|
lastmod: user.updatedAt
|
||||||
});
|
});
|
||||||
}); */
|
}); */
|
||||||
|
|
||||||
if (firesMapEnabled) {
|
Fires.find({}, { limit: 100, sort: { createdAt: -1 } }).fetch().forEach((fire) => {
|
||||||
Fires.find({}, { limit: 100, sort: { createdAt: -1 } }).fetch().forEach((fire) => {
|
// Search the last comment of tha fire
|
||||||
// Search the last comment of tha fire
|
const lastComment = Comments.getCollection().findOne({ referenceId: `fire-${fire._id}` }, { sort: { createdAt: -1 } });
|
||||||
const lastComment = Comments.getCollection().findOne({ referenceId: `fire-${fire._id}` }, { sort: { createdAt: -1 } });
|
out.push({
|
||||||
out.push({
|
page: `/fire/archive/${fire._id._str}`,
|
||||||
page: `/fire/archive/${fire._id._str}`,
|
lastmod: lastComment ? lastComment.createdAt : fire.updatedAt
|
||||||
lastmod: lastComment ? lastComment.createdAt : fire.updatedAt
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ import { Meteor } from 'meteor/meteor';
|
||||||
import Subscriptions from '/imports/api/Subscriptions/Subscriptions';
|
import Subscriptions from '/imports/api/Subscriptions/Subscriptions';
|
||||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||||
import Perlin from 'loms.perlin';
|
import Perlin from 'loms.perlin';
|
||||||
import './leaflet-workaround';
|
import L from 'leaflet-headless';
|
||||||
import L from 'leaflet';
|
|
||||||
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
||||||
import { isMailServerMaster } from '/imports/startup/server/email';
|
import { isMailServerMaster } from '/imports/startup/server/email';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,7 @@ class DefMapLayers extends Component {
|
||||||
<TileLayer
|
<TileLayer
|
||||||
opacity={defOpacity}
|
opacity={defOpacity}
|
||||||
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
|
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
|
||||||
// url="https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png"
|
url="https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png"
|
||||||
url="https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png"
|
|
||||||
/>
|
/>
|
||||||
</BaseLayer>);
|
</BaseLayer>);
|
||||||
const osmlayer = (
|
const osmlayer = (
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { GeoJSON } from 'react-leaflet';
|
import { Circle } from 'react-leaflet';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { rectangleAround } from 'map-common-utils';
|
|
||||||
import { onMarkClick } from './MarkListeners';
|
import { onMarkClick } from './MarkListeners';
|
||||||
import FirePopup from './FirePopup';
|
import FirePopup from './FirePopup';
|
||||||
|
|
||||||
|
|
||||||
class FireCircleMark extends Component {
|
class FireCircleMark extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
@ -22,26 +22,22 @@ class FireCircleMark extends Component {
|
||||||
lat,
|
lat,
|
||||||
lon,
|
lon,
|
||||||
scan,
|
scan,
|
||||||
track,
|
|
||||||
nasa,
|
nasa,
|
||||||
id,
|
id,
|
||||||
history,
|
history,
|
||||||
when,
|
when,
|
||||||
t
|
t
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const rect = rectangleAround({ lat, lon }, track, track);
|
|
||||||
return (
|
return (
|
||||||
<GeoJSON data={rect} color="red" stroke width="1" opacity=".4" fillOpacity="1">
|
<Circle center={[lat, lon]} color="red" stroke={false} fillOpacity="1" fill radius={scan * 500} onClick={this.onClick}>
|
||||||
<FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} />
|
<FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} />
|
||||||
</GeoJSON>
|
</Circle>
|
||||||
);
|
);
|
||||||
/* <Circle center={[lat, lon]} color="red" stroke={false} fillOpacity="1" fill radius={scan * 500} onClick={this.onClick}> */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FireCircleMark.propTypes = {
|
FireCircleMark.propTypes = {
|
||||||
scan: PropTypes.number.isRequired,
|
scan: PropTypes.number.isRequired,
|
||||||
track: PropTypes.number.isRequired,
|
|
||||||
lat: PropTypes.number.isRequired,
|
lat: PropTypes.number.isRequired,
|
||||||
lon: PropTypes.number.isRequired,
|
lon: PropTypes.number.isRequired,
|
||||||
nasa: PropTypes.bool.isRequired,
|
nasa: PropTypes.bool.isRequired,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import React, { Component, Fragment } from 'react';
|
||||||
import { CircleMarker, Marker, Tooltip } from 'react-leaflet';
|
import { CircleMarker, Marker, Tooltip } from 'react-leaflet';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { fireIconS, fireIconM, fireIconL, nFireIcon, industryIcon, regIndustryIcon } from '/imports/ui/components/Maps/Icons';
|
import { fireIconS, fireIconM, fireIconL, nFireIcon, industryIcon, regIndustryIcon } from '/imports/ui/components/Maps/Icons';
|
||||||
import { translate } from 'react-i18next';
|
|
||||||
import { onMarkClick } from './MarkListeners';
|
import { onMarkClick } from './MarkListeners';
|
||||||
|
import { translate } from 'react-i18next';
|
||||||
import FirePopup from './FirePopup';
|
import FirePopup from './FirePopup';
|
||||||
|
|
||||||
class FireIconMark extends Component {
|
class FireIconMark extends Component {
|
||||||
|
|
@ -30,7 +30,17 @@ class FireIconMark extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
lat, lon, scan, track, nasa, id, history, falsePositives, industries, neighbour, when, t
|
lat,
|
||||||
|
lon,
|
||||||
|
scan,
|
||||||
|
nasa,
|
||||||
|
id,
|
||||||
|
history,
|
||||||
|
falsePositives,
|
||||||
|
industries,
|
||||||
|
neighbour,
|
||||||
|
when,
|
||||||
|
t
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -69,7 +79,6 @@ FireIconMark.propTypes = {
|
||||||
lat: PropTypes.number.isRequired,
|
lat: PropTypes.number.isRequired,
|
||||||
lon: PropTypes.number.isRequired,
|
lon: PropTypes.number.isRequired,
|
||||||
scan: PropTypes.number,
|
scan: PropTypes.number,
|
||||||
track: PropTypes.number,
|
|
||||||
nasa: PropTypes.bool,
|
nasa: PropTypes.bool,
|
||||||
falsePositives: PropTypes.bool.isRequired,
|
falsePositives: PropTypes.bool.isRequired,
|
||||||
industries: PropTypes.bool.isRequired,
|
industries: PropTypes.bool.isRequired,
|
||||||
|
|
|
||||||
|
|
@ -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 }) => (<FirePolygonMark t={t} history={history} id={_id} key={_id} nasa={nasa} {...otherProps} />));
|
|
||||||
return (<div style={{ display: 'none' }}>{items}</div>);
|
|
||||||
}
|
|
||||||
|
|
||||||
FireListUnion.propTypes = {
|
|
||||||
firesUnion: PropTypes.array.isRequired,
|
|
||||||
nasa: PropTypes.bool.isRequired,
|
|
||||||
history: PropTypes.object.isRequired,
|
|
||||||
t: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
@ -3,32 +3,31 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { CircleMarker } from 'react-leaflet';
|
import { CircleMarker } from 'react-leaflet';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { translate } from 'react-i18next';
|
|
||||||
import FirePopup from './FirePopup';
|
import FirePopup from './FirePopup';
|
||||||
|
import { translate } from 'react-i18next';
|
||||||
|
|
||||||
/* Less acurate (1 pixel per fire) but faster */
|
/* Less acurate (1 pixel per fire) but faster */
|
||||||
const FirePixel = ({
|
const FirePixel = ({
|
||||||
lat, lon, nasa, id, when, t, history, track
|
lat, lon, nasa, id, when, t, history
|
||||||
}) => (
|
}) => (
|
||||||
<CircleMarker
|
<CircleMarker
|
||||||
center={[lat, lon]}
|
center={[lat, lon]}
|
||||||
color={nasa ? 'red' : '#D35400'}
|
color={nasa ? 'red' : '#D35400'}
|
||||||
stroke={false}
|
stroke={false}
|
||||||
fillOpacity="1"
|
fillOpacity="1"
|
||||||
fill
|
fill
|
||||||
radius={nasa ? 1 : 2}
|
radius={nasa ? 1 : 2}
|
||||||
>
|
>
|
||||||
<FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} />
|
<FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} />
|
||||||
</CircleMarker>
|
</CircleMarker>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
FirePixel.propTypes = {
|
FirePixel.propTypes = {
|
||||||
lat: PropTypes.number.isRequired,
|
lat: PropTypes.number.isRequired,
|
||||||
lon: PropTypes.number.isRequired,
|
lon: PropTypes.number.isRequired,
|
||||||
id: PropTypes.object.isRequired,
|
id: PropTypes.object.isRequired,
|
||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired,
|
||||||
scan: PropTypes.number,
|
|
||||||
track: PropTypes.number,
|
|
||||||
when: PropTypes.instanceOf(Date),
|
when: PropTypes.instanceOf(Date),
|
||||||
nasa: PropTypes.bool.isRequired,
|
nasa: PropTypes.bool.isRequired,
|
||||||
t: PropTypes.func.isRequired
|
t: PropTypes.func.isRequired
|
||||||
|
|
|
||||||
|
|
@ -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 (
|
|
||||||
<GeoJSON data={shape} color="orange" stroke width="1" opacity=".2" fillOpacity=".0" />
|
|
||||||
);
|
|
||||||
/* <FirePopup t={t} history={history} id={id} nasa={nasa} lat={lat} lon={lon} when={when} /> */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
@ -1,9 +1,56 @@
|
||||||
import { calcUnion as calcUnionWoBounds } from 'map-common-utils';
|
import { check } from 'meteor/check';
|
||||||
|
import tunion from '@turf/union';
|
||||||
|
import ttrunc from '@turf/truncate';
|
||||||
|
import { rectangleAround } from 'map-common-utils';
|
||||||
|
import tcircle from '@turf/circle';
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
const cleanPol = ttrunc(pol, truncOptions);
|
||||||
|
if (i === 0) {
|
||||||
|
unionTemp = cleanPol;
|
||||||
|
} else {
|
||||||
|
unionTemp = ttrunc(tunion(unionTemp, cleanPol), truncOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unionTemp;
|
||||||
|
};
|
||||||
|
|
||||||
const calcUnion = (L, subs, decorated, typeCircle) => {
|
const calcUnion = (L, subs, decorated, typeCircle) => {
|
||||||
const unionJson = calcUnionWoBounds(subs, decorated, typeCircle);
|
const unionGroup = [];
|
||||||
// return [unionJson, L.geoJSON(unionJson).getBounds()];
|
const doCircle = (typeof typeCircle !== 'undefined') ? typeCircle : true;
|
||||||
return [unionJson, unionJson === null ? null : L.geoJSON(unionJson).getBounds()];
|
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 jsonPolygon = doCircle ?
|
||||||
|
tcircle(
|
||||||
|
[dsub.location.lon, dsub.location.lat], dsub.distance,
|
||||||
|
{ units: 'kilometers', steps: 144 }
|
||||||
|
) :
|
||||||
|
rectangleAround(
|
||||||
|
{ lon: dsub.location.lon, lat: dsub.location.lat },
|
||||||
|
dsub.distance,
|
||||||
|
(typeof dsub.distanceY !== 'undefined') ? dsub.distanceY : dsub.distance
|
||||||
|
);
|
||||||
|
unionGroup.push(jsonPolygon);
|
||||||
|
} else {
|
||||||
|
console.info(`Wrong element to do union ${JSON.stringify(osub)}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e, `Wrong element trying to make union ${JSON.stringify(osub)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const unionJson = unify(unionGroup);
|
||||||
|
return [unionJson, L.geoJSON(unionJson).getBounds()];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default calcUnion;
|
export default calcUnion;
|
||||||
|
|
|
||||||
|
|
@ -98,66 +98,66 @@ const App = props => (
|
||||||
/* https://react.i18next.com/components/i18nextprovider.html */
|
/* https://react.i18next.com/components/i18nextprovider.html */
|
||||||
<div>
|
<div>
|
||||||
{props.i18nReady.get() &&
|
{props.i18nReady.get() &&
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
<ErrorBoundary appName={i18n.t('AppNameFull')} title={i18n.t('general-error-title')} subTitle={i18n.t('general-error-description')}>
|
<ErrorBoundary appName={i18n.t('AppNameFull')} title={i18n.t('general-error-title')} subTitle={i18n.t('general-error-description')}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<LocationListener>
|
<LocationListener>
|
||||||
{ !props.loading &&
|
{ !props.loading &&
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<title>{i18n.t('AppName')}</title>
|
<title>{i18n.t('AppName')}</title>
|
||||||
<meta name="description" content={`${i18n.t('AppDescrip')}: ${i18n.t('AppDescripLong')}`} />
|
<meta name="description" content={`${i18n.t('AppDescrip')}: ${i18n.t('AppDescripLong')}`} />
|
||||||
<link rel="alternate" href={`https://fires.comunes.org${history.location.pathname}`} hrefLang="en" />
|
<link rel="alternate" href={`https://fires.comunes.org${history.location.pathname}`} hrefLang="en" />
|
||||||
<link rel="alternate" href={`https://fuegos.comunes.org${history.location.pathname}`} hrefLang="es" />
|
<link rel="alternate" href={`https://fuegos.comunes.org${history.location.pathname}`} hrefLang="es" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Navigation {...props} />
|
<Navigation {...props} />
|
||||||
<ReSendEmail {...props} />
|
<ReSendEmail {...props} />
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact name="index" path="/" component={Index} />
|
<Route exact name="index" path="/" component={Index} />
|
||||||
<Authenticated exact path="/subscriptions" component={Subscriptions} {...props} />
|
<Authenticated exact path="/subscriptions" component={Subscriptions} {...props} />
|
||||||
<Authenticated exact path="/subscriptions/new" component={NewSubscription} {...props} />
|
<Authenticated exact path="/subscriptions/new" component={NewSubscription} {...props} />
|
||||||
<Authenticated exact path="/subscriptions/:_id" component={ViewSubscription} {...props} />
|
<Authenticated exact path="/subscriptions/:_id" component={ViewSubscription} {...props} />
|
||||||
<Authenticated exact path="/subscriptions/:_id/edit" component={EditSubscription} {...props} />
|
<Authenticated exact path="/subscriptions/:_id/edit" component={EditSubscription} {...props} />
|
||||||
<Authenticated exact path="/profile" component={Profile} {...props} />
|
<Authenticated exact path="/profile" component={Profile} {...props} />
|
||||||
<Authenticated exact path="/status" component={Status} {...props} />
|
<Authenticated exact path="/status" component={Status} {...props} />
|
||||||
<Route path="/fires" component={FiresMap} industries={false} {...props} />
|
<Route path="/fires" component={FiresMap} industries={false} {...props} />
|
||||||
<Route path="/zones" component={ZonesMap} {...props} />
|
<Route path="/zones" component={ZonesMap} {...props} />
|
||||||
|
|
||||||
<Route path="/fire/:type(active|archive|alert)/:id" component={Fires} {...props} />
|
<Route path="/fire/:type(active|archive|alert)/:id" component={Fires} {...props} />
|
||||||
<Route path="/fire/:id" component={Fires} {...props} />
|
<Route path="/fire/:id" component={Fires} {...props} />
|
||||||
<Public path="/auth/:token" component={Auth} {...props} />
|
<Public path="/auth/:token" component={Auth} {...props} />
|
||||||
<Public path="/signup" component={Signup} {...props} />
|
<Public path="/signup" component={Signup} {...props} />
|
||||||
<Public path="/login" component={Login} {...props} />
|
<Public path="/login" component={Login} {...props} />
|
||||||
<Route path="/logout" component={Logout} {...props} />
|
<Route path="/logout" component={Logout} {...props} />
|
||||||
<Route path="/sandbox" component={Sandbox} {...props} />
|
<Route path="/sandbox" component={Sandbox} {...props} />
|
||||||
<Route path="/error" component={TestError} {...props} />
|
<Route path="/error" component={TestError} {...props} />
|
||||||
|
|
||||||
<Route name="verify-email" path="/verify-email/:token" component={VerifyEmail} />
|
<Route name="verify-email" path="/verify-email/:token" component={VerifyEmail} />
|
||||||
<Route name="recover-password" path="/recover-password" component={RecoverPassword} />
|
<Route name="recover-password" path="/recover-password" component={RecoverPassword} />
|
||||||
<Route name="reset-password" path="/reset-password/:token" component={ResetPassword} />
|
<Route name="reset-password" path="/reset-password/:token" component={ResetPassword} />
|
||||||
<Route name="terms" path="/terms" component={Terms} />
|
<Route name="terms" path="/terms" component={Terms} />
|
||||||
<Route name="privacy" path="/privacy" component={Privacy} />
|
<Route name="privacy" path="/privacy" component={Privacy} />
|
||||||
<Route name="license" path="/license" component={License} />
|
<Route name="license" path="/license" component={License} />
|
||||||
<Route name="credits" path="/credits" component={Credits} />
|
<Route name="credits" path="/credits" component={Credits} />
|
||||||
<Route name="about" path="/about" component={About} />
|
<Route name="about" path="/about" component={About} />
|
||||||
|
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Footer />
|
<Footer />
|
||||||
<Reconnect {...props} />
|
<Reconnect {...props} />
|
||||||
<Feedback {...props} />
|
<Feedback {...props} />
|
||||||
{props.i18nReady.get() && <Blaze template="cookieConsent" /> }
|
{props.i18nReady.get() && <Blaze template="cookieConsent" /> }
|
||||||
</div>}
|
</div>}
|
||||||
</LocationListener>
|
</LocationListener>
|
||||||
</Router>
|
</Router>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</I18nextProvider>
|
</I18nextProvider>
|
||||||
</ErrorBoundary> }
|
</ErrorBoundary> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -186,9 +186,7 @@ export default withTracker(() => {
|
||||||
const loading = !Roles.subscription.ready() || !i18nReady.get();
|
const loading = !Roles.subscription.ready() || !i18nReady.get();
|
||||||
const name = user && user.profile && user.profile.name && getUserName(user.profile.name);
|
const name = user && user.profile && user.profile.name && getUserName(user.profile.name);
|
||||||
const emailAddress = user && user.emails && user.emails[0].address;
|
const emailAddress = user && user.emails && user.emails[0].address;
|
||||||
Meteor.autorun(() => {
|
// console.log(`i18n ready?: ${i18nReady.get()}`);
|
||||||
console.log(`i18n ready?: ${i18nReady.get()}`);
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
loggingIn,
|
loggingIn,
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ import { Row, Col, Alert, FormGroup } from 'react-bootstrap';
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { Map, GeoJSON } from 'react-leaflet';
|
import { Map, Circle } from 'react-leaflet';
|
||||||
import { rectangleAround } from 'map-common-utils';
|
|
||||||
import Blaze from 'meteor/gadicc:blaze-react-component';
|
import Blaze from 'meteor/gadicc:blaze-react-component';
|
||||||
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
|
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
|
||||||
import NotFound from '/imports/ui/pages/NotFound/NotFound';
|
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 en {{where}} el {{when}}', { where: fire.address, when: this.dateLongFormat }) :
|
||||||
t('Información adicional sobre fuego detectado el {{when}}', { 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 (fire && !loading ? (
|
||||||
return (ready ? (
|
|
||||||
<div className="ViewFire">
|
<div className="ViewFire">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{t('AppName')}: {t('Información adicional sobre fuego')}</title>
|
<title>{t('AppName')}: {t('Información adicional sobre fuego')}</title>
|
||||||
|
|
@ -139,13 +137,14 @@ class Fire extends React.Component {
|
||||||
zoom={13}
|
zoom={13}
|
||||||
>
|
>
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<GeoJSON
|
<Circle
|
||||||
ref={(circle) => { this.circle = circle; this.handleLeafletCircleLoad(circle); }}
|
center={[fire.lat, fire.lon]}
|
||||||
data={rect}
|
|
||||||
color="red"
|
color="red"
|
||||||
stroke
|
fillColor="red"
|
||||||
width="1"
|
fillOpacity={0.0}
|
||||||
fillOpacity="0.0"
|
interactive={false}
|
||||||
|
radius={fire.scan ? fire.scan * 500 : 300}
|
||||||
|
ref={(circle) => { this.circle = circle; this.handleLeafletCircleLoad(circle); }}
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
<FireList
|
<FireList
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,9 @@ import 'leaflet-sleep/Leaflet.Sleep.js';
|
||||||
import geolocation from '/imports/startup/client/geolocation';
|
import geolocation from '/imports/startup/client/geolocation';
|
||||||
import CenterInMyPosition from '/imports/ui/components/CenterInMyPosition/CenterInMyPosition';
|
import CenterInMyPosition from '/imports/ui/components/CenterInMyPosition/CenterInMyPosition';
|
||||||
import FireList from '/imports/ui/components/Maps/FireList';
|
import FireList from '/imports/ui/components/Maps/FireList';
|
||||||
import FireListUnion from '/imports/ui/components/Maps/FireListUnion';
|
|
||||||
import subsUnion from '/imports/ui/components/Maps/SubsUnion/SubsUnion';
|
import subsUnion from '/imports/ui/components/Maps/SubsUnion/SubsUnion';
|
||||||
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
|
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
|
||||||
import ActiveFiresCollection from '/imports/api/ActiveFires/ActiveFires';
|
import ActiveFiresCollection from '/imports/api/ActiveFires/ActiveFires';
|
||||||
import ActiveFiresUnion from '/imports/api/ActiveFiresUnion/ActiveFiresUnion';
|
|
||||||
import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts';
|
import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts';
|
||||||
import IndustriesCollection, { industriesRemap } from '/imports/api/Industries/Industries';
|
import IndustriesCollection, { industriesRemap } from '/imports/api/Industries/Industries';
|
||||||
import FalsePositivesCollection, { falsePositivesRemap } from '/imports/api/FalsePositives/FalsePositives';
|
import FalsePositivesCollection, { falsePositivesRemap } from '/imports/api/FalsePositives/FalsePositives';
|
||||||
|
|
@ -84,6 +82,19 @@ class FiresMap extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
* const notMoving = !nextState.moving;
|
||||||
|
* const markersChanged = this.state.useMarkers !== nextState.useMarkers;
|
||||||
|
* const unionChanged = this.state.showSubsUnion !== nextState.showSubsUnion;
|
||||||
|
* const otherViewport = this.state.viewport !== nextState.viewport;
|
||||||
|
* // const init = nextState.viewport.center === [0, 0];
|
||||||
|
* // console.log(notMoving ? 'Not moving map' : 'Moving map');
|
||||||
|
* // console.log(otherViewport ? 'Other viewport' : 'Not other viewport');
|
||||||
|
* console.log(`${otherViewport ? 'OTHER' : 'Not other'} viewport ${nextState.viewport.center} zoom: ${nextState.viewport.zoom}`);
|
||||||
|
* return this.state.init || (notMoving && otherViewport && this.state.moved) || unionChanged || markersChanged;
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
const notMoving = !nextState.moving;
|
const notMoving = !nextState.moving;
|
||||||
return notMoving;
|
return notMoving;
|
||||||
|
|
@ -191,7 +202,6 @@ class FiresMap extends React.Component {
|
||||||
|
|
||||||
if (Meteor.isDevelopment && this.props.activefires.length === 1) console.log(`Active fire: ${JSON.stringify(this.props.activefires[0])}`);
|
if (Meteor.isDevelopment && this.props.activefires.length === 1) console.log(`Active fire: ${JSON.stringify(this.props.activefires[0])}`);
|
||||||
if (Meteor.isDevelopment) console.log(`Active fires total: ${this.props.activefires.length}`);
|
if (Meteor.isDevelopment) console.log(`Active fires total: ${this.props.activefires.length}`);
|
||||||
if (Meteor.isDevelopment) console.log(`Active fires union total: ${this.props.activefiresunion.length}`);
|
|
||||||
if (Meteor.isDevelopment) console.log(`False positives total: ${this.props.falsePositives.length}`);
|
if (Meteor.isDevelopment) console.log(`False positives total: ${this.props.falsePositives.length}`);
|
||||||
if (Meteor.isDevelopment) console.log(`Fire alerts total: ${this.props.firealerts.length}`);
|
if (Meteor.isDevelopment) console.log(`Fire alerts total: ${this.props.firealerts.length}`);
|
||||||
if (Meteor.isDevelopment) console.log(`Industries total: ${this.props.industries.length}`);
|
if (Meteor.isDevelopment) console.log(`Industries total: ${this.props.industries.length}`);
|
||||||
|
|
@ -236,7 +246,7 @@ class FiresMap extends React.Component {
|
||||||
<p className="firesmap-legend">
|
<p className="firesmap-legend">
|
||||||
{ (this.props.activefires.length + this.props.firealerts.length) === 0 ?
|
{ (this.props.activefires.length + this.props.firealerts.length) === 0 ?
|
||||||
<Fragment><Trans parent="span" i18nKey="noActiveFireInMapCount">No hay fuegos activos en esta zona del mapa. <strong>{{ countTotal: this.props.activefirestotal }}</strong> fuegos activos en el mundo.</Trans> <FireStats loadingAll={loading} {... this.props} /></Fragment> :
|
<Fragment><Trans parent="span" i18nKey="noActiveFireInMapCount">No hay fuegos activos en esta zona del mapa. <strong>{{ countTotal: this.props.activefirestotal }}</strong> fuegos activos en el mundo.</Trans> <FireStats loadingAll={loading} {... this.props} /></Fragment> :
|
||||||
<Fragment><Trans parent="span" i18nKey="activeFireInMapCount">En rojo, <strong>{{ count: this.props.activefiresunion.length + this.props.firealerts.length }}</strong> fuegos activos. <strong>{{ countTotal: this.props.activefirestotal }}</strong> fuegos activos en el mundo.</Trans> <FireStats loadingAll={loading} {... this.props} /></Fragment>
|
<Fragment><Trans parent="span" i18nKey="activeFireInMapCount">En rojo, <strong>{{ count: this.props.activefires.length + this.props.firealerts.length }}</strong> fuegos activos. <strong>{{ countTotal: this.props.activefirestotal }}</strong> fuegos activos en el mundo.</Trans> <FireStats loadingAll={loading} {... this.props} /></Fragment>
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
{isNotHomeAndMobile() && this.props.firealerts.length > 0 &&
|
{isNotHomeAndMobile() && this.props.firealerts.length > 0 &&
|
||||||
|
|
@ -297,14 +307,6 @@ class FiresMap extends React.Component {
|
||||||
neighbour={false}
|
neighbour={false}
|
||||||
industries={false}
|
industries={false}
|
||||||
/>
|
/>
|
||||||
{ Meteor.isDevelopment &&
|
|
||||||
<FireListUnion
|
|
||||||
t={t}
|
|
||||||
history={this.props.history}
|
|
||||||
firesUnion={this.props.activefiresunion}
|
|
||||||
nasa
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
<FireList
|
<FireList
|
||||||
t={t}
|
t={t}
|
||||||
history={this.props.history}
|
history={this.props.history}
|
||||||
|
|
@ -367,14 +369,12 @@ FiresMap.propTypes = {
|
||||||
userSubs: PropTypes.string,
|
userSubs: PropTypes.string,
|
||||||
userSubsBounds: PropTypes.string,
|
userSubsBounds: PropTypes.string,
|
||||||
activefires: PropTypes.arrayOf(PropTypes.object).isRequired,
|
activefires: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
activefiresunion: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
||||||
lastFireDetected: PropTypes.object,
|
lastFireDetected: PropTypes.object,
|
||||||
firealerts: PropTypes.arrayOf(PropTypes.object).isRequired,
|
firealerts: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
falsePositives: PropTypes.arrayOf(PropTypes.object).isRequired,
|
falsePositives: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
industries: PropTypes.arrayOf(PropTypes.object).isRequired,
|
industries: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
lastCheck: PropTypes.instanceOf(Date),
|
lastCheck: PropTypes.instanceOf(Date),
|
||||||
activefirestotal: PropTypes.number.isRequired,
|
activefirestotal: PropTypes.number.isRequired,
|
||||||
activefiresuniontotal: PropTypes.number.isRequired,
|
|
||||||
center: PropTypes.arrayOf(PropTypes.number),
|
center: PropTypes.arrayOf(PropTypes.number),
|
||||||
zoom: PropTypes.number,
|
zoom: PropTypes.number,
|
||||||
marks: PropTypes.bool.isRequired,
|
marks: PropTypes.bool.isRequired,
|
||||||
|
|
@ -391,7 +391,6 @@ export default translate([], { wait: true })(withTracker(() => {
|
||||||
// console.log(`With industries: ${withIndustries}`);
|
// console.log(`With industries: ${withIndustries}`);
|
||||||
|
|
||||||
let subscription;
|
let subscription;
|
||||||
let subscriptionUnion;
|
|
||||||
let alertSubscription;
|
let alertSubscription;
|
||||||
|
|
||||||
const centerStored = store.get('firesmap_center');
|
const centerStored = store.get('firesmap_center');
|
||||||
|
|
@ -423,14 +422,6 @@ export default translate([], { wait: true })(withTracker(() => {
|
||||||
mapSize.get()[1].lat,
|
mapSize.get()[1].lat,
|
||||||
marks.get() && zoom.get() >= MAXZOOM
|
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(
|
alertSubscription = Meteor.subscribe(
|
||||||
'fireAlerts',
|
'fireAlerts',
|
||||||
mapSize.get()[0].lng,
|
mapSize.get()[0].lng,
|
||||||
|
|
@ -451,7 +442,6 @@ export default translate([], { wait: true })(withTracker(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Meteor.subscribe('activefirestotal');
|
Meteor.subscribe('activefirestotal');
|
||||||
Meteor.subscribe('activefiresuniontotal');
|
|
||||||
|
|
||||||
const settingsSubs = Meteor.subscribe('settings');
|
const settingsSubs = Meteor.subscribe('settings');
|
||||||
const lastCheck = SiteSettings.findOne({ name: 'last-fire-check' });
|
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 } });
|
const lastFireDetected = ActiveFiresCollection.findOne({}, { sort: { when: -1 } });
|
||||||
|
|
||||||
return {
|
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() && settingsSubs.ready()),
|
||||||
userSubs: userSubs ? userSubs.value : null,
|
userSubs: userSubs ? userSubs.value : null,
|
||||||
userSubsBounds: userSubs ? userSubsBounds.value : null,
|
userSubsBounds: userSubs ? userSubsBounds.value : null,
|
||||||
subsready: settingsSubs.ready(),
|
subsready: settingsSubs.ready(),
|
||||||
// Not reactive query depending on zoom level
|
// Not reactive query depending on zoom level
|
||||||
activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
|
activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
|
||||||
activefiresunion: ActiveFiresUnion.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(),
|
|
||||||
activefirestotal: Counter.get('countActiveFires') + fireAlerts.length,
|
activefirestotal: Counter.get('countActiveFires') + fireAlerts.length,
|
||||||
activefiresuniontotal: Counter.get('countActiveFiresUnion') + fireAlerts.length,
|
|
||||||
firealerts: fireAlerts,
|
firealerts: fireAlerts,
|
||||||
falsePositives,
|
falsePositives,
|
||||||
industries,
|
industries,
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,9 @@ class Index extends Component {
|
||||||
</div>
|
</div>
|
||||||
<p className="moto"><Trans>Siempre alerta a los fuegos en nuestro vecindario</Trans></p>
|
<p className="moto"><Trans>Siempre alerta a los fuegos en nuestro vecindario</Trans></p>
|
||||||
{/* <Link className="participe-btn btn btn-lg btn-warning" role="button" to="/#platforms">{this.props.t('Participa')}</Link> */}
|
{/* <Link className="participe-btn btn btn-lg btn-warning" role="button" to="/#platforms">{this.props.t('Participa')}</Link> */}
|
||||||
<div className="android-btn">
|
<p>
|
||||||
<MobileStoreButton store="android" url={androidUrl} />
|
<MobileStoreButton store="android" url={androidUrl} />
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.android-btn > div {
|
|
||||||
height: 50px !important;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ class SubscriptionsMap extends React.Component {
|
||||||
|
|
||||||
handleLeafletLoad(map) {
|
handleLeafletLoad(map) {
|
||||||
// console.log('Map loading');
|
// console.log('Map loading');
|
||||||
if (map && this.props.userSubs !== 'null') {
|
// console.log(map);
|
||||||
// console.log(`Union of ${this.props.userSubs}`);
|
if (map) {
|
||||||
this.state.union = subsUnion(this.state.union, {
|
this.state.union = subsUnion(this.state.union, {
|
||||||
map,
|
map,
|
||||||
subs: this.props.userSubs,
|
subs: this.props.userSubs,
|
||||||
|
|
|
||||||
1091
package-lock.json
generated
1091
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "tcef",
|
"name": "tcef",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "QT_QPA_PLATFORM='' MONGO_URL=mongodb://fuegos:fuegos@localhost:27017/fuegos meteor --settings settings-development.json",
|
"start": "QT_QPA_PLATFORM='' MONGO_URL=mongodb://localhost:27017/fuegos meteor --settings settings-development.json",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -10,6 +10,9 @@
|
||||||
"@cleverbeagle/dates": "^0.5.1",
|
"@cleverbeagle/dates": "^0.5.1",
|
||||||
"@cleverbeagle/seeder": "^1.3.1",
|
"@cleverbeagle/seeder": "^1.3.1",
|
||||||
"@turf/buffer": "^5.1.5",
|
"@turf/buffer": "^5.1.5",
|
||||||
|
"@turf/circle": "^6.0.1",
|
||||||
|
"@turf/truncate": "^5.1.5",
|
||||||
|
"@turf/union": "^5.1.5",
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"bcrypt": "^1.0.3",
|
"bcrypt": "^1.0.3",
|
||||||
"bootstrap-carousel-swipe": "0.0.6",
|
"bootstrap-carousel-swipe": "0.0.6",
|
||||||
|
|
@ -39,10 +42,11 @@
|
||||||
"juice": "^4.2.2",
|
"juice": "^4.2.2",
|
||||||
"leaflet": "^1.3.1",
|
"leaflet": "^1.3.1",
|
||||||
"leaflet-graphicscale": "0.0.2",
|
"leaflet-graphicscale": "0.0.2",
|
||||||
|
"leaflet-headless": "^0.2.6",
|
||||||
"leaflet-sleep": "^0.5.1",
|
"leaflet-sleep": "^0.5.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"loms.perlin": "^1.0.1",
|
"loms.perlin": "^1.0.1",
|
||||||
"map-common-utils": "^0.5.0",
|
"map-common-utils": "^0.2.0",
|
||||||
"maxmind": "^2.3.0",
|
"maxmind": "^2.3.0",
|
||||||
"meteor-accounts-t9n": "^2.0.3",
|
"meteor-accounts-t9n": "^2.0.3",
|
||||||
"meteor-node-stubs": "^0.3.2",
|
"meteor-node-stubs": "^0.3.2",
|
||||||
|
|
@ -82,6 +86,7 @@
|
||||||
"react-router-hash-link": "^1.1.1",
|
"react-router-hash-link": "^1.1.1",
|
||||||
"react-share": "^2.0.0",
|
"react-share": "^2.0.0",
|
||||||
"reactstrap": "^5.0.0-alpha.3",
|
"reactstrap": "^5.0.0-alpha.3",
|
||||||
|
"segfault-handler": "^1.0.0",
|
||||||
"simpl-schema": "^1.5.0",
|
"simpl-schema": "^1.5.0",
|
||||||
"simple-line-icons": "^2.4.1",
|
"simple-line-icons": "^2.4.1",
|
||||||
"store": "^2.0.12",
|
"store": "^2.0.12",
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4761da921f467838a2c01b34e84a7703ee49b12c
|
Subproject commit 3346b6db70c153b1dd66e6a16a0ad28f10ebf740
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
/* eslint-env mocha */
|
|
||||||
/* eslint-disable func-names, prefer-arrow-callback */
|
|
||||||
/* eslint-disable import/no-absolute-path */
|
|
||||||
|
|
||||||
import { chai } from 'meteor/practicalmeteor:chai';
|
|
||||||
import ActiveFiresUnion from '/imports/api/ActiveFiresUnion/ActiveFiresUnion';
|
|
||||||
|
|
||||||
const centerid = { type: 'Point', coordinates: [-5.905956029891968, 43.55727622097011] };
|
|
||||||
const shape = { type: 'Polygon', coordinates: [[[-5.9084, 43.5558], [-5.906, 43.5558], [-5.906, 43.5566], [-5.9036, 43.5566], [-5.9036, 43.5583], [-5.9061, 43.5583], [-5.9061, 43.558], [-5.9084, 43.558], [-5.9084, 43.5558]]] };
|
|
||||||
const fireUnion = { centerid, shape, when: Date('2018-05-02T16:11:04.617Z') };
|
|
||||||
|
|
||||||
describe('activeFireUnion insert', () => {
|
|
||||||
it('should insert fire union', () => {
|
|
||||||
// Remove previous test register
|
|
||||||
const alreadyInserted = ActiveFiresUnion.findOne({ centerid });
|
|
||||||
if (alreadyInserted) {
|
|
||||||
ActiveFiresUnion.remove(alreadyInserted._id);
|
|
||||||
}
|
|
||||||
|
|
||||||
const insertedId = ActiveFiresUnion.insert(fireUnion);
|
|
||||||
ActiveFiresUnion.schema.validate(fireUnion);
|
|
||||||
|
|
||||||
const inserted = ActiveFiresUnion.findOne(insertedId);
|
|
||||||
delete inserted._id;
|
|
||||||
chai.expect(fireUnion).to.deep.equal(inserted);
|
|
||||||
ActiveFiresUnion.remove(insertedId);
|
|
||||||
chai.expect(ActiveFiresUnion.find({ _id: inserted }).count()).equal(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue