Subs union to server side
This commit is contained in:
parent
ed7c89476f
commit
ac4331edbd
10 changed files with 299 additions and 162 deletions
|
|
@ -3,43 +3,8 @@
|
|||
import { Meteor } from 'meteor/meteor';
|
||||
import { Mongo } from 'meteor/mongo';
|
||||
import { check } from 'meteor/check';
|
||||
import Perlin from 'loms.perlin';
|
||||
import Subscriptions from '../Subscriptions';
|
||||
|
||||
Perlin.seed(Math.random());
|
||||
|
||||
Meteor.publishTransformed('userSubsToFires', function transform() {
|
||||
// https://en.wikipedia.org/wiki/Location_obfuscation
|
||||
// https://en.wikipedia.org/wiki/Decimal_degrees#Precision
|
||||
// https://gis.stackexchange.com/questions/27792/what-simple-effective-techniques-for-obfuscating-points-are-available
|
||||
return Subscriptions.find().serverTransform(function transformDoc(odoc) {
|
||||
const doc = odoc;
|
||||
// Destructuring gives me an error: "Cannot destructure property `location` of 'undefined'"
|
||||
const location = doc.location;
|
||||
/* doc.lat = location.lat;
|
||||
* doc.lon = location.lon; */
|
||||
let lat;
|
||||
let lon;
|
||||
if (location) {
|
||||
lat = Math.round(location.lat * 10) / 10;
|
||||
lon = Math.round(location.lon * 10) / 10;
|
||||
// console.log(`[${lat}, ${lon}]`);
|
||||
const noiseBase = Perlin.perlin2(lat, lon);
|
||||
const noise = Math.abs(noiseBase / 3);
|
||||
// console.log(`Noise ${noise}, abs: ${Math.abs(noise)}`);
|
||||
lat += noise;
|
||||
lon += noise;
|
||||
doc.location.lat = lat;
|
||||
doc.location.lon = lon;
|
||||
doc.distance += noiseBase;
|
||||
}
|
||||
// console.log(`with noise: [${doc.lat}, ${doc.lon}]`);
|
||||
delete doc.chatId;
|
||||
delete doc.geo;
|
||||
return doc;
|
||||
});
|
||||
});
|
||||
|
||||
Meteor.publish('mysubscriptions', function subscriptions() {
|
||||
return Subscriptions.find({ owner: this.userId }); // type: 'web'
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ import './notificationsObserver';
|
|||
import './facts';
|
||||
import '../common/comments';
|
||||
import './sitemaps';
|
||||
import './subsUnion';
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Meteor.startup(() => {
|
|||
|
||||
Migrations.config({
|
||||
// Log job run details to console
|
||||
log: true
|
||||
log: Meteor.isProduction
|
||||
});
|
||||
|
||||
Migrations.add({
|
||||
|
|
@ -120,7 +120,7 @@ Meteor.startup(() => {
|
|||
Migrations.add({
|
||||
version: 8,
|
||||
up: function siteSettingsAddIndex() {
|
||||
SiteSettings._ensureIndex({ isPublic: 1 }, { unique: 1 });
|
||||
SiteSettings._ensureIndex({ isPublic: 1 });
|
||||
SiteSettings.find({ isPublic: null }).forEach((setting) => {
|
||||
SiteSettings.update({ _id: setting._id }, { $set: { isPublic: true } });
|
||||
});
|
||||
|
|
|
|||
84
imports/startup/server/subsUnion.js
Normal file
84
imports/startup/server/subsUnion.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* eslint-disable import/no-absolute-path */
|
||||
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import Subscriptions from '/imports/api/Subscriptions/Subscriptions';
|
||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||
import Perlin from 'loms.perlin';
|
||||
import L from 'leaflet-headless';
|
||||
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
||||
|
||||
// sudo apt-get install libcairo2-dev libjpeg-dev libgif-dev
|
||||
|
||||
Meteor.startup(() => {
|
||||
Perlin.seed(Math.random());
|
||||
|
||||
const addNoisy = (osub) => {
|
||||
const sub = osub;
|
||||
let lat = Math.round(sub.location.lat * 10) / 10;
|
||||
let lon = Math.round(sub.location.lon * 10) / 10;
|
||||
const noiseBase = Perlin.perlin2(lat, lon);
|
||||
const noise = Math.abs(noiseBase / 3);
|
||||
lat += noise;
|
||||
lon += noise;
|
||||
sub.location.lat = lat;
|
||||
sub.location.lon = lon;
|
||||
sub.distance += noiseBase;
|
||||
return sub;
|
||||
};
|
||||
|
||||
const process = () => {
|
||||
const group = new L.FeatureGroup();
|
||||
const result = calcUnion(Subscriptions.find().fetch(), group, addNoisy);
|
||||
const union = result[0];
|
||||
const bounds = result[1];
|
||||
|
||||
if (typeof union === 'object') {
|
||||
const unionSet = {
|
||||
$set: {
|
||||
name: 'subs-public-union',
|
||||
value: JSON.stringify(union),
|
||||
isPublic: true,
|
||||
description: 'Public subscriptions union',
|
||||
type: 'string'
|
||||
}
|
||||
};
|
||||
const boundsSet = {
|
||||
$set: {
|
||||
name: 'subs-public-union-bounds',
|
||||
value: JSON.stringify(bounds),
|
||||
isPublic: true,
|
||||
description: 'Public subscriptions union bounds',
|
||||
type: 'string'
|
||||
}
|
||||
};
|
||||
// FIXME, take care of object size:
|
||||
// https://stackoverflow.com/questions/10827812/what-is-the-length-maximum-for-a-string-data-type-in-mongodb-used-with-ruby
|
||||
SiteSettings.upsert({ name: 'subs-public-union' }, unionSet, { multi: false });
|
||||
SiteSettings.upsert({ name: 'subs-public-union-bounds' }, boundsSet, { multi: false });
|
||||
if (Meteor.isDevelopment) console.log('Subscription union calculated');
|
||||
} else {
|
||||
console.log('Subscription union failed!');
|
||||
}
|
||||
};
|
||||
|
||||
// At startup
|
||||
process();
|
||||
|
||||
Subscriptions.find({ createdAt: { $gt: new Date() } }).observe({
|
||||
added: function newSubAdded() { // doc) {
|
||||
if (Meteor.isDevelopment) console.log('Subs added so recreate union');
|
||||
process();
|
||||
}
|
||||
});
|
||||
|
||||
Subscriptions.find().observe({
|
||||
changed: function subsChanged() { // updatedDoc, oldDoc) {
|
||||
if (Meteor.isDevelopment) console.log('Subs changed so recreate union');
|
||||
process();
|
||||
},
|
||||
removed: function subsRemoved() { // oldDoc) {
|
||||
if (Meteor.isDevelopment) console.log('Subs removed so recreate union');
|
||||
process();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -3,89 +3,43 @@
|
|||
/* eslint-disable import/no-absolute-path */
|
||||
/* global L */
|
||||
|
||||
import { Map } from 'react-leaflet';
|
||||
import LGeo from 'leaflet-geodesy';
|
||||
import tunion from '@turf/union';
|
||||
import ttrunc from '@turf/truncate';
|
||||
import { check, Match } from 'meteor/check';
|
||||
|
||||
// https://stackoverflow.com/questions/35394577/leaflet-js-union-merge-circles
|
||||
const truncOptions = { precision: 6, coordinates: 2 };
|
||||
|
||||
function 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;
|
||||
}
|
||||
import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify';
|
||||
|
||||
const subsUnion = (union, options) => {
|
||||
// check(union, Match.Optional(Object));
|
||||
check(options, {
|
||||
map: Map,
|
||||
show: Boolean,
|
||||
subs: [Object],
|
||||
color: Match.Optional(String),
|
||||
fillcolor: Match.Optional(String),
|
||||
opacity: Match.Optional(Number),
|
||||
fit: Boolean
|
||||
});
|
||||
|
||||
const color = options.color || '#145A32';
|
||||
const fillColor = options.fillColor || 'green';
|
||||
const opacity = options.options || 0.1;
|
||||
|
||||
if (options.subs) {
|
||||
const lmap = options.map.leafletElement;
|
||||
// http://leafletjs.com/reference-1.2.0.html#layergroup
|
||||
// FeatureGroup has getBounds
|
||||
const unionGroup = new L.FeatureGroup();
|
||||
|
||||
if (union) {
|
||||
lmap.removeLayer(union);
|
||||
}
|
||||
union = null;
|
||||
|
||||
if (options.subs.length > 0 && options.show) {
|
||||
// http://leafletjs.com/reference-1.2.0.html#path
|
||||
const copts = {
|
||||
parts: 144
|
||||
};
|
||||
options.subs.forEach((sub) => {
|
||||
try {
|
||||
if (sub.location && sub.location.lat && sub.location.lon && sub.distance) {
|
||||
check(sub.location.lon, Number);
|
||||
check(sub.location.lat, Number);
|
||||
check(sub.distance, Number);
|
||||
const circle = LGeo.circle([sub.location.lat, sub.location.lon], sub.distance * 1000, copts);
|
||||
circle.addTo(unionGroup);
|
||||
} else {
|
||||
console.error(`Wrong subscription ${JSON.stringify(sub)}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
console.error(`Wrong subscription trying to make union ${JSON.stringify(sub)}`);
|
||||
if (options.show) {
|
||||
if (options.fromServer) {
|
||||
// We get the json from server side
|
||||
union = L.geoJson(JSON.parse(options.subs));
|
||||
union.setStyle({ color, fillColor, fillOpacity: opacity });
|
||||
union.addTo(lmap);
|
||||
if (options.fit && options.bounds) {
|
||||
// console.log(options.bounds);
|
||||
const bounds = JSON.parse(options.bounds);
|
||||
options.map.leafletElement.fitBounds(L.latLngBounds(bounds._northEast, bounds._southWest));
|
||||
}
|
||||
} else if (options.subs.length > 0) {
|
||||
const unionGroup = new L.FeatureGroup();
|
||||
const result = calcUnion(options.subs, unionGroup, sub => sub);
|
||||
const unionJson = result[0];
|
||||
const bounds = result[1];
|
||||
|
||||
union = L.geoJson(unionJson);
|
||||
union.setStyle({ color, fillColor, fillOpacity: opacity });
|
||||
union.addTo(lmap);
|
||||
if (options.fit) {
|
||||
options.map.leafletElement.fitBounds(bounds);
|
||||
}
|
||||
});
|
||||
const unionJson = unify(unionGroup.getLayers());
|
||||
union = L.geoJson(unionJson);
|
||||
union.setStyle({
|
||||
color,
|
||||
fillColor,
|
||||
fillOpacity: opacity
|
||||
});
|
||||
union.addTo(lmap);
|
||||
if (options.fit) {
|
||||
options.map.leafletElement.fitBounds(unionGroup.getBounds());
|
||||
}
|
||||
return union;
|
||||
}
|
||||
}
|
||||
return union;
|
||||
|
|
|
|||
48
imports/ui/components/Maps/SubsUnion/Unify.js
Normal file
48
imports/ui/components/Maps/SubsUnion/Unify.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { check } from 'meteor/check';
|
||||
import LGeo from 'leaflet-geodesy';
|
||||
import tunion from '@turf/union';
|
||||
import ttrunc from '@turf/truncate';
|
||||
|
||||
// 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.error(`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;
|
||||
|
|
@ -29,7 +29,6 @@ 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';
|
||||
import { isHome } from '/imports/ui/components/Utils/location';
|
||||
import ShareIt from '/imports/ui/components/ShareIt/ShareIt';
|
||||
|
|
@ -174,6 +173,8 @@ class FiresMap extends React.Component {
|
|||
map,
|
||||
subs: this.props.userSubs,
|
||||
show: this.state.showSubsUnion,
|
||||
bounds: this.props.userSubsBounds,
|
||||
fromServer: true,
|
||||
fit: false
|
||||
});
|
||||
}
|
||||
|
|
@ -181,7 +182,7 @@ 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. False positives: ${this.props.falsePositives.length}. 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}. Reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
|
||||
const title = `${t('AppName')}: ${t('Fuegos activos')}`;
|
||||
if (Meteor.isDevelopment) {
|
||||
console.log(`False positives total: ${this.props.falsePositivesTotal}`);
|
||||
|
|
@ -315,7 +316,8 @@ class FiresMap extends React.Component {
|
|||
FiresMap.propTypes = {
|
||||
loading: PropTypes.bool.isRequired,
|
||||
subsready: PropTypes.bool.isRequired,
|
||||
userSubs: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
userSubs: PropTypes.string,
|
||||
userSubsBounds: PropTypes.string,
|
||||
activefires: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
firealerts: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
falsePositives: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
|
|
@ -379,15 +381,17 @@ export default translate([], { wait: true })(withTracker(() => {
|
|||
|
||||
Meteor.subscribe('activefirestotal');
|
||||
Meteor.subscribe('falsePositivesTotal');
|
||||
Meteor.subscribe('settings');
|
||||
const userSubs = Meteor.subscribe('userSubsToFires');
|
||||
const settingsSubs = Meteor.subscribe('settings');
|
||||
const lastCheck = SiteSettings.findOne({ name: 'last-fire-check' });
|
||||
const userSubs = SiteSettings.findOne({ name: 'subs-public-union' });
|
||||
const userSubsBounds = SiteSettings.findOne({ name: 'subs-public-union-bounds' });
|
||||
const fireAlerts = FireAlertsCollection.find().fetch();
|
||||
const falsePositives = FalsePositivesCollection.find().fetch();
|
||||
return {
|
||||
loading: !subscription ? true : !subscription.ready(),
|
||||
userSubs: UserSubsToFiresCollection.find().fetch(),
|
||||
subsready: userSubs.ready(),
|
||||
loading: !subscription ? true : !(subscription.ready() && settingsSubs.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(),
|
||||
activefirestotal: Counter.get('countActiveFires') + fireAlerts.length,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import CenterInMyPosition from '/imports/ui/components/CenterInMyPosition/Center
|
|||
import subsUnion from '/imports/ui/components/Maps/SubsUnion/SubsUnion';
|
||||
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
|
||||
import Loading from '/imports/ui/components/Loading/Loading';
|
||||
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||
import { isChrome } from '/imports/ui/components/Utils/isMobile';
|
||||
import { isHome } from '/imports/ui/components/Utils/location';
|
||||
import ShareIt from '/imports/ui/components/ShareIt/ShareIt';
|
||||
|
|
@ -66,6 +66,8 @@ class SubscriptionsMap extends React.Component {
|
|||
this.state.union = subsUnion(this.state.union, {
|
||||
map,
|
||||
subs: this.props.userSubs,
|
||||
bounds: this.props.userSubsBounds,
|
||||
fromServer: true,
|
||||
show: true,
|
||||
fit: this.state.init
|
||||
});
|
||||
|
|
@ -89,7 +91,7 @@ class SubscriptionsMap extends React.Component {
|
|||
render() {
|
||||
const { t } = this.props;
|
||||
const title = `${t('AppName')}: ${t('Zonas vigiladas')}`;
|
||||
console.log(`Rendering Subs users ready ${this.props.subsready} subs: ${this.props.userSubs.length} viewport: ${JSON.stringify(this.state.viewport)}`);
|
||||
console.log(`Rendering Subs users ready ${this.props.subsready} viewport: ${JSON.stringify(this.state.viewport)}`);
|
||||
return (
|
||||
<Fragment>
|
||||
{ !isHome() &&
|
||||
|
|
@ -153,16 +155,20 @@ class SubscriptionsMap extends React.Component {
|
|||
}
|
||||
|
||||
SubscriptionsMap.propTypes = {
|
||||
userSubs: PropTypes.string,
|
||||
userSubsBounds: PropTypes.string,
|
||||
subsready: PropTypes.bool.isRequired,
|
||||
userSubs: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
t: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default translate([], { wait: true })(withTracker(() => {
|
||||
const userSubs = Meteor.subscribe('userSubsToFires');
|
||||
const settingsSubs = Meteor.subscribe('settings');
|
||||
const userSubs = SiteSettings.findOne({ name: 'subs-public-union' });
|
||||
const userSubsBounds = SiteSettings.findOne({ name: 'subs-public-union-bounds' });
|
||||
return {
|
||||
userSubs: UserSubsToFiresCollection.find().fetch(),
|
||||
subsready: userSubs.ready()
|
||||
userSubs: userSubs ? userSubs.value : null,
|
||||
userSubsBounds: userSubs ? userSubsBounds.value : null,
|
||||
subsready: settingsSubs.ready()
|
||||
};
|
||||
})(SubscriptionsMap));
|
||||
|
|
|
|||
158
package-lock.json
generated
158
package-lock.json
generated
|
|
@ -60,8 +60,7 @@
|
|||
"abab": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
|
||||
"integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=",
|
||||
"dev": true
|
||||
"integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4="
|
||||
},
|
||||
"acorn": {
|
||||
"version": "5.2.1",
|
||||
|
|
@ -282,8 +281,7 @@
|
|||
"array-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
|
||||
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
|
||||
"dev": true
|
||||
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM="
|
||||
},
|
||||
"array-includes": {
|
||||
"version": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
|
||||
|
|
@ -2247,6 +2245,14 @@
|
|||
"integrity": "sha1-H5CV8u/UlA4LpsWZKreptkzDW6Q=",
|
||||
"dev": true
|
||||
},
|
||||
"canvas": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/canvas/-/canvas-1.6.9.tgz",
|
||||
"integrity": "sha1-4/lc7HsWvy1vP8clwC2UDTJY9ps=",
|
||||
"requires": {
|
||||
"nan": "2.6.2"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
|
|
@ -2778,8 +2784,7 @@
|
|||
"content-type-parser": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.2.tgz",
|
||||
"integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ=="
|
||||
},
|
||||
"convert-source-map": {
|
||||
"version": "1.5.1",
|
||||
|
|
@ -2909,14 +2914,12 @@
|
|||
"cssom": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz",
|
||||
"integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=",
|
||||
"dev": true
|
||||
"integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs="
|
||||
},
|
||||
"cssstyle": {
|
||||
"version": "0.2.37",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz",
|
||||
"integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cssom": "0.3.2"
|
||||
}
|
||||
|
|
@ -2930,6 +2933,11 @@
|
|||
"es5-ext": "0.10.37"
|
||||
}
|
||||
},
|
||||
"d3-queue": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-2.0.3.tgz",
|
||||
"integrity": "sha1-B/vaOsrlNYqcUpmq+ICt8JU+0sI="
|
||||
},
|
||||
"damerau-levenshtein": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
|
||||
|
|
@ -3331,7 +3339,6 @@
|
|||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz",
|
||||
"integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esprima": "3.1.3",
|
||||
"estraverse": "4.2.0",
|
||||
|
|
@ -3343,38 +3350,32 @@
|
|||
"deep-is": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||
"dev": true
|
||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
|
||||
"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
|
||||
"dev": true
|
||||
"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
||||
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
|
||||
"dev": true
|
||||
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
||||
"dev": true
|
||||
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
|
||||
},
|
||||
"fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||
},
|
||||
"levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prelude-ls": "1.1.2",
|
||||
"type-check": "0.3.2"
|
||||
|
|
@ -3384,7 +3385,6 @@
|
|||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
|
||||
"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"deep-is": "0.1.3",
|
||||
"fast-levenshtein": "2.0.6",
|
||||
|
|
@ -3397,21 +3397,18 @@
|
|||
"prelude-ls": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
|
||||
"dev": true
|
||||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prelude-ls": "1.1.2"
|
||||
}
|
||||
|
|
@ -3419,8 +3416,7 @@
|
|||
"wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
|
||||
"dev": true
|
||||
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4941,7 +4937,6 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
|
||||
"integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"whatwg-encoding": "1.0.3"
|
||||
}
|
||||
|
|
@ -7451,6 +7446,92 @@
|
|||
"resolved": "https://registry.npmjs.org/leaflet-graphicscale/-/leaflet-graphicscale-0.0.2.tgz",
|
||||
"integrity": "sha1-q2INKJ6acETC9RB8g74XhDrsUwM="
|
||||
},
|
||||
"leaflet-headless": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/leaflet-headless/-/leaflet-headless-0.2.6.tgz",
|
||||
"integrity": "sha1-Hqh4c/fuJj/JyI3xXsx4qZUdcsk=",
|
||||
"requires": {
|
||||
"canvas": "1.6.9",
|
||||
"jsdom": "9.8.3",
|
||||
"leaflet": "1.3.1",
|
||||
"leaflet-image": "0.4.0",
|
||||
"request": "2.83.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
|
||||
"integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc="
|
||||
},
|
||||
"acorn-globals": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz",
|
||||
"integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=",
|
||||
"requires": {
|
||||
"acorn": "2.7.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
|
||||
},
|
||||
"jsdom": {
|
||||
"version": "9.8.3",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.8.3.tgz",
|
||||
"integrity": "sha1-/eKcEJwyoRMeC2xlkU5kGY+Xw3A=",
|
||||
"requires": {
|
||||
"abab": "1.0.4",
|
||||
"acorn": "2.7.0",
|
||||
"acorn-globals": "1.0.9",
|
||||
"array-equal": "1.0.0",
|
||||
"content-type-parser": "1.0.2",
|
||||
"cssom": "0.3.2",
|
||||
"cssstyle": "0.2.37",
|
||||
"escodegen": "1.9.0",
|
||||
"html-encoding-sniffer": "1.0.2",
|
||||
"iconv-lite": "0.4.19",
|
||||
"nwmatcher": "1.4.3",
|
||||
"parse5": "1.5.1",
|
||||
"request": "2.83.0",
|
||||
"sax": "1.2.4",
|
||||
"symbol-tree": "3.2.2",
|
||||
"tough-cookie": "2.3.3",
|
||||
"webidl-conversions": "3.0.1",
|
||||
"whatwg-encoding": "1.0.3",
|
||||
"whatwg-url": "3.1.0",
|
||||
"xml-name-validator": "2.0.1"
|
||||
}
|
||||
},
|
||||
"parse5": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz",
|
||||
"integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ="
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-3.1.0.tgz",
|
||||
"integrity": "sha1-e9yuSQ+SGu9kUftnOexrvY6Qe/Y=",
|
||||
"requires": {
|
||||
"tr46": "0.0.3",
|
||||
"webidl-conversions": "3.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"leaflet-image": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/leaflet-image/-/leaflet-image-0.4.0.tgz",
|
||||
"integrity": "sha1-6E8i/2KI8JubDi9RpIUKnweWjME=",
|
||||
"requires": {
|
||||
"d3-queue": "2.0.3"
|
||||
}
|
||||
},
|
||||
"leaflet-sleep": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/leaflet-sleep/-/leaflet-sleep-0.5.1.tgz",
|
||||
|
|
@ -9028,8 +9109,7 @@
|
|||
"nwmatcher": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.3.tgz",
|
||||
"integrity": "sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw=="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
|
|
@ -10887,8 +10967,7 @@
|
|||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.4.1",
|
||||
|
|
@ -11291,8 +11370,7 @@
|
|||
"symbol-tree": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
|
||||
"integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=",
|
||||
"dev": true
|
||||
"integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY="
|
||||
},
|
||||
"table": {
|
||||
"version": "4.0.2",
|
||||
|
|
@ -11479,8 +11557,7 @@
|
|||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
|
||||
"dev": true
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"trim-right": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -11688,7 +11765,6 @@
|
|||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz",
|
||||
"integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"iconv-lite": "0.4.19"
|
||||
},
|
||||
|
|
@ -11696,8 +11772,7 @@
|
|||
"iconv-lite": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -11865,8 +11940,7 @@
|
|||
"xml-name-validator": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz",
|
||||
"integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=",
|
||||
"dev": true
|
||||
"integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1",
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"leaflet": "^1.3.1",
|
||||
"leaflet-geodesy": "^0.2.1",
|
||||
"leaflet-graphicscale": "0.0.2",
|
||||
"leaflet-headless": "^0.2.6",
|
||||
"leaflet-sleep": "^0.5.1",
|
||||
"lodash": "^4.17.4",
|
||||
"loms.perlin": "^1.0.1",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue