From 08b3289f4d58f71767f7e3a6903635cb1caa674c Mon Sep 17 00:00:00 2001 From: vjrj Date: Mon, 12 Feb 2018 19:52:22 +0100 Subject: [PATCH 001/309] Lang for oauth users --- .../api/Users/server/send-welcome-email.js | 3 +- imports/modules/get-oauth-profile.js | 37 +++++++++---------- .../startup/server/accounts/lang-fallback.js | 8 ++++ .../startup/server/accounts/on-create-user.js | 13 +++++-- public/locales/en/common.json | 1 + public/locales/es/common.json | 5 ++- 6 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 imports/startup/server/accounts/lang-fallback.js diff --git a/imports/api/Users/server/send-welcome-email.js b/imports/api/Users/server/send-welcome-email.js index 10748dd..f93c7d2 100644 --- a/imports/api/Users/server/send-welcome-email.js +++ b/imports/api/Users/server/send-welcome-email.js @@ -10,11 +10,12 @@ export default (options, user, lang) => { const applicationName = i18n.t('AppName'); const firstName = OAuthProfile ? OAuthProfile.name.first : options.profile.name.first; const emailAddress = OAuthProfile ? OAuthProfile.email : options.email; + const welcome = i18n.t('welcome'); if (emailAddress) { sendEmail({ to: emailAddress, from: `${applicationName} `, - subject: `[${applicationName}] Welcome, ${firstName}!`, + subject: `[${applicationName}] ${welcome} ${firstName}!`, lang, template: 'welcome', templateVars: { diff --git a/imports/modules/get-oauth-profile.js b/imports/modules/get-oauth-profile.js index 91866dc..8e427a1 100644 --- a/imports/modules/get-oauth-profile.js +++ b/imports/modules/get-oauth-profile.js @@ -1,12 +1,11 @@ -const parseGoogleData = service => { - return { - email: service.email, - name: { - first: service.given_name, - last: service.family_name, - }, - }; -}; +const parseGoogleData = service => ({ + email: service.email, + name: { + first: service.given_name, + last: service.family_name + }, + lang: service.locale +}); const parseGithubData = (profile, service) => { const name = profile.name.split(' '); @@ -14,20 +13,18 @@ const parseGithubData = (profile, service) => { email: service.email, name: { first: name[0], - last: name[1], - }, + last: name[1] + } }; }; -const parseFacebookData = service => { - return { - email: service.email, - name: { - first: service.first_name, - last: service.last_name, - }, - }; -}; +const parseFacebookData = service => ({ + email: service.email, + name: { + first: service.first_name, + last: service.last_name + } +}); const getDataForService = (profile, services) => { if (services.facebook) return parseFacebookData(services.facebook); diff --git a/imports/startup/server/accounts/lang-fallback.js b/imports/startup/server/accounts/lang-fallback.js new file mode 100644 index 0000000..af96ce5 --- /dev/null +++ b/imports/startup/server/accounts/lang-fallback.js @@ -0,0 +1,8 @@ +const getFallbackLang = (lang) => { + if (lang && (lang === 'ast' || lang === 'gl' || lang === 'eu' || lang === 'ca' || lang.match(/^es/))) { + return 'es'; + } + return 'en'; +}; + +export default getFallbackLang; diff --git a/imports/startup/server/accounts/on-create-user.js b/imports/startup/server/accounts/on-create-user.js index fa2a99e..383b8c0 100644 --- a/imports/startup/server/accounts/on-create-user.js +++ b/imports/startup/server/accounts/on-create-user.js @@ -1,18 +1,25 @@ import { Accounts } from 'meteor/accounts-base'; import sendWelcomeEmail from '../../../api/Users/server/send-welcome-email'; +import getOAuthProfile from '../../../modules/get-oauth-profile'; +import getFallbackLang from './lang-fallback'; Accounts.onCreateUser((options, user) => { const userToCreate = user; // console.log(JSON.stringify(user)); // console.log(JSON.stringify(options)); + let lang = 'en'; // fallback if (options.profile) { userToCreate.profile = options.profile; userToCreate.lang = options.profile.lang; - lang = options.profile.lang; + // console.log(JSON.stringify(user)); + lang = userToCreate.lang; delete options.profile.lang; - } else { - // TODO others (google, etc) ? + } + const OAuthProfile = getOAuthProfile(options, user); + if (OAuthProfile) { + userToCreate.lang = getFallbackLang(OAuthProfile && OAuthProfile.lang ? OAuthProfile.lang : lang); + lang = userToCreate.lang; } sendWelcomeEmail(options, userToCreate, lang); return userToCreate; diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 6b383de..1f1c564 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -158,6 +158,7 @@ "Más información sobre este fuego": "More information about this fire", "termsAccept": "I accept the <1>conditions of service of this site", "Bienvenid@!": "Welcome!", + "welcome": "Welcome", "Verifica tu dirección de correo": "Verify Your Email Address", "Zonas vigiladas": "Monitored areas", "En verde, las zonas vigiladas por nuestros usuari@s actualmente": "In green, the areas monitored by our users currently", diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 0231e6e..15763d8 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -228,6 +228,7 @@ "Última actualización, {{when}}": "Última actualización, {{when}}", "termsAccept": "Acepto las <1>condiciones de servicio de este sitio", "Bienvenid@!": "Bienvenid@!", + "welcome": "Bienvenid@", "Has iniciado sesión con {{service}} usando la dirección de correo {{email}}.": "Has iniciado sesión con {{service}} usando la dirección de correo {{email}}.", "Verifica tu dirección de correo": "Verifica tu dirección de correo", @@ -269,5 +270,7 @@ "Detectado": "Detectado", "Zonas vigiladas por nuestros usuari@s actualmente": - "Zonas vigiladas por nuestros usuari@s actualmente" + "Zonas vigiladas por nuestros usuari@s actualmente", + "Iniciar sesión con Facebook": + "Iniciar sesión con Facebook" } From a7f9e51b5f0862a907d6d27ed26ca2ccd3ce0659 Mon Sep 17 00:00:00 2001 From: vjrj Date: Mon, 12 Feb 2018 19:56:46 +0100 Subject: [PATCH 002/309] Truncate subs union --- imports/ui/components/Maps/SubsUnion/SubsUnion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imports/ui/components/Maps/SubsUnion/SubsUnion.js b/imports/ui/components/Maps/SubsUnion/SubsUnion.js index e179b33..60cbd26 100644 --- a/imports/ui/components/Maps/SubsUnion/SubsUnion.js +++ b/imports/ui/components/Maps/SubsUnion/SubsUnion.js @@ -20,7 +20,7 @@ function unify(polyList) { if (i === 0) { unionTemp = cleanPol; } else { - unionTemp = tunion(unionTemp, cleanPol); + unionTemp = ttrunc(tunion(unionTemp, cleanPol), truncOptions); } } return unionTemp; From bc4201ffe679fd2ec4d260cc8d417d94503aeeb6 Mon Sep 17 00:00:00 2001 From: vjrj Date: Mon, 12 Feb 2018 20:00:45 +0100 Subject: [PATCH 003/309] Styling in error message on mobile --- imports/ui/components/ErrorBoundary/ErrorBoundary.js | 4 ++-- imports/ui/components/ErrorBoundary/ErrorBoundary.scss | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imports/ui/components/ErrorBoundary/ErrorBoundary.js b/imports/ui/components/ErrorBoundary/ErrorBoundary.js index 542894f..cc1f95b 100644 --- a/imports/ui/components/ErrorBoundary/ErrorBoundary.js +++ b/imports/ui/components/ErrorBoundary/ErrorBoundary.js @@ -35,9 +35,9 @@ class ErrorBoundary extends Component {

{this.t('AppNameFull')}

{this.t('general-error-title')}

- +

{this.t('general-error-description')} - +

diff --git a/imports/ui/components/ErrorBoundary/ErrorBoundary.scss b/imports/ui/components/ErrorBoundary/ErrorBoundary.scss index 9ced77e..225e4ca 100644 --- a/imports/ui/components/ErrorBoundary/ErrorBoundary.scss +++ b/imports/ui/components/ErrorBoundary/ErrorBoundary.scss @@ -2,9 +2,9 @@ background-image: url('/error-background.png'); height: 100%; min-height: 55vh; - margin-top: 40px; + margin: 40px 10px 10px 10px; } .error-boundary > div > div > h4 { - line-height: 1.5em; + line-height: 1.3em; } From 981e8e798e513d6cf07b2a35b14a4c9991446c1e Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 01:44:15 +0100 Subject: [PATCH 004/309] FiresMap store checkbox and improved performance --- imports/ui/pages/FiresMap/FiresMap.js | 80 +++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index ffbf2f2..b75d26b 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -41,6 +41,8 @@ const MAXZOOMREACTIVE = 6; const zoom = new ReactiveVar(8); const center = new ReactiveVar([0, 0]); const mapSize = new ReactiveVar(); +const marks = new ReactiveVar(false); +const showUnion = new ReactiveVar(true); // Remove map in subscription class FiresMap extends React.Component { @@ -51,9 +53,11 @@ class FiresMap extends React.Component { center: props.center, zoom: props.zoom }, - useMarkers: false, + // init: true, + useMarkers: props.marks, scaleAdded: false, - showSubsUnion: true + moving: false, + showSubsUnion: props.showUnion }; const self = this; // viewportchange @@ -62,12 +66,43 @@ class FiresMap extends React.Component { self.handleViewportChange(viewport); }, 1500); this.onViewportChanged = this.onViewportChanged.bind(this); + this.onMoveEnd = this.onMoveEnd.bind(this); + this.onMoveStart = this.onMoveStart.bind(this); } componentDidMount() { } + /* 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) { + const notMoving = !nextState.moving; + return notMoving; + } + + onMoveStart() { + // this.setState({ moving: true }); + this.state.moving = true; + } + + onMoveEnd() { + // this.setState({ moving: false }); + this.state.moving = false; + } + onViewportChanged(viewport) { + this.debounceView.cancel(); this.debounceView(viewport); } @@ -77,6 +112,11 @@ class FiresMap extends React.Component { setShowSubsUnion(showSubsUnion) { this.setState({ showSubsUnion }); + store.set('firesmap_showunion', showSubsUnion); + } + + componentDidUnMount() { + // this.setState({ init: true }); } handleViewportChange(viewport) { @@ -94,7 +134,8 @@ class FiresMap extends React.Component { } zoom.set(viewport.zoom); center.set(viewport.center); - this.setState({ viewport }); + // this.setState({ viewport }); + this.state.viewport = viewport; } } @@ -104,6 +145,7 @@ class FiresMap extends React.Component { useMarkers(use) { this.setState({ useMarkers: use }); + store.set('firesmap_marks', use); } addScale(map) { @@ -116,7 +158,7 @@ class FiresMap extends React.Component { } handleLeafletLoad(map) { - if (map && map.leafletElement) { + if (map && map.leafletElement && !this.state.moving) { const lmap = map.leafletElement; try { const bounds = lmap.getBounds(); @@ -179,7 +221,7 @@ class FiresMap extends React.Component { Resaltar en verde el área vigilada por nuestros usuarios/as (*) {(this.state.viewport.zoom >= MAXZOOM) && - this.useMarkers(e.target.checked)}> + this.useMarkers(e.target.checked)}> Resaltar los fuegos con un marcador } } @@ -201,13 +243,16 @@ class FiresMap extends React.Component { className="firesmap-leaflet-container" animate minZoom={5} - center={this.props.center} - zoom={this.props.zoom} + center={this.state.viewport.center} + zoom={this.state.viewport.zoom} preferCanvas - onClick={this.onClickReset} viewport={this.state.viewport} onViewportChanged={this.onViewportChanged} sleep={isHome() && !isChrome} + onMoveend={this.onMoveEnd} + onMovestart={this.onMoveStart} + onZoomend={this.onMoveEnd} + onZoomstart={this.onMoveStart} sleepTime={10750} wakeTime={750} sleepNote @@ -279,24 +324,33 @@ FiresMap.propTypes = { activefirestotal: PropTypes.number.isRequired, center: PropTypes.arrayOf(PropTypes.number), zoom: PropTypes.number, + marks: PropTypes.bool.isRequired, + showUnion: PropTypes.bool.isRequired, history: PropTypes.object.isRequired, t: PropTypes.func.isRequired }; -let init = true; +let geoInit = true; export default translate([], { wait: true })(withTracker(() => { let subscription; const centerStored = store.get('firesmap_center'); const zoomStored = store.get('firesmap_zoom'); + const marksStored = store.get('firesmap_marks'); + const showUnionStored = store.get('firesmap_showunion'); zoom.set(zoomStored || 8); - + if (typeof marksStored === 'boolean') { + marks.set(marksStored); + } + if (typeof showUnionStored === 'boolean') { + showUnion.set(showUnionStored); + } Meteor.autorun(() => { - if ((centerStored || geolocation.get()) && init) { + if ((centerStored || geolocation.get()) && geoInit) { center.set(centerStored || geolocation.get()); // console.log(`Geolocation ${geolocation.get()}`); - init = false; + geoInit = false; } if (mapSize.get() && mapSize.get()[0].lng && mapSize.get()[1].lat) { subscription = Meteor.subscribe( @@ -342,6 +396,8 @@ export default translate([], { wait: true })(withTracker(() => { falsePositives, lastCheck: lastCheck ? lastCheck.value : null, center: center.get(), + marks: marks.get(), + showUnion: showUnion.get(), zoom: zoom.get() }; })(FiresMap)); From dfed8d3a74f39065b474622efe147676c66f7415 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 09:24:47 +0100 Subject: [PATCH 005/309] Nav reorder --- imports/ui/components/Navigation/Navigation.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imports/ui/components/Navigation/Navigation.js b/imports/ui/components/Navigation/Navigation.js index f252702..e3e3937 100644 --- a/imports/ui/components/Navigation/Navigation.js +++ b/imports/ui/components/Navigation/Navigation.js @@ -47,12 +47,13 @@ const Navigation = props => ( {props.authenticated ? Mis zonas : Participar} - - {props.t('activeFires')} - - {props.t('Zonas vigiladas')} + {props.t('Zonas vigiladas')} + + {props.t('activeFires')} + + {!props.authenticated ? : } {/* */} From add5dedcb149af98caa4146f65c01e0598322a03 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 09:24:56 +0100 Subject: [PATCH 006/309] Migrating users without lang --- imports/startup/server/migrations.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/imports/startup/server/migrations.js b/imports/startup/server/migrations.js index a4482f0..6002d4d 100644 --- a/imports/startup/server/migrations.js +++ b/imports/startup/server/migrations.js @@ -104,8 +104,21 @@ Meteor.startup(() => { } }); + Migrations.add({ + version: 7, + up: function defLangIfNull() { + Meteor.users.find({ lang: null }).forEach((user) => { + Meteor.users.update({ _id: user._id }, { + $set: { + lang: 'es' + } + }); + }); + } + }); + // Set createdAt in users & subs Migrations.migrateTo('latest'); - // Migrations.migrateTo('5,rerun'); + // Migrations.migrateTo('7,rerun'); }); From 9e4815d8b80d466be63785176a667659c5d7ca26 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 09:38:58 +0100 Subject: [PATCH 007/309] Link to tranlator --- imports/ui/pages/Index/Index.js | 2 +- public/locales/en/common.json | 2 +- public/locales/es/common.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imports/ui/pages/Index/Index.js b/imports/ui/pages/Index/Index.js index 4cfa2f4..d353423 100644 --- a/imports/ui/pages/Index/Index.js +++ b/imports/ui/pages/Index/Index.js @@ -289,7 +289,7 @@ class Index extends Component {

Software Libre

-

Todo nuestro trabajo es sofware libre. Traductoræs y desarrolladoræs siempre bienvenid@s.

+

Todo nuestro trabajo es sofware librea>. Traductoræs y desarrolladoræs siempre bienvenid@s.

diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 1f1c564..f27af55 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -105,7 +105,7 @@ "Otros dispositivos": "Other Devices", "support-us-home": "We are developing our tools for other devices. You can <1>help make it possible.", "Software Libre": "Free/Open/Libre Software", - "dev-with-us-home": "All of our work is free/open software. <1>Translators and developers always welcome.", + "dev-with-us-home": "All of our work is <1>free/open software. <3>Translators and <5>developers always welcome.", "Suscríbete a alertas de fuegos": "Subscribe to fire alerts", "Gracias por Participar": "Thanks for participating", "También puedes seguirnos en la web": "You can also follow us on the web", diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 15763d8..38d75b8 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -165,7 +165,6 @@ "Otros dispositivos": "Otros dispositivos", "support-us-home": "Estamos desarrollando nuestras herramientas para otros dispositivos. Puedes <1>contribuir a hacerlo posible.", "Software Libre": "Software Libre", - "dev-with-us-home": "Todo nuestro trabajo es sofware libre. <1>Traductoræs y desarrolladoræs siempre bienvenid@s.", "Suscríbete a alertas de fuegos": "Suscríbete a alertas de fuegos", "Gracias por Participar": "Gracias por Participar", "También puedes seguirnos en la web": "También puedes seguirnos en la web", @@ -174,6 +173,7 @@ "Sí": "Sí", "No": "No", "Sobre los datos y imágenes usados": "Sobre los datos y imágenes usados", + "dev-with-us-home": "Todo nuestro trabajo es <1>sofware libre. <3>Traductoræs y <5>desarrolladoræs siempre bienvenid@s.", "Términos de Servicio": "Términos de Servicio", "Política de Privacidad": "Política de Privacidad", "No estás suscrito a fuegos en ninguna zona": "No estás suscrito a fuegos en ninguna zona", From 26d668b68cbaaeaf94751b79d2e44094507e0e55 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 09:39:23 +0100 Subject: [PATCH 008/309] Send missing in dev --- imports/startup/client/i18n.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imports/startup/client/i18n.js b/imports/startup/client/i18n.js index 42c0ab3..63abf76 100644 --- a/imports/startup/client/i18n.js +++ b/imports/startup/client/i18n.js @@ -53,7 +53,7 @@ i18nOpts.react = { nsMode: 'default' */ }; -const sendMissing = false; // Meteor.isDevelopment; +const sendMissing = true; // Meteor.isDevelopment; if (sendMissing && Meteor.isDevelopment) { i18nOpts.sendMissing = true; i18nOpts.missingKeyHandler = function miss(lng, ns, key, defaultValue) { From 0bb1df35842e06bc746e814e3868e1c8c584cbb4 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 08:49:25 +0000 Subject: [PATCH 009/309] Translated using Weblate (English) Currently translated at 100.0% (187 of 187 strings) --- public/locales/en/common.json | 365 +++++++++++++++++----------------- 1 file changed, 187 insertions(+), 178 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 1f1c564..d9e5177 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -1,180 +1,189 @@ { - "AppName": "All Against Fire", - "AppNameFull": "All Against Fire!", - "AppDescrip": "Crowdsourcing against wildfires", - "AppDescripLong": "We use different sources of data to notify you of active fires in your areas of interest", - "OrgName": "Comunes", - "OrgNameFull": "Comunes Association", - "Términos": "Terms", - "Términos de Servicio": "Terms of Service", - "Privacidad": "Privacy", - "Inicio": "Home", - "Licencia": "License", - "Cerrar sesión": "Logout", - "Registrarse": "Sign Up", - "Regístrate": "Sign Up", - "Iniciar sesión": "Login", - "o regístrate con un correo": "or Sign Up with an Email Address", - "o con un correo": "or with an Email Address", - "Nombre": "First Name", - "Apellidos": "Last Name", - "Correo electrónico": "Email Address", - "Contraseña": "Password", - "¿Ya tienes un cuenta?": "Already have an account?", - "Usa al menos seis caracteres.": "Use at least six characters.", - "Iniciar sesión con Google": "Log In with Google", - "¿Olvidaste tu contraseña?": "Forgot password?", - "¿No tienes una cuenta?": "Don't have an account?", - "Introduce tu correo abajo para recibir un enlace para resetear tu contraseña.": "Enter your email address below to receive a link to reset your password.", - "Recupera tu contraseña": "Recover Password", - "¿Recuerdas tu contraseña?": "Remember your password?", - "Necesitamos un correo aquí.": "Need an email address here.", - "¿Es este correo correcto?": "Is this email address correct?", - "Necesitamos una contraseña aquí.": "Need a password here.", - "Bienvenid@ de nuevo": "Welcome back", - "Guardar perfíl": "Save profile", - "Contraseña actual": "Current Password", - "Nueva contraseña": "New Password", - "Editar perfíl": "Edit Profile", - "Editar perfíl en": "Edit Profile on", - "¡Perfíl actualizado!": "Profile updated!", - "¿Cuál es tu nombre?": "What's your first name?", - "¿Cuál es tu apellido?": "What's your lastName name?", - "Necesito tu contraseña si la quieres cambiar.": "Need your current password if changing.", - "Necesito tu nueva contraseña si la quieres cambiar.": "Need your new password if changing.", - "¿Es correcto este correo?": "Is this email address correct?", - "verifyEmail": "Hey friend! Can you verify your email address ({{email}}) for us?", - "Reenviar email de verificación": "Re-send verification email", - "checkVerificationEmail": "Check {{email}} for a verification link!", - "checkResetEmail": "Check ${email} for a reset link!", - "¡Listo, gracias!": "All set, thanks!", - "Por favor, inténtalo otra vez.": "Please try again.", - "Verificando...": "Verifying...", - "Introduce una nueva contraseña, por favor.": "Enter a new password, please.", - "Repite tu nueva contraseña, por favor.": "Repeat your new password, please.", - "Mmmm, tus contraseñas no coinciden. Inténtalo otra vez": "Hmm, your passwords don't match. Try again", - "Para resetear tu contraseña, introduce una nueva debajo. Iniciarás la sesión con la nueva contraseña.": "To reset your password, enter a new one below. You will be logged in with your new password.", - "Resetea tu contraseña": "Reset your Password", - "Repite la nueva contraseña": "Repeat New Password", - "Resetea la contraseña y entra": "Reset Password & Login", - "Imágenes capturadas por los satélites de la NASA muestran el humo de grandes incendios que se extienden sobre el Océano Pacífico. La actividad del fuego está delineada en rojo.": "Images captured by NASA satellites show the smoke of large fires spreading over the Pacific Ocean. Fire activity is outlined in red.", - "Todavía sin subscriptiones": "No subscriptions yet", - "Suscripción añadida": "Subscription added", - "Suscripción actualizada": "Subscription updated", - "Última actualización, {{when}}": "Last updated, {{when}}", - "Has iniciado sesión con {{service}} usando la dirección de correo {{email}}.": "You're logged in with {{service}} using the email address {{email}}.", - "Uso de Cookies": "Use of Cookies", - "Utilizamos cookies para asegurar un mejor uso de nuestra web. Si continúas navegando, consideramos que aceptas su uso": "We use cookies to ensure a better use of our website. If you continue browsing, we consider that you accept their use", - "Participa": "Get Involved", - "activeFires": "Active Fires", - "Fuegos activos": "Active Fires", - "noActiveFireInMapCount": "There are no active fires in this area of the map. There is a total of <1><0>{{countTotal}} active fires detected worldwide.", - "activeFireInMapCount": "On the map marked in red <1><0>{{count,number}} active fires. There is a total of <3><0>{{countTotal,number}} active fires detected worldwide by NASA.", - "activeNeigFireInMapCount": "In Orange, the fires recently reported by our users.", - "Centrar en tu ubicación": "Center on your location", - "Resaltar en verde el área vigilada por nuestros usuarios/as": "The area monitored by our users is highlighted in green", - "Resaltar los fuegos con un marcador": "Highlight the fires with a marker", - "mapPrivacy": "<0>In order to preserve the privacy of our users, the reflected data are randomly altered and are only indicative.", - "Nuevas notificaciones de {{app}}": "New notifications of {{app}}", - "Mis zonas": "My areas", - "Nueva zona": "New area", - "Subscribirme a fuegos en este rádio": "Subscribe to fires in this radio", - "Créditos": "Credits", - "Escribe aquí un lugar": "Write here a place", - "Indícanos la posición de la zona a vigilar (por ej. tu pueblo, una calle, etc):": "Tell us the position of the area to be monitored (eg your town, a street, etc.):", - "También puedes seleccionar la zona en el mapa arrastrando el puntero naranja.": "You can also select the area on the map by dragging the orange pointer.", - "¿A que distancia a la redonda quieres recibir notificaciones?": "At what distance around you want to receive notifications?", - "Pulsa para activar": "Click to activate", - "Arrastrar para seleccionar otro punto": "Drag to select another point", - "Mapa gris de OpenStreetMap": "Grey map from OpenStreetMap", - "Mapa color de OpenStreetMap": "Color OpenStreetMap", - "Mapa de carreteras de Google": "Google road map", - "Mapa de terreno de Google": "Google terrain map", - "Mapa de satélite de Google": "Google satellite map", - "Zona añadida": "Zone added", - "Añadir zona": "Add zone", - "Editar": "Edit", - "Suscripciones a alertas de fuegos en zonas de mi interés": "Subscriptions to alerts for fires in areas of my interest", - "En verde, áreas de las que recibirás alertas de fuegos": "In green, areas from which you will receive fire alerts", - "Terminar": "Finish", - "Pulsa para borrar": "Click to delete", - "Pulsa aquí para borrar la zona": "Click here to remove the area", - "Los fuegos activos se actualizan en tiempo real.": "Fires are updated in real-time.", - "Somos muchos ojos": "We are many eyes", - "Usa nuestro bot de Telegram para estar al tanto de los fuegos en tus área": "Use our Telegram bot to be aware of the fires in your area", - "Otros dispositivos": "Other Devices", - "support-us-home": "We are developing our tools for other devices. You can <1>help make it possible.", - "Software Libre": "Free/Open/Libre Software", - "dev-with-us-home": "All of our work is free/open software. <1>Translators and developers always welcome.", - "Suscríbete a alertas de fuegos": "Subscribe to fire alerts", - "Gracias por Participar": "Thanks for participating", - "También puedes seguirnos en la web": "You can also follow us on the web", - "Participar": "Participate", - "Dejarás de recibir notificaciones de fuegos en esa área ¿Estás seguro/a? ": "Are you sure you want to stop getting notifications of fires in this area? ", - "Sí": "Yes", - "No": "No", - "Sobre los datos y imágenes usados": "About the data and images used", - "Política de Privacidad": "Privacy Policy", - "No estás suscrito a fuegos en ninguna zona": "You are not subscribed to fires in any area", - "Iniciar sesión con Telegram": "Login with Telegram", - "Idioma": "Language", - "fireDetected": "fire detected {{when}}", - "fireDetectedAt": "fire detected on {{when}}", - "Comentarios": "Comments", - "Guardar": "Save", - "Responder": "Reply", - "Borrar": "Delete", - "Añadir un comentario": "Add a comment", - "Añadir una respuesta": "Add a Reply", - "Añadir comentario": "Add a comment", - "Necesitas iniciar sesión para": "You need to login to", - "añadir comentarios": "add comments", - "puntuar comentarios": "rate it comments", - "responder": "reply", - "Más comentarios": "More Comments", - "Elige un lugar": "Choose a place", - "Elige un radio de vigilancia": "Choose a watch radio", - "Recibe alertas de fuegos en esa zona": "Get alerts of fires in that area", - "Alerta cuando hay un fuego": "Alert when there is a fire", - "Anterior": "Previous", - "Siguiente": "Next", - "Siempre alerta a los fuegos en nuestro vecindario": "Always alert to the fires in our neighborhood", - "Información adicional sobre fuego detectado en {{where}} el {{when}}": "Additional information about fire detected in {{where}} on {{when}}", - "Información adicional sobre fuego detectado el {{when}}": "Additional information about fire detected on {{when}}", - "Coordenadas:": "Coordinates:", - "Fuego detectado por satélites de la NASA <1>": "Fire detected by NASA satellites <1>", - "Puedes añadir un comentario si tienes información adicional sobre este fuego.": "You can add a comment if you have additional information about this fire.", - "Por ejemplo:": "For example:", - "si conoces esta zona y cómo acceder al fuego (esto puede de ser de ayuda para apagarlo si sigue activo o para investigarlo en un futuro)": "If you know the area and how to access the fire (this can be helpful to turn off if still active or to investigate in the future)", - "si conoces el motivo por el que comenzó el fuego": "if you know the reason why the fire started", - "si quieres denunciar algún tipo de ilegalidad, incluso anónimamente": "if you want to denounce some kind of illegality, even anonymously", - "o cualquier otra información": "or any other information", - "Haga zoom en una zona de su interés si quiere que los fuegos se actualicen en tiempo real.": "Zoom into an area of your interest if you want that fires to be updated in real time.", - "Notificaciones": "Notifications", - "Recibe nuestras notificaciones de fuegos por correo o en tu navegador": "Receive our fire notifications by mail or in your browser", - "Fuego notificado por uno de nuestros usuarios/as <1>": "Fire reported by one of our users <1>", - "No recibirás notificaciones de fuegos en este equipo, solo por correo": "You will not receive notifications of fires in this device, only by email", - "not-found": "Oops: This page doesn't exist", - "Más información sobre este fuego": "More information about this fire", - "termsAccept": "I accept the <1>conditions of service of this site", - "Bienvenid@!": "Welcome!", - "welcome": "Welcome", - "Verifica tu dirección de correo": "Verify Your Email Address", - "Zonas vigiladas": "Monitored areas", - "En verde, las zonas vigiladas por nuestros usuari@s actualmente": "In green, the areas monitored by our users currently", - "Datos actualizados <1>.": "Data updated <1>.", - "Información adicional sobre fuego": "Additional information about fire", - "CO2emisions": - "Did you know that wildfires <1>produce as much CO² as cars and <3>about ⅕ of all our carbon emissions?", - "Ayúdanos a combatir el cambio climático y a proteger el medioambiente": "Help us fight climate change and protect the environment", - "Fuego en La Tuna, Los Ángeles, Estados Unidos, septiembre de 2017": - "La Tuna fire, LA, United States, September 2017", - "Polución en la ciudad de Almaty, Kazakhstan, enero de 2014": - "Smog over Almaty city, Kazakhstan, January 2014", - "Fuente": "Source", - "NASA": "NASA", - "nuestros usuarios/as": "our users", - "Pulsa para más información": "Click for more information", - "Detectado": - "Detected" + "AppName": "All Against Fire", + "AppNameFull": "All Against Fire!", + "AppDescrip": "Crowdsourcing against wildfires", + "AppDescripLong": "We use different sources of data to notify you of active fires in your areas of interest", + "OrgName": "Comunes", + "OrgNameFull": "Comunes Association", + "Términos": "Terms", + "Términos de Servicio": "Terms of Service", + "Privacidad": "Privacy", + "Inicio": "Home", + "Licencia": "License", + "Cerrar sesión": "Logout", + "Registrarse": "Sign Up", + "Regístrate": "Sign Up", + "Iniciar sesión": "Login", + "o regístrate con un correo": "or Sign Up with an Email Address", + "o con un correo": "or with an Email Address", + "Nombre": "First Name", + "Apellidos": "Last Name", + "Correo electrónico": "Email Address", + "Contraseña": "Password", + "¿Ya tienes un cuenta?": "Already have an account?", + "Usa al menos seis caracteres.": "Use at least six characters.", + "Iniciar sesión con Google": "Log In with Google", + "¿Olvidaste tu contraseña?": "Forgot password?", + "¿No tienes una cuenta?": "Don't have an account?", + "Introduce tu correo abajo para recibir un enlace para resetear tu contraseña.": "Enter your email address below to receive a link to reset your password.", + "Recupera tu contraseña": "Recover Password", + "¿Recuerdas tu contraseña?": "Remember your password?", + "Necesitamos un correo aquí.": "Need an email address here.", + "¿Es este correo correcto?": "Is this email address correct?", + "Necesitamos una contraseña aquí.": "Need a password here.", + "Bienvenid@ de nuevo": "Welcome back", + "Guardar perfíl": "Save profile", + "Contraseña actual": "Current Password", + "Nueva contraseña": "New Password", + "Editar perfíl": "Edit Profile", + "Editar perfíl en": "Edit Profile on", + "¡Perfíl actualizado!": "Profile updated!", + "¿Cuál es tu nombre?": "What's your first name?", + "¿Cuál es tu apellido?": "What's your lastName name?", + "Necesito tu contraseña si la quieres cambiar.": "Need your current password if changing.", + "Necesito tu nueva contraseña si la quieres cambiar.": "Need your new password if changing.", + "¿Es correcto este correo?": "Is this email address correct?", + "verifyEmail": "Hey friend! Can you verify your email address ({{email}}) for us?", + "Reenviar email de verificación": "Re-send verification email", + "checkVerificationEmail": "Check {{email}} for a verification link!", + "checkResetEmail": "Check ${email} for a reset link!", + "¡Listo, gracias!": "All set, thanks!", + "Por favor, inténtalo otra vez.": "Please try again.", + "Verificando...": "Verifying...", + "Introduce una nueva contraseña, por favor.": "Enter a new password, please.", + "Repite tu nueva contraseña, por favor.": "Repeat your new password, please.", + "Mmmm, tus contraseñas no coinciden. Inténtalo otra vez": "Hmm, your passwords don't match. Try again", + "Para resetear tu contraseña, introduce una nueva debajo. Iniciarás la sesión con la nueva contraseña.": "To reset your password, enter a new one below. You will be logged in with your new password.", + "Resetea tu contraseña": "Reset your Password", + "Repite la nueva contraseña": "Repeat New Password", + "Resetea la contraseña y entra": "Reset Password & Login", + "Imágenes capturadas por los satélites de la NASA muestran el humo de grandes incendios que se extienden sobre el Océano Pacífico. La actividad del fuego está delineada en rojo.": "Images captured by NASA satellites show the smoke of large fires spreading over the Pacific Ocean. Fire activity is outlined in red.", + "Todavía sin subscriptiones": "No subscriptions yet", + "Suscripción añadida": "Subscription added", + "Suscripción actualizada": "Subscription updated", + "Última actualización, {{when}}": "Last updated, {{when}}", + "Has iniciado sesión con {{service}} usando la dirección de correo {{email}}.": "You're logged in with {{service}} using the email address {{email}}.", + "Uso de Cookies": "Use of Cookies", + "Utilizamos cookies para asegurar un mejor uso de nuestra web. Si continúas navegando, consideramos que aceptas su uso": "We use cookies to ensure a better use of our website. If you continue browsing, we consider that you accept their use", + "Participa": "Get Involved", + "activeFires": "Active Fires", + "Fuegos activos": "Active Fires", + "noActiveFireInMapCount": "There are no active fires in this area of the map. There is a total of <1><0>{{countTotal}} active fires detected worldwide.", + "activeFireInMapCount": "On the map marked in red <1><0>{{count,number}} active fires. There is a total of <3><0>{{countTotal,number}} active fires detected worldwide by NASA.", + "activeNeigFireInMapCount": "In Orange, the fires recently reported by our users.", + "Centrar en tu ubicación": "Center on your location", + "Resaltar en verde el área vigilada por nuestros usuarios/as": "The area monitored by our users is highlighted in green", + "Resaltar los fuegos con un marcador": "Highlight the fires with a marker", + "mapPrivacy": "<0>In order to preserve the privacy of our users, the reflected data are randomly altered and are only indicative.", + "Nuevas notificaciones de {{app}}": "New notifications of {{app}}", + "Mis zonas": "My areas", + "Nueva zona": "New area", + "Subscribirme a fuegos en este rádio": "Subscribe to fires in this radio", + "Créditos": "Credits", + "Escribe aquí un lugar": "Write here a place", + "Indícanos la posición de la zona a vigilar (por ej. tu pueblo, una calle, etc):": "Tell us the position of the area to be monitored (eg your town, a street, etc.):", + "También puedes seleccionar la zona en el mapa arrastrando el puntero naranja.": "You can also select the area on the map by dragging the orange pointer.", + "¿A que distancia a la redonda quieres recibir notificaciones?": "At what distance around you want to receive notifications?", + "Pulsa para activar": "Click to activate", + "Arrastrar para seleccionar otro punto": "Drag to select another point", + "Mapa gris de OpenStreetMap": "Grey map from OpenStreetMap", + "Mapa color de OpenStreetMap": "Color OpenStreetMap", + "Mapa de carreteras de Google": "Google road map", + "Mapa de terreno de Google": "Google terrain map", + "Mapa de satélite de Google": "Google satellite map", + "Zona añadida": "Zone added", + "Añadir zona": "Add zone", + "Editar": "Edit", + "Suscripciones a alertas de fuegos en zonas de mi interés": "Subscriptions to alerts for fires in areas of my interest", + "En verde, áreas de las que recibirás alertas de fuegos": "In green, areas from which you will receive fire alerts", + "Terminar": "Finish", + "Pulsa para borrar": "Click to delete", + "Pulsa aquí para borrar la zona": "Click here to remove the area", + "Los fuegos activos se actualizan en tiempo real.": "Fires are updated in real-time.", + "Somos muchos ojos": "We are many eyes", + "Usa nuestro bot de Telegram para estar al tanto de los fuegos en tus área": "Use our Telegram bot to be aware of the fires in your area", + "Otros dispositivos": "Other Devices", + "support-us-home": "We are developing our tools for other devices. You can <1>help make it possible.", + "Software Libre": "Free/Open/Libre Software", + "dev-with-us-home": "All of our work is free/open software. <1>Translators and developers always welcome.", + "Suscríbete a alertas de fuegos": "Subscribe to fire alerts", + "Gracias por Participar": "Thanks for participating", + "También puedes seguirnos en la web": "You can also follow us on the web", + "Participar": "Participate", + "Dejarás de recibir notificaciones de fuegos en esa área ¿Estás seguro/a? ": "Are you sure you want to stop getting notifications of fires in this area? ", + "Sí": "Yes", + "No": "No", + "Sobre los datos y imágenes usados": "About the data and images used", + "Política de Privacidad": "Privacy Policy", + "No estás suscrito a fuegos en ninguna zona": "You are not subscribed to fires in any area", + "Iniciar sesión con Telegram": "Login with Telegram", + "Idioma": "Language", + "fireDetected": "fire detected {{when}}", + "fireDetectedAt": "fire detected on {{when}}", + "Comentarios": "Comments", + "Guardar": "Save", + "Responder": "Reply", + "Borrar": "Delete", + "Añadir un comentario": "Add a comment", + "Añadir una respuesta": "Add a Reply", + "Añadir comentario": "Add a comment", + "Necesitas iniciar sesión para": "You need to login to", + "añadir comentarios": "add comments", + "puntuar comentarios": "rate it comments", + "responder": "reply", + "Más comentarios": "More Comments", + "Elige un lugar": "Choose a place", + "Elige un radio de vigilancia": "Choose a watch radio", + "Recibe alertas de fuegos en esa zona": "Get alerts of fires in that area", + "Alerta cuando hay un fuego": "Alert when there is a fire", + "Anterior": "Previous", + "Siguiente": "Next", + "Siempre alerta a los fuegos en nuestro vecindario": "Always alert to the fires in our neighborhood", + "Información adicional sobre fuego detectado en {{where}} el {{when}}": "Additional information about fire detected in {{where}} on {{when}}", + "Información adicional sobre fuego detectado el {{when}}": "Additional information about fire detected on {{when}}", + "Coordenadas:": "Coordinates:", + "Fuego detectado por satélites de la NASA <1>": "Fire detected by NASA satellites <1>", + "Puedes añadir un comentario si tienes información adicional sobre este fuego.": "You can add a comment if you have additional information about this fire.", + "Por ejemplo:": "For example:", + "si conoces esta zona y cómo acceder al fuego (esto puede de ser de ayuda para apagarlo si sigue activo o para investigarlo en un futuro)": "If you know the area and how to access the fire (this can be helpful to turn off if still active or to investigate in the future)", + "si conoces el motivo por el que comenzó el fuego": "if you know the reason why the fire started", + "si quieres denunciar algún tipo de ilegalidad, incluso anónimamente": "if you want to denounce some kind of illegality, even anonymously", + "o cualquier otra información": "or any other information", + "Haga zoom en una zona de su interés si quiere que los fuegos se actualicen en tiempo real.": "Zoom into an area of your interest if you want that fires to be updated in real time.", + "Notificaciones": "Notifications", + "Recibe nuestras notificaciones de fuegos por correo o en tu navegador": "Receive our fire notifications by mail or in your browser", + "Fuego notificado por uno de nuestros usuarios/as <1>": "Fire reported by one of our users <1>", + "No recibirás notificaciones de fuegos en este equipo, solo por correo": "You will not receive notifications of fires in this device, only by email", + "not-found": "Oops: This page doesn't exist", + "Más información sobre este fuego": "More information about this fire", + "termsAccept": "I accept the <1>conditions of service of this site", + "Bienvenid@!": "Welcome!", + "welcome": "Welcome", + "Verifica tu dirección de correo": "Verify Your Email Address", + "Zonas vigiladas": "Monitored areas", + "En verde, las zonas vigiladas por nuestros usuari@s actualmente": "In green, the areas monitored by our users currently", + "Datos actualizados <1>.": "Data updated <1>.", + "Información adicional sobre fuego": "Additional information about fire", + "CO2emisions": "Did you know that wildfires <1>produce as much CO² as cars and <3>about ⅕ of all our carbon emissions?", + "Ayúdanos a combatir el cambio climático y a proteger el medioambiente": "Help us fight climate change and protect the environment", + "Fuego en La Tuna, Los Ángeles, Estados Unidos, septiembre de 2017": "La Tuna fire, LA, United States, September 2017", + "Polución en la ciudad de Almaty, Kazakhstan, enero de 2014": "Smog over Almaty city, Kazakhstan, January 2014", + "Fuente": "Source", + "NASA": "NASA", + "nuestros usuarios/as": "our users", + "Pulsa para más información": "Click for more information", + "Detectado": "Detected", + "general-error-title": "Upppps: Something has gone wrong", + "general-error-description": "We are investigating the problem, try again in a while", + "Tomamos nota, ¡gracias por colaborar!": "We take note, thanks for collaborating!", + "Indícanos de que tipo de fuego se trata y ayúdanos así a mejorar nuestras notificaciones:": "Tell us what kind of fire it is and help us improve our notifications:", + "¿No es un fuego forestal?": "Isn't that a forest fire?", + "Regístrate o inicia sesión para aportar información sobre este fuego": "Sign up or login to provide information about this fire", + "Fuego no encontrado": "Fire not found", + "Es una industria": "It's an industry", + "Es una quema controlada": "It's a controlled burning", + "Parece una falsa alarma": "It seems a false alarm", + "Fuegos activos en el mundo actualizados en tiempo real": "Active fires in the world updated in real time", + "Zonas vigiladas por nuestros usuari@s actualmente": "Areas currently monitored by our users", + "Iniciar sesión con Facebook": "Login With Facebook" } From 3fc0fca23bf938a33f643a4a8b56074ca56fa848 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 13 Feb 2018 10:43:41 +0100 Subject: [PATCH 010/309] Added untranslated message --- imports/ui/pages/Fires/Fires.js | 2 +- public/locales/en/common.json | 4 +++- public/locales/es/common.json | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/imports/ui/pages/Fires/Fires.js b/imports/ui/pages/Fires/Fires.js index 7b7f425..fe423a5 100644 --- a/imports/ui/pages/Fires/Fires.js +++ b/imports/ui/pages/Fires/Fires.js @@ -125,7 +125,7 @@ class Fire extends React.Component {
{Object.keys(FalsePositiveTypes).map(key => ( diff --git a/public/locales/en/common.json b/public/locales/en/common.json index c46033e..dffcc24 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -185,5 +185,7 @@ "Parece una falsa alarma": "It seems a false alarm", "Fuegos activos en el mundo actualizados en tiempo real": "Active fires in the world updated in real time", "Zonas vigiladas por nuestros usuari@s actualmente": "Areas currently monitored by our users", - "Iniciar sesión con Facebook": "Login With Facebook" + "Iniciar sesión con Facebook": "Login With Facebook", + "Elige un tipo": + "Choose a type" } diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 38d75b8..d4304e7 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -272,5 +272,7 @@ "Zonas vigiladas por nuestros usuari@s actualmente": "Zonas vigiladas por nuestros usuari@s actualmente", "Iniciar sesión con Facebook": - "Iniciar sesión con Facebook" + "Iniciar sesión con Facebook", + "Elige un tipo": + "Elige un tipo" } From b5e9e301b93d0da7f6f4af97c05e0448268f22d7 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 09:57:06 +0100 Subject: [PATCH 011/309] Test docs --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 29a6a62..56a40d5 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,15 @@ More platforms and services in the future... We do tests via: ``` TEST_WATCH=1 MONGO_URL=mongodb://localhost:27017/fuegos meteor --settings settings-development.json test --driver-package meteortesting:mocha --port 3010 + +# and + +chimp --watch --ddp=http://localhost:3000 --path=cucumber + +# and + +chimp --ddp=http://localhost:3000 --path=cucumber + ``` ## Data source acknowledgements From fc4155ea49efc8eac97b9dd7da2fdeefbee8600a Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 09:57:37 +0100 Subject: [PATCH 012/309] Prevent QT error in phantom --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68b572a..3fd1c7b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "tcef", "private": true, "scripts": { - "start": "MONGO_URL=mongodb://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" }, "dependencies": { From 8809a3e3c8351d47b3fa7437322360a2471cf092 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 10:26:22 +0100 Subject: [PATCH 013/309] Some work with spiderable --- cucumber/features/general.feature | 1 - cucumber/features/pages.feature | 2 ++ cucumber/features/steps_definitions/pages.js | 9 ++++++ imports/ui/components/History/History.js | 7 ----- imports/ui/layouts/App/App.js | 32 +++++++++++++++++++- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/cucumber/features/general.feature b/cucumber/features/general.feature index c3ea6a8..3cf078d 100644 --- a/cucumber/features/general.feature +++ b/cucumber/features/general.feature @@ -11,4 +11,3 @@ Feature: This app should generate a correct sitemap, etc | fires | Active Fires | | login | Login | | signup | Signup | - # And should be spiderables diff --git a/cucumber/features/pages.feature b/cucumber/features/pages.feature index 9814434..ed3f4fe 100644 --- a/cucumber/features/pages.feature +++ b/cucumber/features/pages.feature @@ -9,6 +9,7 @@ Feature: Test all secundary pages | activeFires | Active Fires | Then I check that all pages works properly + @watch Scenario: Check that all secondary pages work well Given a list of page urls and contents | login | Login | true | @@ -20,6 +21,7 @@ Feature: Test all secundary pages | fire/inexistent | This page doesn't exist | 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 + # And they are spiderable Scenario: Check that other non visible pages work well Given a list of non visible pages ids and contents diff --git a/cucumber/features/steps_definitions/pages.js b/cucumber/features/steps_definitions/pages.js index 1ce3c8c..5074d52 100644 --- a/cucumber/features/steps_definitions/pages.js +++ b/cucumber/features/steps_definitions/pages.js @@ -71,4 +71,13 @@ module.exports = function () { } callback(); }); + + this.Then(/^they are spiderable$/, (callback) => { + // Write code here that turns the phrase above into concrete actions + for (let i = 0; i < pages.length; i += 1) { + client.url(`${process.env.ROOT_URL}/${pages[i][0]}?_escaped_fragment_=`); + client.waitForText('#react-root', pages[i][1]); + } + callback(); + }); }; diff --git a/imports/ui/components/History/History.js b/imports/ui/components/History/History.js index f72523c..a33464f 100644 --- a/imports/ui/components/History/History.js +++ b/imports/ui/components/History/History.js @@ -1,12 +1,5 @@ -import { Meteor } from 'meteor/meteor'; import createHistory from 'history/createBrowserHistory'; const history = createHistory(); -history.listen((location) => { // , action ) => { - // console.log(location.pathname); - // console.log(action); // PUSH, etc - Meteor.Piwik.trackPage(location.pathname); -}); - export default history; diff --git a/imports/ui/layouts/App/App.js b/imports/ui/layouts/App/App.js index 9a11c69..f4cfc36 100644 --- a/imports/ui/layouts/App/App.js +++ b/imports/ui/layouts/App/App.js @@ -1,7 +1,7 @@ /* eslint-disable jsx-a11y/no-href */ /* eslint import/no-absolute-path: [2, { esmodule: false, commonjs: false, amd: false }] */ -import React from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Router, Switch, Route } from 'react-router-dom'; import { Grid } from 'react-bootstrap'; @@ -54,11 +54,40 @@ import history from '../../components/History/History'; import '../../components/NotificationsObserver/NotificationsObserver'; import './App.scss'; +class LocationListener extends Component { + // https://stackoverflow.com/questions/43512450/react-router-v4-route-onchange-event + static contextTypes = { + router: PropTypes.object + }; + + componentDidMount() { + this.handleLocationChange(this.context.router.history.location); + this.unlisten = + this.context.router.history.listen(this.handleLocationChange); + } + + componentWillUnmount() { + this.unlisten(); + } + + handleLocationChange(location) { + // your staff here + console.log(`----- location: '${location.pathname}'`); + Meteor.Piwik.trackPage(location.pathname); + // Meteor.isReadyForSpiderable = true; + } + + render() { + return this.props.children; + } +} + const App = props => ( /* https://react.i18next.com/components/i18nextprovider.html */ + { !props.loading ?
@@ -112,6 +141,7 @@ const App = props => ( }
: ''} +
From 078931b4f94985eb99a71d7516bbe993e7362578 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 10:31:19 +0100 Subject: [PATCH 014/309] Translation link --- imports/ui/pages/Profile/Profile.js | 1 + public/locales/en/common.json | 4 +++- public/locales/es/common.json | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/imports/ui/pages/Profile/Profile.js b/imports/ui/pages/Profile/Profile.js index 4800200..3f3dbb2 100644 --- a/imports/ui/pages/Profile/Profile.js +++ b/imports/ui/pages/Profile/Profile.js @@ -214,6 +214,7 @@ class Profile extends React.Component { }
+ {this.t('Puedes participar en las traducciones')}
{this.t('Contraseña actual')} diff --git a/public/locales/en/common.json b/public/locales/en/common.json index dffcc24..7c2740b 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -187,5 +187,7 @@ "Zonas vigiladas por nuestros usuari@s actualmente": "Areas currently monitored by our users", "Iniciar sesión con Facebook": "Login With Facebook", "Elige un tipo": - "Choose a type" + "Choose a type", + "Puedes participar en las traducciones": + "You can help with the translations" } diff --git a/public/locales/es/common.json b/public/locales/es/common.json index d4304e7..5d1a46d 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -274,5 +274,7 @@ "Iniciar sesión con Facebook": "Iniciar sesión con Facebook", "Elige un tipo": - "Elige un tipo" + "Elige un tipo", + "Puedes participar en las traducciones": + "Puedes participar en las traducciones" } From 9ebbe5482a62908d001cfe084dc868f1d4ab5e14 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 11:22:11 +0100 Subject: [PATCH 015/309] SiteSettings isPublic --- imports/api/SiteSettings/SiteSettings.js | 1 + imports/api/SiteSettings/server/publications.js | 2 +- imports/startup/server/migrations.js | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/imports/api/SiteSettings/SiteSettings.js b/imports/api/SiteSettings/SiteSettings.js index e690671..2bbd95f 100644 --- a/imports/api/SiteSettings/SiteSettings.js +++ b/imports/api/SiteSettings/SiteSettings.js @@ -40,6 +40,7 @@ SiteSettings.getSchema = type => new SimpleSchema({ type: String, description: String, value: SiteSettingsTypes[type].value, + isPublic: Boolean, createdAt: defaultCreatedAt, updatedAt: defaultUpdateAt }); diff --git a/imports/api/SiteSettings/server/publications.js b/imports/api/SiteSettings/server/publications.js index cd7f33d..ab9f1b2 100644 --- a/imports/api/SiteSettings/server/publications.js +++ b/imports/api/SiteSettings/server/publications.js @@ -3,4 +3,4 @@ import { Meteor } from 'meteor/meteor'; import SiteSettings from '../SiteSettings'; -Meteor.publish('settings', () => SiteSettings.find()); +Meteor.publish('settings', () => SiteSettings.find({ isPublic: true })); diff --git a/imports/startup/server/migrations.js b/imports/startup/server/migrations.js index 6002d4d..e58605f 100644 --- a/imports/startup/server/migrations.js +++ b/imports/startup/server/migrations.js @@ -117,6 +117,16 @@ Meteor.startup(() => { } }); + Migrations.add({ + version: 8, + up: function siteSettingsAddIndex() { + SiteSettings._ensureIndex({ isPublic: 1 }, { unique: 1 }); + SiteSettings.find({ isPublic: null }).forEach((setting) => { + SiteSettings.update({ _id: setting._id }, { $set: { isPublic: true } }); + }); + } + }); + // Set createdAt in users & subs Migrations.migrateTo('latest'); From ed7c89476fd6f63f070bc6fbda9099d36e8b98d1 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 11:26:14 +0100 Subject: [PATCH 016/309] Disable sitesettings methods --- imports/api/SiteSettings/methods.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imports/api/SiteSettings/methods.js b/imports/api/SiteSettings/methods.js index 737bc3a..5f9d73d 100644 --- a/imports/api/SiteSettings/methods.js +++ b/imports/api/SiteSettings/methods.js @@ -1,11 +1,11 @@ import { Meteor } from 'meteor/meteor'; -import { check } from 'meteor/check'; +/* import { check } from 'meteor/check'; import SiteSettings from './SiteSettings'; -import SiteSettingsTypes from './SiteSettingsTypes'; +import SiteSettingsTypes from './SiteSettingsTypes'; */ import rateLimit from '../../modules/rate-limit'; Meteor.methods({ - 'siteSettings.insert': function siteSettingsInsert(setting) { +/* 'siteSettings.insert': function siteSettingsInsert(setting) { check(setting, { name: String, type: String, @@ -46,14 +46,14 @@ Meteor.methods({ } catch (exception) { throw new Meteor.Error('500', exception); } - } + } */ }); rateLimit({ methods: [ - 'siteSettings.insert', + /* 'siteSettings.insert', 'siteSettings.update', - 'siteSettings.remove' + 'siteSettings.remove' */ ], limit: 5, timeRange: 1000 From ac4331edbd8477cebfb728353043f8380fc480c3 Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 14 Feb 2018 18:21:50 +0100 Subject: [PATCH 017/309] Subs union to server side --- .../api/Subscriptions/server/publications.js | 35 ---- imports/startup/server/index.js | 1 + imports/startup/server/migrations.js | 4 +- imports/startup/server/subsUnion.js | 84 ++++++++++ .../ui/components/Maps/SubsUnion/SubsUnion.js | 92 +++------- imports/ui/components/Maps/SubsUnion/Unify.js | 48 ++++++ imports/ui/pages/FiresMap/FiresMap.js | 20 ++- .../pages/Subscriptions/SubscriptionsMap.js | 18 +- package-lock.json | 158 +++++++++++++----- package.json | 1 + 10 files changed, 299 insertions(+), 162 deletions(-) create mode 100644 imports/startup/server/subsUnion.js create mode 100644 imports/ui/components/Maps/SubsUnion/Unify.js diff --git a/imports/api/Subscriptions/server/publications.js b/imports/api/Subscriptions/server/publications.js index f67fc3a..adf6e13 100644 --- a/imports/api/Subscriptions/server/publications.js +++ b/imports/api/Subscriptions/server/publications.js @@ -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' }); diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index aa32e9d..b331b73 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -9,3 +9,4 @@ import './notificationsObserver'; import './facts'; import '../common/comments'; import './sitemaps'; +import './subsUnion'; diff --git a/imports/startup/server/migrations.js b/imports/startup/server/migrations.js index e58605f..f420f82 100644 --- a/imports/startup/server/migrations.js +++ b/imports/startup/server/migrations.js @@ -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 } }); }); diff --git a/imports/startup/server/subsUnion.js b/imports/startup/server/subsUnion.js new file mode 100644 index 0000000..d527f50 --- /dev/null +++ b/imports/startup/server/subsUnion.js @@ -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(); + } + }); +}); diff --git a/imports/ui/components/Maps/SubsUnion/SubsUnion.js b/imports/ui/components/Maps/SubsUnion/SubsUnion.js index 60cbd26..c624759 100644 --- a/imports/ui/components/Maps/SubsUnion/SubsUnion.js +++ b/imports/ui/components/Maps/SubsUnion/SubsUnion.js @@ -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; diff --git a/imports/ui/components/Maps/SubsUnion/Unify.js b/imports/ui/components/Maps/SubsUnion/Unify.js new file mode 100644 index 0000000..68f602a --- /dev/null +++ b/imports/ui/components/Maps/SubsUnion/Unify.js @@ -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; diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index b75d26b..f577e08 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -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, diff --git a/imports/ui/pages/Subscriptions/SubscriptionsMap.js b/imports/ui/pages/Subscriptions/SubscriptionsMap.js index ce675fd..5d162a9 100644 --- a/imports/ui/pages/Subscriptions/SubscriptionsMap.js +++ b/imports/ui/pages/Subscriptions/SubscriptionsMap.js @@ -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 ( { !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)); diff --git a/package-lock.json b/package-lock.json index 5581dfe..174ad76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 3fd1c7b..43ffaf6 100644 --- a/package.json +++ b/package.json @@ -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", From 4f9e0cc63da333600df44e0a089474ab70e8944a Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 15 Feb 2018 12:48:33 +0100 Subject: [PATCH 018/309] Added prerender --- .meteor/packages | 1 + .meteor/versions | 1 + 2 files changed, 2 insertions(+) diff --git a/.meteor/packages b/.meteor/packages index de1e606..823ac22 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -62,3 +62,4 @@ barbatus:stars-rating arkham:comments-ui facts gadicohen:sitemaps +dferber:prerender diff --git a/.meteor/versions b/.meteor/versions index e9ae166..f6a33ef 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -35,6 +35,7 @@ ddp-common@1.3.0 ddp-rate-limiter@1.0.7 ddp-server@2.1.0 deps@1.0.12 +dferber:prerender@2.2.2_3 diff-sequence@1.0.7 dynamic-import@0.2.0 ecmascript@0.9.0 From dbfbba1067dfb03060fe30711ca69b93dd98ea43 Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 15 Feb 2018 13:27:09 +0100 Subject: [PATCH 019/309] Added unstranslated cookie message --- imports/startup/client/i18n.js | 2 +- public/locales/en/common.json | 3 ++- public/locales/es/common.json | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imports/startup/client/i18n.js b/imports/startup/client/i18n.js index 63abf76..69771e2 100644 --- a/imports/startup/client/i18n.js +++ b/imports/startup/client/i18n.js @@ -90,7 +90,7 @@ i18n.use(backend) position: 'bottom', linkText: 'Lee más', linkRouteName: '/privacy', - acceptButtonText: 'Aceptar', + acceptButtonText: t('Aceptar'), html: false, expirationInDays: 70, forceShow: false diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 7c2740b..fd4fcd3 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -189,5 +189,6 @@ "Elige un tipo": "Choose a type", "Puedes participar en las traducciones": - "You can help with the translations" + "You can help with the translations", + "Aceptar": "Accept" } diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 5d1a46d..49ae9e0 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -276,5 +276,6 @@ "Elige un tipo": "Elige un tipo", "Puedes participar en las traducciones": - "Puedes participar en las traducciones" + "Puedes participar en las traducciones", + "Aceptar": "Aceptar" } From 79bdc189347c1559d1d15bd216d9b0ece5f825ee Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 15 Feb 2018 16:53:12 +0100 Subject: [PATCH 020/309] Migrated to prerender node-module --- .meteor/packages | 1 - .meteor/versions | 1 - client/main.html | 1 + imports/startup/server/index.js | 1 + imports/startup/server/prerender.js | 46 ++++++ package-lock.json | 232 +++++++++++++++++++++++++++- package.json | 1 + 7 files changed, 278 insertions(+), 5 deletions(-) create mode 100644 imports/startup/server/prerender.js diff --git a/.meteor/packages b/.meteor/packages index 823ac22..de1e606 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -62,4 +62,3 @@ barbatus:stars-rating arkham:comments-ui facts gadicohen:sitemaps -dferber:prerender diff --git a/.meteor/versions b/.meteor/versions index f6a33ef..e9ae166 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -35,7 +35,6 @@ ddp-common@1.3.0 ddp-rate-limiter@1.0.7 ddp-server@2.1.0 deps@1.0.12 -dferber:prerender@2.2.2_3 diff-sequence@1.0.7 dynamic-import@0.2.0 ecmascript@0.9.0 diff --git a/client/main.html b/client/main.html index 90fe4b1..5f2bc53 100644 --- a/client/main.html +++ b/client/main.html @@ -1,5 +1,6 @@ + All against Fire | Tod@s contra el Fuego diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index b331b73..2a0cebb 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -10,3 +10,4 @@ import './facts'; import '../common/comments'; import './sitemaps'; import './subsUnion'; +import './prerender'; diff --git a/imports/startup/server/prerender.js b/imports/startup/server/prerender.js new file mode 100644 index 0000000..4942165 --- /dev/null +++ b/imports/startup/server/prerender.js @@ -0,0 +1,46 @@ +/* global WebApp */ + +import { Meteor } from 'meteor/meteor'; +import prerenderIO from 'prerender-node'; + +// NOTE: Fetch as Google needs the /?_escaped_fragment_= +// https://webmasters.stackexchange.com/questions/72819/fetch-as-google-doesnt-find-the-html-snapshot-for-my-ajax-content + +// https://forums.meteor.com/t/any-guide-for-prerender-node-and-your-own-server-on-meteor/22054/9 +const settings = Meteor.settings.PrerenderIO; + +// https://github.com/dferber90/meteor-prerender/blob/master/server/prerender.js +const token = process.env.PRERENDERIO_TOKEN || (settings && settings.token); +const protocol = process.env.PRERENDERIO_PROTOCOL || (settings && settings.protocol); +// service url (support `prerenderServiceUrl` (for historical reasons) and `serviceUrl`) +let serviceUrl = settings && (settings.prerenderServiceUrl || settings.serviceUrl); +serviceUrl = process.env.PRERENDERIO_SERVICE_URL || serviceUrl; + +Meteor.startup(() => { + /* TODO if (!__meteor_runtime_config__.ROOT_URL.match(/www|stg|app/)) return; */ + + prerenderIO.set('prerenderToken', token); + + if (serviceUrl) prerenderIO.set('prerenderServiceUrl', serviceUrl); + prerenderIO.set('prerenderToken', token); + if (protocol) prerenderIO.set('protocol', protocol); + + prerenderIO.set('beforeRender', (req, done) => { + if (Meteor.isDevelopment) console.log('\nprerender before', req.headers, '\n\n'); + /* This method is intended to be used for caching, but could be used to save analytics or anything else you need to do for each crawler request. If you return a string from beforeRender, the middleware will serve that to the crawler (with status 200) instead of making a request to the prerender service. If you return an object the middleware will look for a status and body property (defaulting to 200 and "" respectively) and serve those instead. */ + done(); + }); + + prerenderIO.set('afterRender', (err, req, prerender_res) => { + /* This method is intended to be used for caching, but could be used to save analytics or anything else you need to do for each crawler request. This method is a noop and is called after the prerender service returns HTML. */ + if (err) { + console.log('prerenderio error', err); + return; + } + if (Meteor.isDevelopment) console.log('prerender after', req.url, '\nheaders:', req.headers, '\nres complete:', prerender_res.complete, prerender_res.statusCode, prerender_res.statusMessage, '\nres headers:', prerender_res.headers, '\nres body', prerender_res); + }); + + WebApp.rawConnectHandlers.use(prerenderIO); + + console.log('\nprerender service:', settings); +}); diff --git a/package-lock.json b/package-lock.json index 174ad76..7aeb4b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7313,7 +7313,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, "requires": { "jsonify": "0.0.0" } @@ -7337,8 +7336,7 @@ "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, "jsonp": { "version": "0.2.1", @@ -9654,6 +9652,234 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prerender-node": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/prerender-node/-/prerender-node-2.7.4.tgz", + "integrity": "sha1-L7PEHRRHjxemCfWpAM0XvwDjy3E=", + "requires": { + "request": "2.81.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.10.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.17" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + } + } + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", diff --git a/package.json b/package.json index 43ffaf6..32d4fbb 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "node-geocoder": "^3.21.1", "nodemailer": "^4.4.2", "popper.js": "^1.12.7", + "prerender-node": "^2.7.4", "prop-types": "^15.6.0", "push.js": "^1.0.5", "rc-slider": "^8.5.0", From aec4c2a0b02150f3491325a7d84f3fc018ba5de3 Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 15 Feb 2018 17:13:54 +0100 Subject: [PATCH 021/309] Added meta hreflang --- imports/ui/layouts/App/App.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imports/ui/layouts/App/App.js b/imports/ui/layouts/App/App.js index f4cfc36..7e14c91 100644 --- a/imports/ui/layouts/App/App.js +++ b/imports/ui/layouts/App/App.js @@ -94,6 +94,8 @@ const App = props => ( {i18n.t('AppName')} + + From 2477c985d6cf95cdefd086cfabbecd6fe1608b78 Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 15 Feb 2018 18:10:38 +0100 Subject: [PATCH 022/309] Added popup to alerts --- imports/api/Fires/server/publications.js | 19 +++++++++++++++++++ imports/ui/components/Maps/FireList.js | 2 +- imports/ui/components/Maps/FirePixel.js | 18 ++++++++++++++---- imports/ui/components/Maps/FirePopup.js | 2 +- imports/ui/layouts/App/App.js | 2 +- imports/ui/pages/Fires/Fires.js | 7 ++++++- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/imports/api/Fires/server/publications.js b/imports/api/Fires/server/publications.js index 575c7af..0f0b80c 100644 --- a/imports/api/Fires/server/publications.js +++ b/imports/api/Fires/server/publications.js @@ -8,6 +8,7 @@ import { Promise } from 'meteor/promise'; import NodeGeocoder from 'node-geocoder'; import { gmapServerKey } from '/imports/startup/server/IPGeocoder'; import ActiveFiresCollection from '/imports/api/ActiveFires/ActiveFires'; +import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts'; import FiresCollection from '../Fires'; function findFire(unsealed) { @@ -70,6 +71,24 @@ const findOrCreateFire = (obj) => { return findFire(obj); }; +Meteor.publish('fireFromAlertId', function fireFromAlertId(_id) { + try { + check(_id, String); + // console.log(`Looking for alert fire ${_id}`); + const fire = FireAlertsCollection.findOne(new Meteor.Collection.ObjectID(_id)); + if (fire) { + // console.info(`Active fire found: ${_id}`); + return findOrCreateFire(fixConfidence(fire)); + } + console.info(`Alert fire not found: ${_id}`); + // Not found in active fires! + return this.ready(); + } catch (e) { + console.info(`Alert fire not found (with error): ${_id}`); + return this.ready(); + } +}); + Meteor.publish('fireFromActiveId', function fireFromActiveId(_id) { try { check(_id, String); diff --git a/imports/ui/components/Maps/FireList.js b/imports/ui/components/Maps/FireList.js index f4a851c..ecf22f1 100644 --- a/imports/ui/components/Maps/FireList.js +++ b/imports/ui/components/Maps/FireList.js @@ -18,7 +18,7 @@ export default function FireList(props) { if (useMarks) { items = fires.map(({ _id, ...otherProps }) => ()); } else if (usePixel && !falsePositives) { - items = fires.map(({ _id, ...otherProps }) => ()); + items = fires.map(({ _id, ...otherProps }) => ()); } else if (!falsePositives) { items = fires.map(({ _id, ...otherProps }) => ()); } diff --git a/imports/ui/components/Maps/FirePixel.js b/imports/ui/components/Maps/FirePixel.js index 57f2092..c81b547 100644 --- a/imports/ui/components/Maps/FirePixel.js +++ b/imports/ui/components/Maps/FirePixel.js @@ -3,9 +3,13 @@ import React from 'react'; import { CircleMarker } from 'react-leaflet'; import PropTypes from 'prop-types'; +import FirePopup from './FirePopup'; +import { translate } from 'react-i18next'; /* Less acurate (1 pixel per fire) but faster */ -const FirePixel = ({ lat, lon, nasa }) => ( +const FirePixel = ({ + lat, lon, nasa, id, when, t, history +}) => ( ( fillOpacity="1" fill radius={nasa ? 1 : 2} - /> + > + + ); FirePixel.propTypes = { lat: PropTypes.number.isRequired, lon: PropTypes.number.isRequired, - nasa: PropTypes.bool.isRequired + id: PropTypes.object.isRequired, + history: PropTypes.object.isRequired, + when: PropTypes.instanceOf(Date), + nasa: PropTypes.bool.isRequired, + t: PropTypes.func.isRequired }; -export default FirePixel; +export default translate([], { wait: true })(FirePixel); diff --git a/imports/ui/components/Maps/FirePopup.js b/imports/ui/components/Maps/FirePopup.js index 8e7d2a8..c917a6b 100644 --- a/imports/ui/components/Maps/FirePopup.js +++ b/imports/ui/components/Maps/FirePopup.js @@ -22,7 +22,7 @@ const FirePopup = ({ {when && {t('Detectado')}: {moment(when).fromNow()}
} { /* if nasa === null means that the is a false positive fire */ } - history.push(`/fire/${nasa ? 'active' : 'archive'}/${id}`)}>{t('Más información sobre este fuego')} + history.push(`/fire/${nasa ? 'active' : 'alert'}/${id}`)}>{t('Más información sobre este fuego')}
diff --git a/imports/ui/layouts/App/App.js b/imports/ui/layouts/App/App.js index 7e14c91..e80d8cc 100644 --- a/imports/ui/layouts/App/App.js +++ b/imports/ui/layouts/App/App.js @@ -116,7 +116,7 @@ const App = props => ( - + diff --git a/imports/ui/pages/Fires/Fires.js b/imports/ui/pages/Fires/Fires.js index fe423a5..a892181 100644 --- a/imports/ui/pages/Fires/Fires.js +++ b/imports/ui/pages/Fires/Fires.js @@ -35,7 +35,7 @@ class Fire extends React.Component { componentWillReceiveProps(nextProps) { if (this.props.when !== nextProps.when || this.props.loading !== nextProps.loading || this.props.notfound !== nextProps.notfound) { // console.log(`Next when ${nextProps.when}`); - if (nextProps.fire && (nextProps.active || nextProps.fromHash)) { + if (nextProps.fire && (nextProps.alert || nextProps.active || nextProps.fromHash)) { // change url to archive with new _id nextProps.history.replace(`/fire/archive/${nextProps.fire._id}`); } @@ -173,6 +173,7 @@ Fire.propTypes = { notfound: PropTypes.bool.isRequired, fromHash: PropTypes.bool.isRequired, active: PropTypes.bool.isRequired, + alert: PropTypes.bool.isRequired, when: PropTypes.instanceOf(Date), fire: PropTypes.object }; @@ -188,10 +189,13 @@ const FireContainer = withTracker(({ match }) => { let subscription; const active = fireType === 'active'; const archive = fireType === 'archive'; + const alert = fireType === 'alert'; let fromHash = false; if (active) { subscription = Meteor.subscribe('fireFromActiveId', id); + } else if (alert) { + subscription = Meteor.subscribe('fireFromAlertId', id); } else if (archive) { subscription = Meteor.subscribe('fireFromId', id); } else { @@ -209,6 +213,7 @@ const FireContainer = withTracker(({ match }) => { return { loading, active, + alert, fromHash, fire: FiresCollection.findOne(), notfound, From 44428be8aa87c60d1551b96734f9ea1cf8731600 Mon Sep 17 00:00:00 2001 From: vjrj Date: Thu, 15 Feb 2018 22:35:23 +0100 Subject: [PATCH 023/309] Comments config --- imports/startup/client/comments.js | 2 +- imports/startup/common/comments.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/imports/startup/client/comments.js b/imports/startup/client/comments.js index 62fc868..94cbe90 100644 --- a/imports/startup/client/comments.js +++ b/imports/startup/client/comments.js @@ -37,6 +37,6 @@ i18n.init((err, t) => { template: 'bootstrap', // default 'semantic-ui' // default 'http://s3.amazonaws.com/37assets/svn/765-default-avatar.png' defaultAvatar: '/default-avatar.png', - markdown: false + markdown: true }); }); diff --git a/imports/startup/common/comments.js b/imports/startup/common/comments.js index 09fa297..728ec88 100644 --- a/imports/startup/common/comments.js +++ b/imports/startup/common/comments.js @@ -8,6 +8,10 @@ Comments.config({ publishUserFields: { profile: 1 }, + mediaAnalyzers: [ + Comments.analyzers.image, + Comments.analyzers.youtube + ], generateUsername: function genUser(user) { // console.log(JSON.stringify(user)); // FIXME From 45a63548c7837de386271635ce18bb1039c075f8 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 16 Feb 2018 13:12:06 +0100 Subject: [PATCH 024/309] Added raven/sentry to server side --- imports/startup/client/ravenLogger.js | 3 +-- imports/startup/server/index.js | 1 + imports/startup/server/ravenLogger.js | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 imports/startup/server/ravenLogger.js diff --git a/imports/startup/client/ravenLogger.js b/imports/startup/client/ravenLogger.js index 509121a..304b1e8 100644 --- a/imports/startup/client/ravenLogger.js +++ b/imports/startup/client/ravenLogger.js @@ -5,9 +5,8 @@ const ravenOptions = {}; const ravenLogger = new RavenLogger({ publicDSN: Meteor.settings.public.sentryPublicDSN, // will be used on the client - privateDSN: Meteor.settings.sentryPrivateDSN, // will be used on the server shouldCatchConsoleError: true, // default - trackUser: false // default + trackUser: true // default }, ravenOptions); export default ravenLogger; diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index 2a0cebb..6db3588 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -1,3 +1,4 @@ +import './ravenLogger'; import './i18n'; import './accounts'; import './api'; diff --git a/imports/startup/server/ravenLogger.js b/imports/startup/server/ravenLogger.js new file mode 100644 index 0000000..d722dcf --- /dev/null +++ b/imports/startup/server/ravenLogger.js @@ -0,0 +1,13 @@ +import RavenLogger from 'meteor/flowkey:raven'; +import { Meteor } from 'meteor/meteor'; + +const ravenOptions = {}; + +const ravenLogger = new RavenLogger({ + publicDSN: Meteor.settings.public.sentryPublicDSN, + privateDSN: Meteor.settings.sentryPrivateDSN, + shouldCatchConsoleError: true, // default + trackUser: true // default +}, ravenOptions); + +export default ravenLogger; From c35349670ab92f6a497178282aea36290c0dcd78 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 16 Feb 2018 16:45:07 +0100 Subject: [PATCH 025/309] Fix test timming --- cucumber/features/steps_definitions/pages.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cucumber/features/steps_definitions/pages.js b/cucumber/features/steps_definitions/pages.js index 5074d52..e309e15 100644 --- a/cucumber/features/steps_definitions/pages.js +++ b/cucumber/features/steps_definitions/pages.js @@ -43,6 +43,7 @@ module.exports = function () { for (let i = 0; i < pages.length; i += 1) { client.url(`${process.env.ROOT_URL}/${pages[i][0]}`); const content = pages[i][1]; + client.waitForVisible('#react-root', 5000); client.waitForText('#react-root', content); } callback(); From 79eed373d41bdcb8e09edd0014eb456435ca0d04 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 16 Feb 2018 16:46:06 +0100 Subject: [PATCH 026/309] Make subs union no clickable (interactive) and wait for fire alerts --- imports/ui/components/Maps/SubsUnion/SubsUnion.js | 11 +++++++++-- imports/ui/pages/FiresMap/FiresMap.js | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/imports/ui/components/Maps/SubsUnion/SubsUnion.js b/imports/ui/components/Maps/SubsUnion/SubsUnion.js index c624759..ab28b21 100644 --- a/imports/ui/components/Maps/SubsUnion/SubsUnion.js +++ b/imports/ui/components/Maps/SubsUnion/SubsUnion.js @@ -9,6 +9,7 @@ const subsUnion = (union, options) => { const color = options.color || '#145A32'; const fillColor = options.fillColor || 'green'; const opacity = options.options || 0.1; + const interactive = options.interactive || false; if (options.subs) { const lmap = options.map.leafletElement; @@ -18,10 +19,14 @@ const subsUnion = (union, options) => { union = null; if (options.show) { if (options.fromServer) { + // http://leafletjs.com/reference-1.3.0.html#geojson // We get the json from server side union = L.geoJson(JSON.parse(options.subs)); - union.setStyle({ color, fillColor, fillOpacity: opacity }); + union.setStyle({ + color, fillColor, fillOpacity: opacity, interactive + }); union.addTo(lmap); + union.bringToBack(); if (options.fit && options.bounds) { // console.log(options.bounds); const bounds = JSON.parse(options.bounds); @@ -34,7 +39,9 @@ const subsUnion = (union, options) => { const bounds = result[1]; union = L.geoJson(unionJson); - union.setStyle({ color, fillColor, fillOpacity: opacity }); + union.setStyle({ + color, fillColor, fillOpacity: opacity, interactive + }); union.addTo(lmap); if (options.fit) { options.map.leafletElement.fitBounds(bounds); diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index f577e08..3319841 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -336,6 +336,7 @@ let geoInit = true; export default translate([], { wait: true })(withTracker(() => { let subscription; + let alertSubscription; const centerStored = store.get('firesmap_center'); const zoomStored = store.get('firesmap_zoom'); @@ -362,7 +363,7 @@ export default translate([], { wait: true })(withTracker(() => { mapSize.get()[1].lng, mapSize.get()[1].lat ); - Meteor.subscribe( + alertSubscription = Meteor.subscribe( 'fireAlerts', mapSize.get()[0].lng, mapSize.get()[0].lat, @@ -388,7 +389,7 @@ export default translate([], { wait: true })(withTracker(() => { const fireAlerts = FireAlertsCollection.find().fetch(); const falsePositives = FalsePositivesCollection.find().fetch(); return { - loading: !subscription ? true : !(subscription.ready() && settingsSubs.ready()), + loading: !subscription ? true : !(subscription.ready() && settingsSubs.ready() && alertSubscription.ready()), userSubs: userSubs ? userSubs.value : null, userSubsBounds: userSubs ? userSubsBounds.value : null, subsready: settingsSubs.ready(), From ee427758c26d1f1e55db0704fa38ed27edebc966 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 16 Feb 2018 17:07:18 +0100 Subject: [PATCH 027/309] i18n whitelist langs --- imports/startup/common/i18n.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imports/startup/common/i18n.js b/imports/startup/common/i18n.js index e72a81f..9be09fd 100644 --- a/imports/startup/common/i18n.js +++ b/imports/startup/common/i18n.js @@ -35,8 +35,7 @@ const i18nOpts = { return value; } }, - whitelist: false, - // whitelist: ['es', 'en'], // allowed languages + whitelist: ['es', 'en'], // allowed languages load: 'languageOnly', // 'es' o 'en', previously: 'all', // es-ES -> es, en-US -> en debug: shouldDebug, ns: 'common', From eee1abf3edde8afae96ef7de8b29e143d9f17ff0 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 16 Feb 2018 20:40:17 +0100 Subject: [PATCH 028/309] Fix some minor bug in SubsMap --- imports/ui/pages/Subscriptions/SubscriptionsMap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imports/ui/pages/Subscriptions/SubscriptionsMap.js b/imports/ui/pages/Subscriptions/SubscriptionsMap.js index 5d162a9..69f5bdf 100644 --- a/imports/ui/pages/Subscriptions/SubscriptionsMap.js +++ b/imports/ui/pages/Subscriptions/SubscriptionsMap.js @@ -168,7 +168,7 @@ export default translate([], { wait: true })(withTracker(() => { const userSubsBounds = SiteSettings.findOne({ name: 'subs-public-union-bounds' }); return { userSubs: userSubs ? userSubs.value : null, - userSubsBounds: userSubs ? userSubsBounds.value : null, + userSubsBounds: userSubsBounds ? userSubsBounds.value : null, subsready: settingsSubs.ready() }; })(SubscriptionsMap)); From 2a6d8bea7841fb5551196110c4e0dd611fe42ca0 Mon Sep 17 00:00:00 2001 From: vjrj Date: Fri, 16 Feb 2018 20:40:41 +0100 Subject: [PATCH 029/309] False positives only for active fires --- .../api/ActiveFires/server/publications.js | 34 ++++++++++++++++++- imports/ui/components/Maps/SubsUnion/Unify.js | 2 +- imports/ui/pages/FiresMap/FiresMap.js | 23 ++++++------- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/imports/api/ActiveFires/server/publications.js b/imports/api/ActiveFires/server/publications.js index 278d937..d4b389a 100644 --- a/imports/api/ActiveFires/server/publications.js +++ b/imports/api/ActiveFires/server/publications.js @@ -4,7 +4,10 @@ import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; +import L from 'leaflet-headless'; import { NumberBetween } from '/imports/modules/server/other-checks'; +import FalsePositives from '/imports/api/FalsePositives/FalsePositives'; +import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify'; import ActiveFires from '../ActiveFires'; const counter = new Counter('countActiveFires', ActiveFires.find({})); @@ -13,6 +16,27 @@ Meteor.publish('activefirestotal', function total() { return counter; }); +const falsePositives = (fires) => { + const falsePos = FalsePositives.find({ + geo: { + $geoWithin: { + $geometry: fires.geometry + } + } + }, { + fields: { + geo: 1, + // type: 1, + // when: 1, + fireId: 1 + } + }); + + /* console.log(`False positive total: ${falsePos.count()}`); + * console.log(`False positives: ${JSON.stringify(falsePos.fetch())}`); */ + return falsePos; +}; + const activefires = (northEastLng, northEastLat, southWestLng, southWestLat) => { const fires = ActiveFires.find({ ourid: { @@ -31,8 +55,16 @@ const activefires = (northEastLng, northEastLat, southWestLng, southWestLat) => scan: 1 } }); + + const group = new L.FeatureGroup(); + const remap = fires.fetch().map(function remap(doc) { + return { location: { lat: doc.lat, lon: doc.lon }, distance: doc.scan }; + }); + const result = calcUnion(remap, group, sub => sub); + const falsePos = falsePositives(result[0]); + // console.log(JSON.stringify(result)); // console.log(`Fires total: ${fires.count()}`); - return fires; + return [fires, falsePos]; }; Meteor.publish('activefiresmyloc', function activeInMyLoc(northEastLng, northEastLat, southWestLng, southWestLat) { diff --git a/imports/ui/components/Maps/SubsUnion/Unify.js b/imports/ui/components/Maps/SubsUnion/Unify.js index 68f602a..46586b7 100644 --- a/imports/ui/components/Maps/SubsUnion/Unify.js +++ b/imports/ui/components/Maps/SubsUnion/Unify.js @@ -35,7 +35,7 @@ const calcUnion = (subs, group, decorated) => { 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)}`); + console.info(`Wrong subscription ${JSON.stringify(osub)}`); } } catch (e) { console.error(e, `Wrong subscription trying to make union ${JSON.stringify(osub)}`); diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index 3319841..8520068 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -185,7 +185,7 @@ class FiresMap extends React.Component { 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}`); + console.log(`False positives total: ${this.props.falsePositives.length}`); } return ( /* Large number of markers: @@ -321,7 +321,6 @@ FiresMap.propTypes = { activefires: PropTypes.arrayOf(PropTypes.object).isRequired, firealerts: PropTypes.arrayOf(PropTypes.object).isRequired, falsePositives: PropTypes.arrayOf(PropTypes.object).isRequired, - falsePositivesTotal: PropTypes.number.isRequired, lastCheck: PropTypes.instanceOf(Date), activefirestotal: PropTypes.number.isRequired, center: PropTypes.arrayOf(PropTypes.number), @@ -370,24 +369,25 @@ export default translate([], { wait: true })(withTracker(() => { mapSize.get()[1].lng, mapSize.get()[1].lat ); - Meteor.subscribe( - 'falsePositivesMyloc', - mapSize.get()[0].lng, - mapSize.get()[0].lat, - mapSize.get()[1].lng, - mapSize.get()[1].lat - ); } }); Meteor.subscribe('activefirestotal'); - Meteor.subscribe('falsePositivesTotal'); 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(); + const falsePositives = FalsePositivesCollection.find().fetch().map((odoc) => { + const doc = odoc; + const geo = doc.geo; + doc.lat = geo.coordinates[1]; + doc.lon = geo.coordinates[0]; + doc._id = doc.fireId; + doc.id = doc.fireId; + delete doc.geo; + return doc; + }); return { loading: !subscription ? true : !(subscription.ready() && settingsSubs.ready() && alertSubscription.ready()), userSubs: userSubs ? userSubs.value : null, @@ -396,7 +396,6 @@ export default translate([], { wait: true })(withTracker(() => { // Not reactive query depending on zoom level activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(), activefirestotal: Counter.get('countActiveFires') + fireAlerts.length, - falsePositivesTotal: Counter.get('countFalsePositives') + fireAlerts.length, firealerts: fireAlerts, falsePositives, lastCheck: lastCheck ? lastCheck.value : null, From 824f66df038f1427f06b8bf519401e96b61df63d Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 17 Feb 2018 08:26:46 +0100 Subject: [PATCH 030/309] import L --- imports/ui/components/Maps/SubsUnion/SubsUnion.js | 2 +- imports/ui/pages/FiresMap/FiresMap.js | 3 ++- imports/ui/pages/Subscriptions/SubscriptionsMap.js | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imports/ui/components/Maps/SubsUnion/SubsUnion.js b/imports/ui/components/Maps/SubsUnion/SubsUnion.js index ab28b21..dab127a 100644 --- a/imports/ui/components/Maps/SubsUnion/SubsUnion.js +++ b/imports/ui/components/Maps/SubsUnion/SubsUnion.js @@ -1,8 +1,8 @@ /* eslint-disable react/jsx-indent-props */ /* eslint-disable import/no-absolute-path */ /* eslint-disable import/no-absolute-path */ -/* global L */ +import L from 'leaflet'; import calcUnion from '/imports/ui/components/Maps/SubsUnion/Unify'; const subsUnion = (union, options) => { diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index 8520068..caf011e 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -1,4 +1,4 @@ -/* global L Counter */ +/* global Counter */ /* eslint-disable import/no-absolute-path */ /* eslint-disable react/jsx-indent-props */ /* eslint-disable react/jsx-indent */ @@ -14,6 +14,7 @@ import { Map } from 'react-leaflet'; import Control from 'react-leaflet-control'; import _ from 'lodash'; import store from 'store'; +import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.css'; import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.js'; diff --git a/imports/ui/pages/Subscriptions/SubscriptionsMap.js b/imports/ui/pages/Subscriptions/SubscriptionsMap.js index 69f5bdf..60bb37f 100644 --- a/imports/ui/pages/Subscriptions/SubscriptionsMap.js +++ b/imports/ui/pages/Subscriptions/SubscriptionsMap.js @@ -1,7 +1,7 @@ -/* global L */ /* eslint-disable import/no-absolute-path */ /* eslint-disable react/jsx-indent-props */ /* eslint-disable react/jsx-indent */ + import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import { Button, ButtonGroup, Row, Col } from 'react-bootstrap'; @@ -10,6 +10,7 @@ import { withTracker } from 'meteor/react-meteor-data'; import { Trans, translate } from 'react-i18next'; import { Map } from 'react-leaflet'; import { Helmet } from 'react-helmet'; +import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.css'; import 'leaflet-graphicscale/dist/Leaflet.GraphicScale.min.js'; From 237269f76123c6fd9216b43e94376f478c31f311 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 17 Feb 2018 08:43:01 +0100 Subject: [PATCH 031/309] Fix some FireMaps data retrieving --- .../api/ActiveFires/server/publications.js | 30 +++++++++++-------- imports/ui/pages/FiresMap/FiresMap.js | 6 ++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/imports/api/ActiveFires/server/publications.js b/imports/api/ActiveFires/server/publications.js index d4b389a..b0b2329 100644 --- a/imports/api/ActiveFires/server/publications.js +++ b/imports/api/ActiveFires/server/publications.js @@ -32,12 +32,12 @@ const falsePositives = (fires) => { } }); - /* console.log(`False positive total: ${falsePos.count()}`); - * console.log(`False positives: ${JSON.stringify(falsePos.fetch())}`); */ + /* console.log(`False positive total: ${falsePos.count()}`); + console.log(`False positives: ${JSON.stringify(falsePos.fetch())}`); */ return falsePos; }; -const activefires = (northEastLng, northEastLat, southWestLng, southWestLat) => { +const activefires = (northEastLng, northEastLat, southWestLng, southWestLat, withMarks) => { const fires = ActiveFires.find({ ourid: { $geoWithin: { @@ -56,23 +56,29 @@ const activefires = (northEastLng, northEastLat, southWestLng, southWestLat) => } }); - const group = new L.FeatureGroup(); - const remap = fires.fetch().map(function remap(doc) { - return { location: { lat: doc.lat, lon: doc.lon }, distance: doc.scan }; - }); - const result = calcUnion(remap, group, sub => sub); - const falsePos = falsePositives(result[0]); // console.log(JSON.stringify(result)); // console.log(`Fires total: ${fires.count()}`); - return [fires, falsePos]; + + if (withMarks && fires.fetch().length > 0) { + const group = new L.FeatureGroup(); + const remap = fires.fetch().map(function remap(doc) { + return { location: { lat: doc.lat, lon: doc.lon }, distance: doc.scan }; + }); + const result = calcUnion(remap, group, sub => sub); + const falsePos = falsePositives(result[0]); + return [fires, falsePos]; + } + + return fires; }; -Meteor.publish('activefiresmyloc', function activeInMyLoc(northEastLng, northEastLat, southWestLng, southWestLat) { +Meteor.publish('activefiresmyloc', 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); - return activefires(northEastLng, northEastLat, southWestLng, southWestLat); + return activefires(northEastLng, northEastLat, southWestLng, southWestLat, withMarks); }); diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index caf011e..c1b3b7b 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -146,6 +146,7 @@ class FiresMap extends React.Component { useMarkers(use) { this.setState({ useMarkers: use }); store.set('firesmap_marks', use); + marks.set(use); } addScale(map) { @@ -183,7 +184,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}. Reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`); + console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'}, zoom ${this.state.viewport.zoom}, 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.falsePositives.length}`); @@ -361,7 +362,8 @@ export default translate([], { wait: true })(withTracker(() => { mapSize.get()[0].lng, mapSize.get()[0].lat, mapSize.get()[1].lng, - mapSize.get()[1].lat + mapSize.get()[1].lat, + marks.get() && zoom.get() >= MAXZOOM ); alertSubscription = Meteor.subscribe( 'fireAlerts', From 53ab69555edfd13ddb653ecbf6e7b1c21ab8d9b4 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 17 Feb 2018 08:48:04 +0100 Subject: [PATCH 032/309] Don't query again if zoom in --- imports/ui/pages/FiresMap/FiresMap.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index c1b3b7b..7076c60 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -127,9 +127,8 @@ class FiresMap extends React.Component { mapSize.set([bounds.getNorthEast(), bounds.getSouthWest()]); store.set('firesmap_center', viewport.center); store.set('firesmap_zoom', viewport.zoom); - if (viewport.center === this.state.viewport.center && - viewport.zoom === this.state.viewport.zoom) { - // Do nothing, in same point + if (viewport.zoom >= this.state.viewport.zoom) { + if (Meteor.isDevelopment) console.log('Don\'t query we are in the same point'); return; } zoom.set(viewport.zoom); From f5d105fbc0543205dc2d7885a199e45002d3b5e1 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 17 Feb 2018 08:52:50 +0100 Subject: [PATCH 033/309] Remove log --- imports/startup/server/prerender.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imports/startup/server/prerender.js b/imports/startup/server/prerender.js index 4942165..dedee0b 100644 --- a/imports/startup/server/prerender.js +++ b/imports/startup/server/prerender.js @@ -42,5 +42,5 @@ Meteor.startup(() => { WebApp.rawConnectHandlers.use(prerenderIO); - console.log('\nprerender service:', settings); + // console.log('\nprerender service:', settings); }); From 79222eb97833eab833b6810890ba5ad86d118553 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 17 Feb 2018 09:30:44 +0100 Subject: [PATCH 034/309] Removed loading in FireMap. Improve data retrieving --- imports/ui/pages/FiresMap/FiresMap.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index 7076c60..afd5dcd 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -25,7 +25,6 @@ import FireList from '/imports/ui/components/Maps/FireList'; import subsUnion from '/imports/ui/components/Maps/SubsUnion/SubsUnion'; import DefMapLayers from '/imports/ui/components/Maps/DefMapLayers'; import FromNow from '/imports/ui/components/FromNow/FromNow'; -import Loading from '/imports/ui/components/Loading/Loading'; import ActiveFiresCollection from '/imports/api/ActiveFires/ActiveFires'; import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts'; import FalsePositivesCollection from '/imports/api/FalsePositives/FalsePositives'; @@ -127,13 +126,13 @@ class FiresMap extends React.Component { mapSize.set([bounds.getNorthEast(), bounds.getSouthWest()]); store.set('firesmap_center', viewport.center); store.set('firesmap_zoom', viewport.zoom); - if (viewport.zoom >= this.state.viewport.zoom) { + if (viewport.zoom > this.state.viewport.zoom) { + this.state.viewport = viewport; if (Meteor.isDevelopment) console.log('Don\'t query we are in the same point'); return; } zoom.set(viewport.zoom); center.set(viewport.center); - // this.setState({ viewport }); this.state.viewport = viewport; } } @@ -185,6 +184,7 @@ class FiresMap extends React.Component { const { t } = this.props; console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'}, zoom ${this.state.viewport.zoom}, 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.falsePositives.length}`); } @@ -199,11 +199,6 @@ class FiresMap extends React.Component { {title} } - {this.props.loading || !this.props.subsready ? - - - - : ''}

Fuegos activos

From 308ad08e742e209773c6c432f2a356912449e20e Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 17 Feb 2018 09:41:21 +0100 Subject: [PATCH 035/309] Tooltip in industries --- imports/ui/components/Maps/FireIconMark.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imports/ui/components/Maps/FireIconMark.js b/imports/ui/components/Maps/FireIconMark.js index 5082edf..5e8af68 100644 --- a/imports/ui/components/Maps/FireIconMark.js +++ b/imports/ui/components/Maps/FireIconMark.js @@ -1,6 +1,6 @@ /* eslint-disable import/no-absolute-path */ -import React from 'react'; -import { CircleMarker, Marker } from 'react-leaflet'; +import React, { Fragment } from 'react'; +import { CircleMarker, Marker, Tooltip } from 'react-leaflet'; import PropTypes from 'prop-types'; import { fireIcon, nFireIcon, industryIcon } from '/imports/ui/components/Maps/Icons'; import { translate } from 'react-i18next'; @@ -23,6 +23,7 @@ const FireIconMark = ({ } { falsePositives && + {t('Es una industria')} { /* disabled because was a past fire (and can be marked multiple times) */ false && } } From 5c7380a1996b0071e3294c161317b5f0598f9f63 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sun, 18 Feb 2018 13:11:40 +0100 Subject: [PATCH 036/309] Fix error message --- imports/ui/pages/Profile/Profile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imports/ui/pages/Profile/Profile.js b/imports/ui/pages/Profile/Profile.js index 3f3dbb2..cb58761 100644 --- a/imports/ui/pages/Profile/Profile.js +++ b/imports/ui/pages/Profile/Profile.js @@ -25,6 +25,7 @@ class Profile extends React.Component { this.t = this.props.t; this.getUserType = this.getUserType.bind(this); this.handleSubmit = this.handleSubmit.bind(this); + this.renderOAuthUser = this.renderOAuthUser.bind(this); this.renderPasswordUser = this.renderPasswordUser.bind(this); this.renderProfileForm = this.renderProfileForm.bind(this); @@ -67,7 +68,7 @@ class Profile extends React.Component { required: this.t('¿Cuál es tu apellido?') }, emailAddress: { - required: this.t('Necesitamos una contraseña aquí.'), + required: this.t('Necesitamos un correo aquí.'), email: this.t('¿Es correcto este correo?') }, currentPassword: { From ba32c4fd0dd89ba7a8e51647ee563fe9852eb771 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sun, 18 Feb 2018 17:00:54 +0100 Subject: [PATCH 037/309] Feedback button --- imports/startup/server/feedback.js | 25 ++++ imports/startup/server/index.js | 1 + imports/ui/components/Feedback/Feedback.js | 120 +++++++++++++++++++ imports/ui/components/Feedback/Feedback.scss | 71 +++++++++++ imports/ui/layouts/App/App.js | 4 +- public/locales/en/common.json | 10 +- public/locales/es/common.json | 10 +- 7 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 imports/startup/server/feedback.js create mode 100644 imports/ui/components/Feedback/Feedback.js create mode 100644 imports/ui/components/Feedback/Feedback.scss diff --git a/imports/startup/server/feedback.js b/imports/startup/server/feedback.js new file mode 100644 index 0000000..98ebaca --- /dev/null +++ b/imports/startup/server/feedback.js @@ -0,0 +1,25 @@ +/* eslint-disable prefer-arrow-callback */ +/* eslint-disable import/no-absolute-path */ + +import { Meteor } from 'meteor/meteor'; +import i18n from 'i18next'; +import { check } from 'meteor/check'; +import sendEmail from '/imports/startup/server/email'; + +Meteor.methods({ + 'send-feedback': function sendFeedback(email, feedback) { + check(email, String); + check(feedback, String); + const appName = i18n.t('AppName'); + sendEmail({ + to: 'info@comunes.org', + from: `${appName} `, + subject: `Feedback de ${email}!`, + sendAt: new Date(), + text: `Feedback de ${email}\n\n${feedback}`, + html: `

${feedback}

`, + template: '{{appName}}

{{{subject}}}

{{{html}}}', + appName + }, true); + } +}); diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index 6db3588..101d249 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -12,3 +12,4 @@ import '../common/comments'; import './sitemaps'; import './subsUnion'; import './prerender'; +import './feedback'; diff --git a/imports/ui/components/Feedback/Feedback.js b/imports/ui/components/Feedback/Feedback.js new file mode 100644 index 0000000..af2f845 --- /dev/null +++ b/imports/ui/components/Feedback/Feedback.js @@ -0,0 +1,120 @@ +/* eslint-disable react/jsx-indent-props */ +/* eslint-disable import/no-absolute-path */ +/* eslint-disable import/no-absolute-path */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Meteor } from 'meteor/meteor'; +import { translate } from 'react-i18next'; +import { FormGroup, Button, FormControl } from 'react-bootstrap'; +import { Bert } from 'meteor/themeteorchef:bert'; +import validate from '../../../modules/validate'; + +import './Feedback.scss'; + +class Feedback extends Component { + constructor(props) { + super(props); + this.t = props.t; + this.handleSubmit = this.handleSubmit.bind(this); + this.onTabClick = this.onTabClick.bind(this); + } + + componentDidMount() { + const component = this; + + validate(component.form, { + rules: { + email: { + required: true, + email: true + }, + feedbackText: { + required: true + } + }, + messages: { + feedbackText: { + required: this.t('Por favor, escribe aquí tu feedback...') + }, + email: { + required: this.t('Tu correo'), + email: this.t('¿Es correcto este correo?') + } + }, + submitHandler() { component.handleSubmit(); } + }); + } + + onTabClick() { + $('#feedback-form').toggle('slide'); + } + + handleSubmit() { + const email = this.email.value.trim(); + const feedbackText = this.feedbackText.value.trim(); + + Meteor.call('send-feedback', email, feedbackText, (error) => { + if (error) { + Bert.alert(error.reason, 'danger'); + } else { + this.form.reset(); + Bert.alert('Feedback recibido, gracias...', 'success'); + this.onTabClick(); + } + }); + } + + render() { + return ( +
+
(this.formdiv = formdiv)} style={{ display: 'none' }} className="card"> +
(this.form = form)} + className="form card-body" + onSubmit={event => event.preventDefault()} + > + + (this.email = email)} + placeholder={this.t('Tu correo')} + type="email" + /> + + +