diff --git a/imports/api/FalsePositives/FalsePositiveTypes.js b/imports/api/FalsePositives/FalsePositiveTypes.js
new file mode 100644
index 0000000..9c8b5fb
--- /dev/null
+++ b/imports/api/FalsePositives/FalsePositiveTypes.js
@@ -0,0 +1,7 @@
+const types = {
+ industry: 'Es una industria (altos hornos, incineradora, etc)',
+ controled: 'Es una quema controlada',
+ falsealarm: 'Parece una falsa alarma'
+};
+
+export default types;
diff --git a/imports/api/FalsePositives/FalsePositives.js b/imports/api/FalsePositives/FalsePositives.js
new file mode 100644
index 0000000..592fe12
--- /dev/null
+++ b/imports/api/FalsePositives/FalsePositives.js
@@ -0,0 +1,37 @@
+/* eslint-disable consistent-return */
+
+import { Meteor } from 'meteor/meteor';
+import { Mongo } from 'meteor/mongo';
+import SimpleSchema from 'simpl-schema';
+import { defaultCreatedAt, defaultUpdateAt } from '/imports/api/Utility/Utils.js';
+import LocationSchema from '/imports/api/Utility/LocationSchema.js';
+
+const FalsePositives = new Mongo.Collection('falsePositives', { idGeneration: 'MONGO' });
+
+FalsePositives.allow({
+ insert: () => false,
+ update: () => false,
+ remove: () => false
+});
+
+FalsePositives.deny({
+ insert: () => true,
+ update: () => true,
+ remove: () => true
+});
+
+FalsePositives.schema = new SimpleSchema({
+ geo: LocationSchema,
+ fireId: { type: Meteor.Collection.ObjectID, optional: true, blackbox: true },
+ chatId: { type: Number, optional: true }, // only in 'telegram' type
+ owner: String,
+ type: String,
+ when: Date,
+ whendateformat: String,
+ createdAt: defaultCreatedAt,
+ updatedAt: defaultUpdateAt
+});
+
+FalsePositives.attachSchema(FalsePositives.schema);
+
+export default FalsePositives;
diff --git a/imports/api/FalsePositives/methods.js b/imports/api/FalsePositives/methods.js
new file mode 100644
index 0000000..7aa4ef1
--- /dev/null
+++ b/imports/api/FalsePositives/methods.js
@@ -0,0 +1,53 @@
+import { Meteor } from 'meteor/meteor';
+import { check } from 'meteor/check';
+import moment from 'moment';
+import FalsePositives from './FalsePositives';
+import FalsePositiveTypes from './FalsePositiveTypes';
+import Fires from '../Fires/Fires';
+import rateLimit from '../../modules/rate-limit';
+
+Meteor.methods({
+ 'falsePositives.insert': function falsePositivesInsert(fireId, keyType) {
+ check(fireId, Meteor.Collection.ObjectID);
+ check(keyType, String);
+ const type = FalsePositiveTypes[keyType];
+ check(type, String);
+ if (!this.userId) {
+ throw new Meteor.Error('500', 'Regístrate o inicia sesión para aportar información sobre este fuego');
+ }
+ check(this.userId, String);
+ const fire = Fires.findOne(fireId);
+ if (fire) {
+ const fireType = fire.type;
+ if (fireType === 'vecinal') {
+ throw new Meteor.Error('500', 'No se puede marcar este tipo de fuego');
+ }
+ const date = new Date();
+ const formated = moment(date).format('YYYYMMDD');
+ try {
+ const set = {
+ owner: this.userId,
+ type: keyType,
+ when: date,
+ whendateformat: formated,
+ fireId,
+ geo: fire.ourid
+ };
+ return FalsePositives.upsert({ geo: fire.ourid, owner: this.userId }, { $set: set }, { multi: false, upsert: true });
+ } catch (exception) {
+ console.log(exception);
+ throw new Meteor.Error('500', exception);
+ }
+ } else {
+ throw new Meteor.Error('500', 'Fuego no encontrado');
+ }
+ }
+});
+
+rateLimit({
+ methods: [
+ 'falsePositives.insert'
+ ],
+ limit: 5,
+ timeRange: 1000
+});
diff --git a/imports/api/Fires/server/publications.js b/imports/api/Fires/server/publications.js
index de67f8b..a7c0c43 100644
--- a/imports/api/Fires/server/publications.js
+++ b/imports/api/Fires/server/publications.js
@@ -30,13 +30,11 @@ Meteor.publish('fireFromHash', function fireFromHash(fireEnc) {
// console.log(fireEnc);
const unsealed = Promise.await(urlEnc.decrypt(fireEnc));
const w = unsealed.when;
- // console.log(w);
unsealed.when = new Date(w);
- // console.log(unsealed.when);
const c = unsealed.createdAt;
- unsealed.createdAt = new Date(c);
+ unsealed.createdAt = !c ? new Date() : new Date(c);
const u = unsealed.updatedAt;
- unsealed.updatedAt = new Date(u);
+ unsealed.updatedAt = !u ? new Date() : new Date(u);
// console.log(unsealed);
FiresCollection.schema.validate(unsealed);
const fire = findFire(unsealed);
diff --git a/imports/startup/common/comments.js b/imports/startup/common/comments.js
index 379f836..09fa297 100644
--- a/imports/startup/common/comments.js
+++ b/imports/startup/common/comments.js
@@ -9,7 +9,7 @@ Comments.config({
profile: 1
},
generateUsername: function genUser(user) {
- console.log(JSON.stringify(user));
+ // console.log(JSON.stringify(user));
// FIXME
return user.profile && user.profile.name && user.profile.name.first ? user.profile.name.first : '';
}
diff --git a/imports/startup/server/api.js b/imports/startup/server/api.js
index 64b3e9f..0fcde5d 100644
--- a/imports/startup/server/api.js
+++ b/imports/startup/server/api.js
@@ -24,3 +24,5 @@ import '../../api/Fires/server/publications';
import '../../api/SiteSettings/methods';
import '../../api/SiteSettings/server/publications';
+
+import '../../api/FalsePositives/methods';
diff --git a/imports/startup/server/migrations.js b/imports/startup/server/migrations.js
index 1c49a4c..a4482f0 100644
--- a/imports/startup/server/migrations.js
+++ b/imports/startup/server/migrations.js
@@ -6,6 +6,7 @@ import randomHex from 'crypto-random-hex';
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts';
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
+import FalsePositives from '/imports/api/FalsePositives/FalsePositives';
Meteor.startup(() => {
// https://github.com/percolatestudio/meteor-migrations
@@ -92,6 +93,17 @@ Meteor.startup(() => {
}
});
+ Migrations.add({
+ version: 6,
+ up: function falsePositiveIndexes() {
+ FalsePositives._ensureIndex({ chatId: 1 });
+ FalsePositives._ensureIndex({ owner: 1 });
+ FalsePositives._ensureIndex({ fireId: 1 });
+ FalsePositives._ensureIndex({ type: 1 });
+ FalsePositives._ensureIndex({ geo: '2dsphere' });
+ }
+ });
+
// Set createdAt in users & subs
Migrations.migrateTo('latest');
diff --git a/imports/ui/pages/Fires/Fires.js b/imports/ui/pages/Fires/Fires.js
index 38c7aad..fce9edd 100644
--- a/imports/ui/pages/Fires/Fires.js
+++ b/imports/ui/pages/Fires/Fires.js
@@ -6,7 +6,9 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { withTracker } from 'meteor/react-meteor-data';
import { translate, Trans } from 'react-i18next';
+import { FormGroup } from 'react-bootstrap';
import { Meteor } from 'meteor/meteor';
+import { Bert } from 'meteor/themeteorchef:bert';
import { Map, Circle } from 'react-leaflet';
import Blaze from 'meteor/gadicc:blaze-react-component';
import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers';
@@ -15,6 +17,7 @@ import FiresCollection from '/imports/api/Fires/Fires';
import FromNow from '/imports/ui/components/FromNow/FromNow';
import { dateLongFormat } from '/imports/api/Common/dates';
import '/imports/startup/client/comments';
+import FalsePositiveTypes from '/imports/api/FalsePositives/FalsePositiveTypes';
import './Fires.scss';
class Fire extends React.Component {
@@ -38,14 +41,25 @@ class Fire extends React.Component {
return !(nextState.when === this.state.when);
}
+ onTypeSelect(key) {
+ // console.log(key);
+ Meteor.call('falsePositives.insert', this.props.fire._id, key, (error) => {
+ if (error) {
+ // console.log(error);
+ Bert.alert(this.props.t(error.reason), 'danger');
+ } else {
+ Bert.alert(this.props.t('Tomamos nota, ¡gracias por colaborar!'), 'success');
+ }
+ });
+ }
+
render() {
const { loading, fire, t } = this.props;
if (fire && fire.when) {
this.dateLongFormat = dateLongFormat(fire.when);
- // this.dateFromNow = () => (