More work with titles & descriptions
This commit is contained in:
parent
a1138c8c43
commit
464af6b9d1
21 changed files with 178 additions and 51 deletions
|
|
@ -10,6 +10,16 @@ Feature: Test all secundary pages
|
||||||
| activeFires | Active Fires |
|
| activeFires | Active Fires |
|
||||||
Then I check that all pages works properly
|
Then I check that all pages works properly
|
||||||
|
|
||||||
|
Scenario: Check that all secondary pages work well
|
||||||
|
Given a list of page urls and contents
|
||||||
|
| login | Login | true |
|
||||||
|
| signup | Sign Up | true |
|
||||||
|
| recover-password | Recover Password | true |
|
||||||
|
| verify-email/something | Verify | true |
|
||||||
|
| 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
|
||||||
|
|
||||||
Scenario: Check that other non visible pages work well
|
Scenario: Check that other non visible pages work well
|
||||||
Given a list of non visible pages ids and contents
|
Given a list of non visible pages ids and contents
|
||||||
| status | Status |
|
| status | Status |
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ module.exports = function doSteps(notos) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function closeAlert() {
|
function closeAlert() {
|
||||||
client.waitForVisible('.bert-alert', 5000);
|
// client.waitForVisible('.bert-alert', 5000);
|
||||||
client.click('.bert-content');
|
// client.click('.bert-content');
|
||||||
client.waitUntil(() => client.isVisible('.bert-alert') === false, 10000);
|
client.waitUntil(() => client.isVisible('.bert-alert') === false, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,21 @@ module.exports = function () {
|
||||||
client.waitForVisible(id, 10000);
|
client.waitForVisible(id, 10000);
|
||||||
client.click(id);
|
client.click(id);
|
||||||
client.waitForText('#react-root', content);
|
client.waitForText('#react-root', content);
|
||||||
|
// https://jasmine.github.io/2.3/introduction.html#section-Expectations
|
||||||
|
expect(client.getTitle()).toContain(pages[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function processPageUrl(i) {
|
||||||
|
const url = `${pages[i][0]}`;
|
||||||
|
const content = pages[i][1];
|
||||||
|
client.url(`${process.env.ROOT_URL}/${url}`);
|
||||||
|
client.waitForVisible('#react-root', 10000);
|
||||||
|
client.waitForText('#react-root', content);
|
||||||
|
const checkTitle = pages[i][2] === 'true';
|
||||||
|
// https://jasmine.github.io/2.3/introduction.html#section-Expectations
|
||||||
|
if (checkTitle) {
|
||||||
|
expect(client.getTitle()).toContain(pages[i][1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Given(/^a list of non visible pages ids and contents$/, (table, callback) => {
|
this.Given(/^a list of non visible pages ids and contents$/, (table, callback) => {
|
||||||
|
|
@ -35,9 +50,25 @@ module.exports = function () {
|
||||||
|
|
||||||
this.Then(/^I check that all pages works properly$/, (callback) => {
|
this.Then(/^I check that all pages works properly$/, (callback) => {
|
||||||
goHome(client);
|
goHome(client);
|
||||||
|
if (client.isVisible('#logout')) {
|
||||||
|
client.click('#logout');
|
||||||
|
}
|
||||||
for (let i = 0; i < pages.length; i += 1) {
|
for (let i = 0; i < pages.length; i += 1) {
|
||||||
processPage(i);
|
processPage(i);
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.Given(/^a list of page urls and contents$/, (table, callback) => {
|
||||||
|
pages = table.raw();
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.Then(/^I check that all page urls works properly$/, (callback) => {
|
||||||
|
goHome(client);
|
||||||
|
for (let i = 0; i < pages.length; i += 1) {
|
||||||
|
processPageUrl(i);
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,29 @@ const options = {
|
||||||
|
|
||||||
const geocoder = NodeGeocoder(options);
|
const geocoder = NodeGeocoder(options);
|
||||||
|
|
||||||
|
const unseal = async (obj) => {
|
||||||
|
try {
|
||||||
|
const unsealed = await urlEnc.decrypt(obj);
|
||||||
|
return unsealed;
|
||||||
|
} catch (error) {
|
||||||
|
// console.warn(error);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsealW = obj => unseal(obj);
|
||||||
|
|
||||||
Meteor.publish('fireFromHash', function fireFromHash(fireEnc) {
|
Meteor.publish('fireFromHash', function fireFromHash(fireEnc) {
|
||||||
check(fireEnc, String);
|
check(fireEnc, String);
|
||||||
try {
|
try {
|
||||||
// console.log(fireEnc);
|
// console.log(fireEnc);
|
||||||
const unsealed = Promise.await(urlEnc.decrypt(fireEnc));
|
// const unsealed = Promise.await(urlEnc.decrypt(fireEnc));
|
||||||
|
const unsealed = Promise.await(unsealW(fireEnc));
|
||||||
|
if (unsealed === undefined) {
|
||||||
|
console.info(`Wrong fire: ${fireEnc}`);
|
||||||
|
// https://guide.meteor.com/data-loading.html
|
||||||
|
return this.ready();
|
||||||
|
}
|
||||||
const w = unsealed.when;
|
const w = unsealed.when;
|
||||||
unsealed.when = new Date(w);
|
unsealed.when = new Date(w);
|
||||||
const c = unsealed.createdAt;
|
const c = unsealed.createdAt;
|
||||||
|
|
@ -36,7 +54,6 @@ Meteor.publish('fireFromHash', function fireFromHash(fireEnc) {
|
||||||
const u = unsealed.updatedAt;
|
const u = unsealed.updatedAt;
|
||||||
unsealed.updatedAt = !u ? new Date() : new Date(u);
|
unsealed.updatedAt = !u ? new Date() : new Date(u);
|
||||||
// console.log(unsealed);
|
// console.log(unsealed);
|
||||||
|
|
||||||
// FIXME:
|
// FIXME:
|
||||||
if (typeof unsealed.confidence === 'string') {
|
if (typeof unsealed.confidence === 'string') {
|
||||||
unsealed.confidence = Number.parseInt(unsealed.confidence, 10);
|
unsealed.confidence = Number.parseInt(unsealed.confidence, 10);
|
||||||
|
|
@ -55,7 +72,7 @@ Meteor.publish('fireFromHash', function fireFromHash(fireEnc) {
|
||||||
}
|
}
|
||||||
// console.log(unsealed.address);
|
// console.log(unsealed.address);
|
||||||
} catch (reve) {
|
} catch (reve) {
|
||||||
console.error(reve);
|
console.warn(reve);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fire.count() === 0) {
|
if (fire.count() === 0) {
|
||||||
|
|
@ -65,9 +82,9 @@ Meteor.publish('fireFromHash', function fireFromHash(fireEnc) {
|
||||||
}
|
}
|
||||||
return findFire(unsealed);
|
return findFire(unsealed);
|
||||||
/* console.log(`fires: ${fire.count()}`);
|
/* console.log(`fires: ${fire.count()}`);
|
||||||
* return fire; */
|
* return fire; */
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.warn(e);
|
||||||
throw new Meteor.Error('500', e);
|
return this.ready();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
4
imports/startup/client/meta.js
Normal file
4
imports/startup/client/meta.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* eslint-env jquery */
|
||||||
|
|
||||||
|
// remove static description so it's not duplicated
|
||||||
|
$('meta[name=description]').remove();
|
||||||
|
|
@ -15,7 +15,7 @@ const backOpts = {
|
||||||
jsonIndent: 2
|
jsonIndent: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
const forceDebug = true;
|
const forceDebug = false;
|
||||||
const shouldDebug = (forceDebug && !Meteor.isProduction);
|
const shouldDebug = (forceDebug && !Meteor.isProduction);
|
||||||
|
|
||||||
const i18nOpts = {
|
const i18nOpts = {
|
||||||
|
|
|
||||||
13
imports/ui/components/Utils/location.js
Normal file
13
imports/ui/components/Utils/location.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
|
|
||||||
|
export const location = new ReactiveVar();
|
||||||
|
|
||||||
|
export const currentLocation = () => {
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
return window.location.pathname;
|
||||||
|
}
|
||||||
|
return location.get();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isHome = () => currentLocation() === '/';
|
||||||
|
|
@ -14,6 +14,7 @@ import { Roles } from 'meteor/alanning:roles';
|
||||||
import Blaze from 'meteor/gadicc:blaze-react-component';
|
import Blaze from 'meteor/gadicc:blaze-react-component';
|
||||||
// i18n
|
// i18n
|
||||||
import i18n, { i18nReady } from '/imports/startup/client/i18n';
|
import i18n, { i18nReady } from '/imports/startup/client/i18n';
|
||||||
|
import '/imports/startup/client/meta';
|
||||||
import '/imports/startup/client/ravenLogger';
|
import '/imports/startup/client/ravenLogger';
|
||||||
import '/imports/startup/client/geolocation';
|
import '/imports/startup/client/geolocation';
|
||||||
import '/imports/startup/client/piwik-start.js';
|
import '/imports/startup/client/piwik-start.js';
|
||||||
|
|
|
||||||
|
|
@ -25,21 +25,25 @@ class Fire extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
|
loading: props.loading,
|
||||||
|
notfound: props.notfound,
|
||||||
when: props.when
|
when: props.when
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (this.props.when !== nextProps.when) {
|
if (this.props.when !== nextProps.when || this.props.loading !== nextProps.loading || this.props.notfound !== nextProps.notfound) {
|
||||||
// console.log(`Next when ${nextProps.when}`);
|
// console.log(`Next when ${nextProps.when}`);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
loading: nextProps.loading,
|
||||||
|
notfound: nextProps.notfound,
|
||||||
when: nextProps.when
|
when: nextProps.when
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return !(nextState.when === this.state.when);
|
return !(nextState.when === this.state.when && nextState.loading === this.state.loading && this.state.notfound === nextState.notfound);
|
||||||
}
|
}
|
||||||
|
|
||||||
onTypeSelect(key) {
|
onTypeSelect(key) {
|
||||||
|
|
@ -55,23 +59,27 @@ class Fire extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loading, fire, t } = this.props;
|
const {
|
||||||
|
notfound, loading, fire, t
|
||||||
|
} = this.props;
|
||||||
|
/* console.log(`loading fire: ${loading}`);
|
||||||
|
* console.log(`Not found fire: ${notfound}`); */
|
||||||
if (fire && fire.when) {
|
if (fire && fire.when) {
|
||||||
this.dateLongFormat = dateLongFormat(fire.when);
|
this.dateLongFormat = dateLongFormat(fire.when);
|
||||||
|
this.title = fire.address ?
|
||||||
|
t('Información adicional sobre fuego detectado en {{where}} el {{when}}', { where: fire.address, when: this.dateLongFormat }) :
|
||||||
|
t('Información adicional sobre fuego detectado el {{when}}', { when: this.dateLongFormat });
|
||||||
}
|
}
|
||||||
const title = fire.address ?
|
|
||||||
t('Información adicional sobre fuego detectado en {{where}} el {{when}}', { where: fire.address, when: this.dateLongFormat }) :
|
return (fire && !loading ? (
|
||||||
t('Información adicional sobre fuego detectado el {{when}}', { when: this.dateLongFormat });
|
|
||||||
return (fire ? (
|
|
||||||
<div className="ViewFire">
|
<div className="ViewFire">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<meta charSet="utf-8" />
|
|
||||||
<title>{t('AppName')}: {t('Información adicional sobre fuego')}</title>
|
<title>{t('AppName')}: {t('Información adicional sobre fuego')}</title>
|
||||||
<meta name="description" content={title} />
|
<meta name="description" content={this.title} />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
{!loading &&
|
{!loading &&
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<h4 className="page-header">{title}</h4>
|
<h4 className="page-header">{this.title}</h4>
|
||||||
<Map
|
<Map
|
||||||
ref={(map) => {
|
ref={(map) => {
|
||||||
this.fireMap = map;
|
this.fireMap = map;
|
||||||
|
|
@ -147,13 +155,14 @@ class Fire extends React.Component {
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
) : <NotFound />);
|
) : <Fragment>{ notfound && <NotFound /> }</Fragment>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fire.propTypes = {
|
Fire.propTypes = {
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
loading: PropTypes.bool.isRequired,
|
loading: PropTypes.bool.isRequired,
|
||||||
|
notfound: PropTypes.bool.isRequired,
|
||||||
when: PropTypes.instanceOf(Date),
|
when: PropTypes.instanceOf(Date),
|
||||||
fire: PropTypes.object
|
fire: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
@ -167,10 +176,15 @@ const FireContainer = withTracker(({ match }) => {
|
||||||
const fireEncrypt = match.params.id;
|
const fireEncrypt = match.params.id;
|
||||||
const subscription = Meteor.subscribe('fireFromHash', fireEncrypt);
|
const subscription = Meteor.subscribe('fireFromHash', fireEncrypt);
|
||||||
// console.log(`Subs ready: ${subscription.ready()}, fire: ${JSON.stringify(FiresCollection.findOne())}`);
|
// console.log(`Subs ready: ${subscription.ready()}, fire: ${JSON.stringify(FiresCollection.findOne())}`);
|
||||||
|
const loading = !subscription.ready();
|
||||||
|
const notfound = !loading && FiresCollection.find().count() === 0;
|
||||||
|
/* console.log(`loading fire: ${loading}`);
|
||||||
|
* console.log(`Not found fire: ${notfound}`); */
|
||||||
return {
|
return {
|
||||||
loading: !subscription.ready(),
|
loading,
|
||||||
fire: FiresCollection.findOne(),
|
fire: FiresCollection.findOne(),
|
||||||
when: subscription.ready() ? FiresCollection.findOne().when : null
|
notfound,
|
||||||
|
when: subscription.ready() && FiresCollection.findOne() ? FiresCollection.findOne().when : null
|
||||||
};
|
};
|
||||||
})(Fire);
|
})(Fire);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import FireAlertsCollection from '/imports/api/FireAlerts/FireAlerts';
|
||||||
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
import SiteSettings from '/imports/api/SiteSettings/SiteSettings';
|
||||||
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
||||||
import { isNotHomeAndMobile, isChrome } from '/imports/ui/components/Utils/isMobile';
|
import { isNotHomeAndMobile, isChrome } from '/imports/ui/components/Utils/isMobile';
|
||||||
|
import { isHome } from '/imports/ui/components/Utils/location';
|
||||||
|
|
||||||
import './FiresMap.scss';
|
import './FiresMap.scss';
|
||||||
|
|
||||||
|
|
@ -110,18 +111,17 @@ class FiresMap extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLeafletLoad(map) {
|
handleLeafletLoad(map) {
|
||||||
// console.log(map);
|
if (map && map.leafletElement) {
|
||||||
if (map) {
|
const lmap = map.leafletElement;
|
||||||
// console.log('Firesmap loading');
|
|
||||||
try {
|
try {
|
||||||
const bounds = this.getMap().getBounds();
|
const bounds = lmap.getBounds();
|
||||||
mapSize.set([bounds.getNorthEast(), bounds.getSouthWest()]);
|
mapSize.set([bounds.getNorthEast(), bounds.getSouthWest()]);
|
||||||
if (!this.state.scaleAdded) {
|
if (!this.state.scaleAdded) {
|
||||||
this.addScale();
|
this.addScale();
|
||||||
this.state.scaleAdded = true;
|
this.state.scaleAdded = true;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Failed to set map bounds and scale');
|
console.warn('Failed to set map bounds and scale');
|
||||||
}
|
}
|
||||||
this.state.union = subsUnion(this.state.union, {
|
this.state.union = subsUnion(this.state.union, {
|
||||||
map,
|
map,
|
||||||
|
|
@ -134,15 +134,14 @@ class FiresMap extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { t } = this.props;
|
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. Subs users ready ${this.props.subsready}, 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. Subs users ready ${this.props.subsready} (${this.props.userSubs.length}), reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
/* Large number of markers:
|
/* Large number of markers:
|
||||||
https://stackoverflow.com/questions/43015854/large-dataset-of-markers-or-dots-in-leaflet/43019740#43019740 */
|
https://stackoverflow.com/questions/43015854/large-dataset-of-markers-or-dots-in-leaflet/43019740#43019740 */
|
||||||
<div
|
<div
|
||||||
ref={(divElement) => { this.divElement = divElement; }}
|
ref={(divElement) => { this.divElement = divElement; }}
|
||||||
>
|
>
|
||||||
{ window.location.pathname !== '/' &&
|
{ !isHome() &&
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{t('AppName')}: {t('Fuegos activos')}</title>
|
<title>{t('AppName')}: {t('Fuegos activos')}</title>
|
||||||
<meta name="description" content={t('Fuegos activos en el mundo actualizados en tiempo real')} />
|
<meta name="description" content={t('Fuegos activos en el mundo actualizados en tiempo real')} />
|
||||||
|
|
@ -199,7 +198,7 @@ class FiresMap extends React.Component {
|
||||||
onClick={this.onClickReset}
|
onClick={this.onClickReset}
|
||||||
viewport={this.state.viewport}
|
viewport={this.state.viewport}
|
||||||
onViewportChanged={this.onViewportChanged}
|
onViewportChanged={this.onViewportChanged}
|
||||||
sleep={window.location.pathname === '/' && !isChrome}
|
sleep={isHome() && !isChrome}
|
||||||
sleepTime={10750}
|
sleepTime={10750}
|
||||||
wakeTime={750}
|
wakeTime={750}
|
||||||
sleepNote
|
sleepNote
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { Row, FormGroup, ControlLabel, Button } from 'react-bootstrap';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
import { translate } from 'react-i18next';
|
import { translate } from 'react-i18next';
|
||||||
import { T9n } from 'meteor-accounts-t9n';
|
import { T9n } from 'meteor-accounts-t9n';
|
||||||
import { testId } from '/imports/ui/components/Utils/TestUtils';
|
import { testId } from '/imports/ui/components/Utils/TestUtils';
|
||||||
|
|
@ -68,6 +69,9 @@ class Login extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="Login">
|
<div className="Login">
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.t('AppName')}: {this.t('Iniciar sesión')}</title>
|
||||||
|
</Helmet>
|
||||||
<Row className="align-items-center justify-content-center">
|
<Row className="align-items-center justify-content-center">
|
||||||
<Col xs={12} sm={6} md={5} lg={4}>
|
<Col xs={12} sm={6} md={5} lg={4}>
|
||||||
<h4 className="page-header">{this.t('Iniciar sesión')}</h4>
|
<h4 className="page-header">{this.t('Iniciar sesión')}</h4>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
import Icon from '../../components/Icon/Icon';
|
import Icon from '../../components/Icon/Icon';
|
||||||
import { translate, Trans } from 'react-i18next';
|
import { translate, Trans } from 'react-i18next';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
import './Logout.scss';
|
import './Logout.scss';
|
||||||
|
|
||||||
|
|
@ -12,6 +14,9 @@ class Logout extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="Logout">
|
<div className="Logout">
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.props.t('AppName')}: {this.props.t('Logout')}</title>
|
||||||
|
</Helmet>
|
||||||
<h1><Trans parent="span">Gracias por Participar</Trans></h1>
|
<h1><Trans parent="span">Gracias por Participar</Trans></h1>
|
||||||
<p><Trans parent="span">También puedes seguirnos en la web</Trans></p>
|
<p><Trans parent="span">También puedes seguirnos en la web</Trans></p>
|
||||||
<ul className="FollowUsElsewhere">
|
<ul className="FollowUsElsewhere">
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Alert } from 'react-bootstrap';
|
import { Alert } from 'react-bootstrap';
|
||||||
import { translate, Trans } from 'react-i18next';
|
import { translate, Trans } from 'react-i18next';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
const NotFound = () => (
|
const NotFound = () => (
|
||||||
<div className="NotFound">
|
<div className="NotFound">
|
||||||
|
<Helmet>
|
||||||
|
<title>This page doesn't exist"</title>
|
||||||
|
</Helmet>
|
||||||
<Alert bsStyle="danger">
|
<Alert bsStyle="danger">
|
||||||
<p>
|
<p>
|
||||||
<Trans i18nKey="not-found">Upppps: Esta página no existe</Trans>
|
<Trans i18nKey="not-found">Upppps: Esta página no existe</Trans>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ const Page = ({ title, subtitle, content }) => (
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<title>{i18n.t('AppName')}: {title}</title>
|
<title>{i18n.t('AppName')}: {title}</title>
|
||||||
<meta name="description" content={content.substr(0, 100).lastIndexOf(' ')} />
|
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<PageHeader title={title} subtitle={subtitle} />
|
<PageHeader title={title} subtitle={subtitle} />
|
||||||
<Content content={content} />
|
<Content content={content} />
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Accounts } from 'meteor/accounts-base';
|
import { Accounts } from 'meteor/accounts-base';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
import AccountPageFooter from '../../components/AccountPageFooter/AccountPageFooter';
|
import AccountPageFooter from '../../components/AccountPageFooter/AccountPageFooter';
|
||||||
import validate from '../../../modules/validate';
|
import validate from '../../../modules/validate';
|
||||||
import { translate } from 'react-i18next';
|
import { translate } from 'react-i18next';
|
||||||
|
|
@ -24,16 +25,16 @@ class RecoverPassword extends React.Component {
|
||||||
rules: {
|
rules: {
|
||||||
emailAddress: {
|
emailAddress: {
|
||||||
required: true,
|
required: true,
|
||||||
email: true,
|
email: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
messages: {
|
messages: {
|
||||||
emailAddress: {
|
emailAddress: {
|
||||||
required: this.t("Necesitamos un correo aquí."),
|
required: this.t('Necesitamos un correo aquí.'),
|
||||||
email: this.t("¿Es este correo correcto?"),
|
email: this.t('¿Es este correo correcto?')
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
submitHandler() { component.handleSubmit(); },
|
submitHandler() { component.handleSubmit(); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +47,7 @@ class RecoverPassword extends React.Component {
|
||||||
if (error) {
|
if (error) {
|
||||||
Bert.alert(T9n.get(`error.accounts.${error.reason}`), 'danger');
|
Bert.alert(T9n.get(`error.accounts.${error.reason}`), 'danger');
|
||||||
} else {
|
} else {
|
||||||
Bert.alert(t("checkResetEmail", {email: email}), 'success');
|
Bert.alert(t('checkResetEmail', { email }), 'success');
|
||||||
history.push('/login');
|
history.push('/login');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -55,14 +56,17 @@ class RecoverPassword extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (<div className="RecoverPassword">
|
return (<div className="RecoverPassword">
|
||||||
<Row className="align-items-center justify-content-center">
|
<Row className="align-items-center justify-content-center">
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.t('AppName')}: {this.t('Recupera tu contraseña')}</title>
|
||||||
|
</Helmet>
|
||||||
<Col xs={12} sm={6} md={5} lg={4}>
|
<Col xs={12} sm={6} md={5} lg={4}>
|
||||||
<h4 className="page-header">{this.t("Recupera tu contraseña")}</h4>
|
<h4 className="page-header">{this.t('Recupera tu contraseña')}</h4>
|
||||||
<Alert bsStyle="info">
|
<Alert bsStyle="info">
|
||||||
{this.t("Introduce tu correo abajo para recibir un enlace para resetear tu contraseña.")}
|
{this.t('Introduce tu correo abajo para recibir un enlace para resetear tu contraseña.')}
|
||||||
</Alert>
|
</Alert>
|
||||||
<form ref={form => (this.form = form)} onSubmit={event => event.preventDefault()}>
|
<form ref={form => (this.form = form)} onSubmit={event => event.preventDefault()}>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<ControlLabel>{this.t("Correo electrónico")}</ControlLabel>
|
<ControlLabel>{this.t('Correo electrónico')}</ControlLabel>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
name="emailAddress"
|
name="emailAddress"
|
||||||
|
|
@ -70,9 +74,9 @@ class RecoverPassword extends React.Component {
|
||||||
className="form-control"
|
className="form-control"
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<Button type="submit" bsStyle="success">{this.t("Recupera tu contraseña")}</Button>
|
<Button type="submit" bsStyle="success">{this.t('Recupera tu contraseña')}</Button>
|
||||||
<AccountPageFooter>
|
<AccountPageFooter>
|
||||||
<p>{this.t("¿Recuerdas tu contraseña?")} <Link to="/login">{this.t("Iniciar sesión")}</Link>.</p>
|
<p>{this.t('¿Recuerdas tu contraseña?')} <Link to="/login">{this.t('Iniciar sesión')}</Link>.</p>
|
||||||
</AccountPageFooter>
|
</AccountPageFooter>
|
||||||
</form>
|
</form>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -82,7 +86,7 @@ class RecoverPassword extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
RecoverPassword.propTypes = {
|
RecoverPassword.propTypes = {
|
||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default translate([], { wait: true })(RecoverPassword);
|
export default translate([], { wait: true })(RecoverPassword);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { Row, Alert, FormGroup, ControlLabel, Button } from 'react-bootstrap';
|
||||||
import Col from '../../components/Col/Col';
|
import Col from '../../components/Col/Col';
|
||||||
import { Accounts } from 'meteor/accounts-base';
|
import { Accounts } from 'meteor/accounts-base';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
import validate from '../../../modules/validate';
|
import validate from '../../../modules/validate';
|
||||||
import { translate } from 'react-i18next';
|
import { translate } from 'react-i18next';
|
||||||
import { T9n } from 'meteor-accounts-t9n';
|
import { T9n } from 'meteor-accounts-t9n';
|
||||||
|
|
@ -61,6 +62,9 @@ class ResetPassword extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (<div className="ResetPassword">
|
return (<div className="ResetPassword">
|
||||||
<Row className="align-items-center justify-content-center">
|
<Row className="align-items-center justify-content-center">
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.t('AppName')}: {this.t('Resetea tu contraseña')}</title>
|
||||||
|
</Helmet>
|
||||||
<Col xs={12} sm={6} md={4}>
|
<Col xs={12} sm={6} md={4}>
|
||||||
<h4 className="page-header">{this.t("Resetea tu contraseña")}</h4>
|
<h4 className="page-header">{this.t("Resetea tu contraseña")}</h4>
|
||||||
<Alert bsStyle="info">
|
<Alert bsStyle="info">
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
/* eslint-disable react/jsx-indent-props */
|
/* eslint-disable react/jsx-indent-props */
|
||||||
|
/* eslint-disable import/no-absolute-path */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Row, FormGroup, ControlLabel, Button, Checkbox } from 'react-bootstrap';
|
import { Row, FormGroup, ControlLabel, Button, Checkbox } from 'react-bootstrap';
|
||||||
import Col from '../../components/Col/Col';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Accounts } from 'meteor/accounts-base';
|
import { Accounts } from 'meteor/accounts-base';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
|
import { translate, Trans } from 'react-i18next';
|
||||||
|
import { T9n } from 'meteor-accounts-t9n';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
import { testId } from '/imports/ui/components/Utils/TestUtils';
|
import { testId } from '/imports/ui/components/Utils/TestUtils';
|
||||||
|
import Col from '../../components/Col/Col';
|
||||||
import Icon from '../../components/Icon/Icon';
|
import Icon from '../../components/Icon/Icon';
|
||||||
import OAuthLoginButtons from '../../components/OAuthLoginButtons/OAuthLoginButtons';
|
import OAuthLoginButtons from '../../components/OAuthLoginButtons/OAuthLoginButtons';
|
||||||
import InputHint from '../../components/InputHint/InputHint';
|
import InputHint from '../../components/InputHint/InputHint';
|
||||||
import AccountPageFooter from '../../components/AccountPageFooter/AccountPageFooter';
|
import AccountPageFooter from '../../components/AccountPageFooter/AccountPageFooter';
|
||||||
import validate from '../../../modules/validate';
|
import validate from '../../../modules/validate';
|
||||||
import './Signup.scss';
|
import './Signup.scss';
|
||||||
import { translate, Trans } from 'react-i18next';
|
|
||||||
import { T9n } from 'meteor-accounts-t9n';
|
|
||||||
|
|
||||||
class Signup extends React.Component {
|
class Signup extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|
@ -120,6 +122,9 @@ class Signup extends React.Component {
|
||||||
const { t, history } = this.props;
|
const { t, history } = this.props;
|
||||||
return (<div className="Signup">
|
return (<div className="Signup">
|
||||||
<Row className="align-items-center justify-content-center">
|
<Row className="align-items-center justify-content-center">
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.t('AppName')}: {this.t('Registrarse')}</title>
|
||||||
|
</Helmet>
|
||||||
<Col xs={12} sm={6} md={5} lg={4}>
|
<Col xs={12} sm={6} md={5} lg={4}>
|
||||||
<h4 className="page-header">{t('Registrarse')}</h4>
|
<h4 className="page-header">{t('Registrarse')}</h4>
|
||||||
<Row>
|
<Row>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
|
||||||
import { translate } from 'react-i18next';
|
import { translate } from 'react-i18next';
|
||||||
import { withTracker } from 'meteor/react-meteor-data';
|
import { withTracker } from 'meteor/react-meteor-data';
|
||||||
import Blaze from 'meteor/gadicc:blaze-react-component';
|
import Blaze from 'meteor/gadicc:blaze-react-component';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://github.com/meteor/docs/blob/version-NEXT/long-form/oplog-observe-driver.md
|
https://github.com/meteor/docs/blob/version-NEXT/long-form/oplog-observe-driver.md
|
||||||
|
|
@ -26,6 +27,9 @@ class Status extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.t('AppName')}: Status</title>
|
||||||
|
</Helmet>
|
||||||
<h4 className="page-header">Status</h4>
|
<h4 className="page-header">Status</h4>
|
||||||
<Blaze template="serverFacts" />
|
<Blaze template="serverFacts" />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { Meteor } from 'meteor/meteor';
|
||||||
import { withTracker } from 'meteor/react-meteor-data';
|
import { withTracker } from 'meteor/react-meteor-data';
|
||||||
import { Trans, translate } from 'react-i18next';
|
import { Trans, translate } from 'react-i18next';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
|
||||||
import SelectionMap, { action } from '/imports/ui/components/SelectionMap/SelectionMap';
|
import SelectionMap, { action } from '/imports/ui/components/SelectionMap/SelectionMap';
|
||||||
import confirm from '/imports/ui/components/Prompt/Confirm';
|
import confirm from '/imports/ui/components/Prompt/Confirm';
|
||||||
|
|
@ -84,6 +85,9 @@ class Subscriptions extends Component {
|
||||||
const firstBtnTitle = ['Añadir zona', '', 'Terminar']; // view, add, edit
|
const firstBtnTitle = ['Añadir zona', '', 'Terminar']; // view, add, edit
|
||||||
return (!loading ? (
|
return (!loading ? (
|
||||||
<div className="Subscriptions">
|
<div className="Subscriptions">
|
||||||
|
<Helmet>
|
||||||
|
<title>{t('AppName')}: {t('Suscripciones a alertas de fuegos en zonas de mi interés')}</title>
|
||||||
|
</Helmet>
|
||||||
<h4 className="page-header"><Trans>Suscripciones a alertas de fuegos en zonas de mi interés</Trans></h4>
|
<h4 className="page-header"><Trans>Suscripciones a alertas de fuegos en zonas de mi interés</Trans></h4>
|
||||||
{ subscriptions.length === 0 ?
|
{ subscriptions.length === 0 ?
|
||||||
<Alert bsStyle="warning"><Trans>No estás suscrito a fuegos en ninguna zona</Trans></Alert> :
|
<Alert bsStyle="warning"><Trans>No estás suscrito a fuegos en ninguna zona</Trans></Alert> :
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Alert } from 'react-bootstrap';
|
import { Alert } from 'react-bootstrap';
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
import { Accounts } from 'meteor/accounts-base';
|
import { Accounts } from 'meteor/accounts-base';
|
||||||
import { Bert } from 'meteor/themeteorchef:bert';
|
import { Bert } from 'meteor/themeteorchef:bert';
|
||||||
import { translate } from 'react-i18next';
|
import { translate } from 'react-i18next';
|
||||||
|
|
@ -32,6 +33,9 @@ class VerifyEmail extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (<div className="VerifyEmail">
|
return (<div className="VerifyEmail">
|
||||||
|
<Helmet>
|
||||||
|
<title>{this.t('AppName')}: {this.t('Verifica tu dirección de correo')}</title>
|
||||||
|
</Helmet>
|
||||||
<Alert bsStyle={!this.state.error ? 'info' : 'danger'}>
|
<Alert bsStyle={!this.state.error ? 'info' : 'danger'}>
|
||||||
{!this.state.error ? this.t('Verificando...') : this.state.error}
|
{!this.state.error ? this.t('Verificando...') : this.state.error}
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@
|
||||||
"Uso de Cookies": "Use of Cookies",
|
"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",
|
"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",
|
"Participa": "Get Involved",
|
||||||
"activeFires": "Active fires",
|
"activeFires": "Active Fires",
|
||||||
"Fuegos activos": "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}}</0></1> active fires detected worldwide.",
|
"noActiveFireInMapCount": "There are no active fires in this area of the map. There is a total of <1><0>{{countTotal}}</0></1> active fires detected worldwide.",
|
||||||
"activeFireInMapCount": "On the map marked in red <1><0>{{count,number}}</0></1> active fires. There is a total of <3><0>{{countTotal,number}} </0></3> active fires detected worldwide by NASA.",
|
"activeFireInMapCount": "On the map marked in red <1><0>{{count,number}}</0></1> active fires. There is a total of <3><0>{{countTotal,number}} </0></3> active fires detected worldwide by NASA.",
|
||||||
"activeNeigFireInMapCount": "In Orange, the fires recently reported by our users.",
|
"activeNeigFireInMapCount": "In Orange, the fires recently reported by our users.",
|
||||||
|
|
@ -161,5 +161,6 @@
|
||||||
"Verifica tu dirección de correo": "Verify Your Email Address",
|
"Verifica tu dirección de correo": "Verify Your Email Address",
|
||||||
"Zonas vigiladas": "Monitored areas",
|
"Zonas vigiladas": "Monitored areas",
|
||||||
"En verde, las zonas vigiladas por nuestros usuari@s actualmente": "In green, the areas monitored by our users currently",
|
"En verde, las zonas vigiladas por nuestros usuari@s actualmente": "In green, the areas monitored by our users currently",
|
||||||
"Datos actualizados <1></1>.": "Data updated <1></1>."
|
"Datos actualizados <1></1>.": "Data updated <1></1>.",
|
||||||
|
"Información adicional sobre fuego": "Additional information about fire"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue