diff --git a/lib/dbcheck.js b/lib/dbcheck.js index 30b13b0c..001723a1 100644 --- a/lib/dbcheck.js +++ b/lib/dbcheck.js @@ -21,10 +21,10 @@ let db = mysql.createPool(mysqlConfig); function listTables(callback) { db.getConnection((err, connection) => { if (err) { - if(err.code === 'ER_ACCESS_DENIED_ERROR'){ + if (err.code === 'ER_ACCESS_DENIED_ERROR') { err = new Error('Could not access the database. Check MySQL config and authentication credentials'); } - if(err.code === 'ECONNREFUSED' || err.code === 'PROTOCOL_SEQUENCE_TIMEOUT'){ + if (err.code === 'ECONNREFUSED' || err.code === 'PROTOCOL_SEQUENCE_TIMEOUT') { err = new Error('Could not connect to the database. Check MySQL host and port configuration'); } return callback(err); diff --git a/lib/models/subscriptions.js b/lib/models/subscriptions.js index cae7cd8b..f5e58bf8 100644 --- a/lib/models/subscriptions.js +++ b/lib/models/subscriptions.js @@ -230,7 +230,7 @@ module.exports.insert = (listId, meta, subscription, callback) => { let keys = []; let values = []; - let allowedKeys = ['first_name', 'last_name']; + let allowedKeys = ['first_name', 'last_name', 'tz']; Object.keys(subscription).forEach(key => { let value = subscription[key]; key = tools.toDbKey(key); @@ -392,7 +392,8 @@ module.exports.getWithMergeTags = (listId, cid, callback) => { EMAIL: subscription.email, FIRST_NAME: subscription.firstName, LAST_NAME: subscription.lastName, - FULL_NAME: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' ') + FULL_NAME: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' '), + TIMEZONE: subscription.tz || '' }; fields.getRow(fieldList, subscription, true, true).forEach(field => { @@ -433,7 +434,7 @@ module.exports.update = (listId, cid, updates, allowEmail, callback) => { return callback(err); } - let allowedKeys = ['first_name', 'last_name']; + let allowedKeys = ['first_name', 'last_name', 'tz']; if (allowEmail) { allowedKeys.unshift('email'); diff --git a/lib/tz.js b/lib/tz.js new file mode 100644 index 00000000..11fa0e79 --- /dev/null +++ b/lib/tz.js @@ -0,0 +1,147 @@ +'use strict'; + +module.exports.list = [ + 'Pacific/Midway', + 'Pacific/Samoa', + 'Pacific/Honolulu', + 'US/Alaska', + 'America/Los_Angeles', + 'America/Tijuana', + 'US/Arizona', + 'America/Chihuahua', + 'America/Chihuahua', + 'America/Mazatlan', + 'US/Mountain', + 'America/Managua', + 'US/Central', + 'America/Mexico_City', + 'America/Mexico_City', + 'America/Monterrey', + 'Canada/Saskatchewan', + 'America/Bogota', + 'US/Eastern', + 'US/East-Indiana', + 'America/Lima', + 'America/Bogota', + 'Canada/Atlantic', + 'America/Caracas', + 'America/La_Paz', + 'America/Santiago', + 'Canada/Newfoundland', + 'America/Sao_Paulo', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Buenos_Aires', + 'America/Godthab', + 'America/Noronha', + 'Atlantic/Azores', + 'Atlantic/Cape_Verde', + 'Africa/Casablanca', + 'Europe/London', + 'Etc/Greenwich', + 'Europe/Lisbon', + 'Europe/London', + 'Africa/Monrovia', + 'UTC', + 'Europe/Amsterdam', + 'Europe/Belgrade', + 'Europe/Berlin', + 'Europe/Berlin', + 'Europe/Bratislava', + 'Europe/Brussels', + 'Europe/Budapest', + 'Europe/Copenhagen', + 'Europe/Ljubljana', + 'Europe/Madrid', + 'Europe/Paris', + 'Europe/Prague', + 'Europe/Rome', + 'Europe/Sarajevo', + 'Europe/Skopje', + 'Europe/Stockholm', + 'Europe/Vienna', + 'Europe/Warsaw', + 'Africa/Lagos', + 'Europe/Zagreb', + 'Europe/Athens', + 'Europe/Bucharest', + 'Africa/Cairo', + 'Africa/Harare', + 'Europe/Helsinki', + 'Europe/Istanbul', + 'Asia/Jerusalem', + 'Europe/Helsinki', + 'Africa/Johannesburg', + 'Europe/Riga', + 'Europe/Sofia', + 'Europe/Tallinn', + 'Europe/Vilnius', + 'Asia/Baghdad', + 'Asia/Kuwait', + 'Europe/Minsk', + 'Africa/Nairobi', + 'Asia/Riyadh', + 'Europe/Volgograd', + 'Asia/Tehran', + 'Asia/Muscat', + 'Asia/Baku', + 'Europe/Moscow', + 'Asia/Muscat', + 'Europe/Moscow', + 'Asia/Tbilisi', + 'Asia/Yerevan', + 'Asia/Kabul', + 'Asia/Karachi', + 'Asia/Karachi', + 'Asia/Tashkent', + 'Asia/Calcutta', + 'Asia/Kolkata', + 'Asia/Calcutta', + 'Asia/Calcutta', + 'Asia/Calcutta', + 'Asia/Katmandu', + 'Asia/Almaty', + 'Asia/Dhaka', + 'Asia/Dhaka', + 'Asia/Yekaterinburg', + 'Asia/Rangoon', + 'Asia/Bangkok', + 'Asia/Bangkok', + 'Asia/Jakarta', + 'Asia/Novosibirsk', + 'Asia/Hong_Kong', + 'Asia/Chongqing', + 'Asia/Hong_Kong', + 'Asia/Krasnoyarsk', + 'Asia/Kuala_Lumpur', + 'Australia/Perth', + 'Asia/Singapore', + 'Asia/Taipei', + 'Asia/Ulan_Bator', + 'Asia/Urumqi', + 'Asia/Irkutsk', + 'Asia/Tokyo', + 'Asia/Tokyo', + 'Asia/Seoul', + 'Asia/Tokyo', + 'Australia/Adelaide', + 'Australia/Darwin', + 'Australia/Brisbane', + 'Australia/Canberra', + 'Pacific/Guam', + 'Australia/Hobart', + 'Australia/Melbourne', + 'Pacific/Port_Moresby', + 'Australia/Sydney', + 'Asia/Yakutsk', + 'Asia/Vladivostok', + 'Pacific/Auckland', + 'Pacific/Fiji', + 'Pacific/Kwajalein', + 'Asia/Kamchatka', + 'Asia/Magadan', + 'Pacific/Fiji', + 'Asia/Magadan', + 'Asia/Magadan', + 'Pacific/Auckland', + 'Pacific/Tongatapu' +]; diff --git a/meta.json b/meta.json index b4a9b4a7..a66ca216 100644 --- a/meta.json +++ b/meta.json @@ -1,3 +1,3 @@ { - "schemaVersion": 4 + "schemaVersion": 5 } diff --git a/public/javascript/tables.js b/public/javascript/tables.js index 492d318a..7d85e5bf 100644 --- a/public/javascript/tables.js +++ b/public/javascript/tables.js @@ -1,6 +1,6 @@ /* eslint-env browser */ /* eslint prefer-arrow-callback: 0, object-shorthand: 0, new-cap: 0, no-invalid-this: 0, no-var: 0*/ -/* globals $: false, moment: false */ +/* globals $: false, moment: false, jstz: false */ 'use strict'; @@ -125,3 +125,13 @@ $('.page-refresh').each(function () { window.location.reload(); }, interval * 1000); }); + +if (typeof jstz !== 'undefined') { + (function () { + var tz = jstz.determine(); + var tzname = tz && tz.name() || false; + if (tzname) { + $('.tz-detect').val(tzname); + } + })(); +} diff --git a/public/jstimezonedetect/jstz.min.js b/public/jstimezonedetect/jstz.min.js new file mode 100644 index 00000000..a6be0f66 --- /dev/null +++ b/public/jstimezonedetect/jstz.min.js @@ -0,0 +1,2 @@ +/* jstz.min.js Version: 1.0.6 Build date: 2015-11-04 */ +!function(e){var a=function(){"use strict";var e="s",s={DAY:864e5,HOUR:36e5,MINUTE:6e4,SECOND:1e3,BASELINE_YEAR:2014,MAX_SCORE:864e6,AMBIGUITIES:{"America/Denver":["America/Mazatlan"],"Europe/London":["Africa/Casablanca"],"America/Chicago":["America/Mexico_City"],"America/Asuncion":["America/Campo_Grande","America/Santiago"],"America/Montevideo":["America/Sao_Paulo","America/Santiago"],"Asia/Beirut":["Asia/Amman","Asia/Jerusalem","Europe/Helsinki","Asia/Damascus","Africa/Cairo","Asia/Gaza","Europe/Minsk"],"Pacific/Auckland":["Pacific/Fiji"],"America/Los_Angeles":["America/Santa_Isabel"],"America/New_York":["America/Havana"],"America/Halifax":["America/Goose_Bay"],"America/Godthab":["America/Miquelon"],"Asia/Dubai":["Asia/Yerevan"],"Asia/Jakarta":["Asia/Krasnoyarsk"],"Asia/Shanghai":["Asia/Irkutsk","Australia/Perth"],"Australia/Sydney":["Australia/Lord_Howe"],"Asia/Tokyo":["Asia/Yakutsk"],"Asia/Dhaka":["Asia/Omsk"],"Asia/Baku":["Asia/Yerevan"],"Australia/Brisbane":["Asia/Vladivostok"],"Pacific/Noumea":["Asia/Vladivostok"],"Pacific/Majuro":["Asia/Kamchatka","Pacific/Fiji"],"Pacific/Tongatapu":["Pacific/Apia"],"Asia/Baghdad":["Europe/Minsk","Europe/Moscow"],"Asia/Karachi":["Asia/Yekaterinburg"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"]}},i=function(e){var a=-e.getTimezoneOffset();return null!==a?a:0},r=function(){var a=i(new Date(s.BASELINE_YEAR,0,2)),r=i(new Date(s.BASELINE_YEAR,5,2)),n=a-r;return 0>n?a+",1":n>0?r+",1,"+e:a+",0"},n=function(){var e,a;if("undefined"!=typeof Intl&&"undefined"!=typeof Intl.DateTimeFormat&&(e=Intl.DateTimeFormat(),"undefined"!=typeof e&&"undefined"!=typeof e.resolvedOptions))return a=e.resolvedOptions().timeZone,a&&(a.indexOf("/")>-1||"UTC"===a)?a:void 0},o=function(e){for(var a=new Date(e,0,1,0,0,1,0).getTime(),s=new Date(e,12,31,23,59,59).getTime(),i=a,r=new Date(i).getTimezoneOffset(),n=null,o=null;s-864e5>i;){var t=new Date(i),A=t.getTimezoneOffset();A!==r&&(r>A&&(n=t),A>r&&(o=t),r=A),i+=864e5}return n&&o?{s:u(n).getTime(),e:u(o).getTime()}:!1},u=function l(e,a,i){"undefined"==typeof a&&(a=s.DAY,i=s.HOUR);for(var r=new Date(e.getTime()-a).getTime(),n=e.getTime()+a,o=new Date(r).getTimezoneOffset(),u=r,t=null;n-i>u;){var A=new Date(u),c=A.getTimezoneOffset();if(c!==o){t=A;break}u+=i}return a===s.DAY?l(t,s.HOUR,s.MINUTE):a===s.HOUR?l(t,s.MINUTE,s.SECOND):t},t=function(e,a,s,i){if("N/A"!==s)return s;if("Asia/Beirut"===a){if("Africa/Cairo"===i.name&&13983768e5===e[6].s&&14116788e5===e[6].e)return 0;if("Asia/Jerusalem"===i.name&&13959648e5===e[6].s&&14118588e5===e[6].e)return 0}else if("America/Santiago"===a){if("America/Asuncion"===i.name&&14124816e5===e[6].s&&1397358e6===e[6].e)return 0;if("America/Campo_Grande"===i.name&&14136912e5===e[6].s&&13925196e5===e[6].e)return 0}else if("America/Montevideo"===a){if("America/Sao_Paulo"===i.name&&14136876e5===e[6].s&&1392516e6===e[6].e)return 0}else if("Pacific/Auckland"===a&&"Pacific/Fiji"===i.name&&14142456e5===e[6].s&&13961016e5===e[6].e)return 0;return s},A=function(e,i){for(var r=function(a){for(var r=0,n=0;n=a.rules[n].s&&e[n].e<=a.rules[n].e)){r="N/A";break}if(r=0,r+=Math.abs(e[n].s-a.rules[n].s),r+=Math.abs(a.rules[n].e-e[n].e),r>s.MAX_SCORE){r="N/A";break}}return r=t(e,i,r,a)},n={},o=a.olson.dst_rules.zones,u=o.length,A=s.AMBIGUITIES[i],c=0;u>c;c++){var m=o[c],l=r(o[c]);"N/A"!==l&&(n[m.name]=l)}for(var f in n)if(n.hasOwnProperty(f))for(var d=0;d { if (field.column) { allowedColumns.push(field.column); diff --git a/routes/subscription.js b/routes/subscription.js index 60f909f8..bef3df01 100644 --- a/routes/subscription.js +++ b/routes/subscription.js @@ -13,6 +13,7 @@ let fields = require('../lib/models/fields'); let subscriptions = require('../lib/models/subscriptions'); let settings = require('../lib/models/settings'); let openpgp = require('openpgp'); +let tzlist = require('../lib/tz').list; router.get('/subscribe/:cid', (req, res, next) => { subscriptions.subscribe(req.params.cid, req.ip, (err, subscription) => { diff --git a/setup/sql/upgrade-00005.sql b/setup/sql/upgrade-00005.sql new file mode 100644 index 00000000..ca4ef4ec --- /dev/null +++ b/setup/sql/upgrade-00005.sql @@ -0,0 +1,17 @@ +# Header section +# Define incrementing schema version number +SET @schema_version = '5'; + +-- {{#each tables.subscription}} + + # Adds new column 'tz' to subscriptions table + # Indicates subscriber time zone, use UTC as default + ALTER TABLE `{{this}}` ADD COLUMN `tz` varchar(100) CHARACTER SET ascii DEFAULT NULL AFTER `opt_in_country`; + CREATE INDEX subscriber_tz ON `{{this}}` (`tz`); + +-- {{/each}} + +# Footer section +LOCK TABLES `settings` WRITE; +INSERT INTO `settings` (`key`, `value`) VALUES('db_schema_version', @schema_version) ON DUPLICATE KEY UPDATE `value`=@schema_version; +UNLOCK TABLES; diff --git a/setup/sql/upgrade-template.sql b/setup/sql/upgrade-template.sql index 3982b6a7..2cabd529 100644 --- a/setup/sql/upgrade-template.sql +++ b/setup/sql/upgrade-template.sql @@ -1,6 +1,6 @@ # This file is a handlebars template # To modify several similar tables at once use (replace [] with {}): -# [[#each tablename]] ALTER TABLE `[[this]]` ... [[/each]] +# [[#each tables.tablename]] ALTER TABLE `[[this]]` ... [[/each]] # NB! as this is a handlebars file, then remember to escape any template sequences # Header section diff --git a/views/lists/subscription/import-preview.hbs b/views/lists/subscription/import-preview.hbs index 8b0913bf..2ffb33f0 100644 --- a/views/lists/subscription/import-preview.hbs +++ b/views/lists/subscription/import-preview.hbs @@ -24,6 +24,7 @@ + {{#each ../customFields}} {{#if column}} diff --git a/views/subscription/layout.hbs b/views/subscription/layout.hbs index 7c959d74..02faf158 100644 --- a/views/subscription/layout.hbs +++ b/views/subscription/layout.hbs @@ -48,6 +48,7 @@ + {{#if useEditor}} diff --git a/views/subscription/manage.hbs b/views/subscription/manage.hbs index ef578e53..4d8cfe76 100644 --- a/views/subscription/manage.hbs +++ b/views/subscription/manage.hbs @@ -11,6 +11,7 @@ +
diff --git a/views/subscription/subscribe.hbs b/views/subscription/subscribe.hbs index 4f1347f1..d32a61d6 100644 --- a/views/subscription/subscribe.hbs +++ b/views/subscription/subscribe.hbs @@ -8,6 +8,7 @@
+