diff --git a/CHANGELOG.md b/CHANGELOG.md index c79358c4..3e0f65f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,29 +5,55 @@ This project adheres to [Semantic Versioning](http://semver.org/). --- -## [2.7.0] - Unreleased +❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror² core. + +## [2.8.0] - Unreleased *This release is scheduled to be released on 2019-04-01.* +### Added +- Option to show event location in calendar + +- Finnish translation for "Feels" and "Weeks" + +- Russian translation for “Feels” + +### Updated + +### Fixed +- Handle SIGTERM messages +- Fixes sliceMultiDayEvents so it respects maximumNumberOfDays + +## [2.7.1] - 2019-04-02 + +Fixed `package.json` version number. + +## [2.7.0] - 2019-04-01 + ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md). ### Added - Italian translation for "Feels" -- Disabled the screensaver on raspbian with installation script +- Basic Klingon (tlhIngan Hol) translations +- Disabled the screensaver on raspbian with installation script - Added option to truncate the number of vertical lines a calendar item can span if `wrapEvents` is enabled. -- Added autoLocation options for weather forcast and current weather modules. -- Added autoTimezone option for the default clock module. - Danish translation for "Feels" and "Weeks" - Added option to split multiple day events in calendar to separate numbered events - Slovakian translation - Alerts now can contain Font Awesome icons +- Notifications display time can be set in request +- Newsfeed: added support for `ARTICLE_INFO_REQUEST` notification +- Add `name` config option for calendars to be sent along with event broadcasts ### Updated - Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MichMich/MagicMirror/issues/1500) +- Updated modernizr code in alert module, fixed a small typo there too +- More verbose error message on console if the config is malformed +- Updated installer script to install Node.js version 10.x ### Fixed - Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503), [#1511](https://github.com/MichMich/MagicMirror/issues/1511). -- Fixed unhandled error on bad git data in updatenotiifcation module [#1285](https://github.com/MichMich/MagicMirror/issues/1285). +- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MichMich/MagicMirror/issues/1285). - Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504). - Fixed analogue clock border display issue where non-black backgrounds used (previous fix for issue 611) - Fixed compatibility issues caused when modules request different versions of Font Awesome, see issue [#1522](https://github.com/MichMich/MagicMirror/issues/1522). MagicMirror now uses [Font Awesome 5 with v4 shims included for backwards compatibility](https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#shims). @@ -38,6 +64,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Fix null dereference in moduleNeedsUpdate when the module isn't visible - Calendar: Fixed event end times by setting default calendarEndTime to "LT" (Local time format). [#1479] - Calendar: Fixed missing calendar fetchers after server process restarts [#1589](https://github.com/MichMich/MagicMirror/issues/1589) +- Notification: fixed background color (was white text on white background) +- Use getHeader instead of data.header when creating the DOM so overwriting the function also propagates into it +- Fix documentation of `useKMPHwind` option in currentweather ### New weather module - Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499). @@ -109,7 +138,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Fixed gzip encoded calendar loading issue #1400. - Mixup between german and spanish translation for newsfeed. - Fixed close dates to be absolute, if no configured in the config.js - module Calendar -- Fixed the UpdateNotification module message about new commits in the repository, so they can be correctly localized in singular and plural form. +- Fixed the updatenotification module message about new commits in the repository, so they can be correctly localized in singular and plural form. - Fix for weatherforecast rainfall rounding [#1374](https://github.com/MichMich/MagicMirror/issues/1374) - Fix calendar parsing issue for Midori on RasperryPi Zero w, related to issue #694. - Fix weather city ID link in sample config @@ -259,7 +288,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Add `clientonly` script to start only the electron client for a remote server. - Add symbol and color properties of event when `CALENDAR_EVENTS` notification is broadcasted from `default/calendar` module. - Add `.vscode/` folder to `.gitignore` to keep custom Visual Studio Code config out of git. -- Add unit test the capitalizeFirstLetter function of newfeed module. +- Add unit test the capitalizeFirstLetter function of newsfeed module. - Add new unit tests for function `shorten` in calendar module. - Add new unit tests for function `getLocaleSpecification` in calendar module. - Add unit test for js/class.js. @@ -280,7 +309,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Set version of the `express-ipfilter` on 0.3.1. ### Fixed -- Fixed issue with incorrect allignment of analog clock when displayed in the center column of the MM. +- Fixed issue with incorrect alignment of analog clock when displayed in the center column of the MM. - Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM. - Fixed issue with calendar module where 'excludedEvents' count towards 'maximumEntries'. - Fixed issue with calendar module where global configuration of maximumEntries was not overridden by calendar specific config (see module doc). @@ -304,7 +333,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Add unit test calendar_modules function capFirst. - Add test for check if exists the directories present in defaults modules. - Add support for showing wind direction as an arrow instead of abbreviation in currentWeather module. -- Add support for writing translation fucntions to support flexible word order +- Add support for writing translation functions to support flexible word order - Add test for check if exits the directories present in defaults modules. - Add calendar option to set a separate date format for full day events. - Add ability for `currentweather` module to display indoor temperature via INDOOR_TEMPERATURE notification @@ -323,7 +352,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Fix double message about port when server is starting - Corrected Swedish translations for TODAY/TOMORROW/DAYAFTERTOMORROW. - Removed unused import from js/electron.js -- Made calendar.js respect config.timeFormat irrespecive of locale setting. +- Made calendar.js respect config.timeFormat irrespective of locale setting. - Fixed alignment of analog clock when a large calendar is displayed in the same side bar. ## [2.1.1] - 2017-04-01 @@ -341,7 +370,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Added `DAYAFTERTOMORROW`, `UPDATE_NOTIFICATION` and `UPDATE_NOTIFICATION_MODULE` to Finnish translations. - Run `npm test` on Travis automatically. - Show the splash screen image even when is reboot or halted. -- Added some missing translaton strings in the sv.json file. +- Added some missing translation strings in the sv.json file. - Run task jsonlint to check translation files. - Restructured Test Suite. @@ -358,12 +387,12 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Option to use RegExp in Calendar's titleReplace. - Hungarian Translation. - Icelandic Translation. -- Add use a script to prevent when is run by SSH session set DISPLAY enviroment. -- Enable ability to set configuration file by the enviroment variable called MM_CONFIG_FILE. +- Add use a script to prevent when is run by SSH session set DISPLAY environment. +- Enable ability to set configuration file by the environment variable called MM_CONFIG_FILE. - Option to give each calendar a different color. - Option for colored min-temp and max-temp. - Add test e2e helloworld. -- Add test e2e enviroment. +- Add test e2e environment. - Add `chai-as-promised` npm module to devDependencies. - Basic set of tests for clock module. - Run e2e test in Travis. @@ -381,10 +410,10 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Added tests for Translations, dev argument, version, dev console. - Added test anytime feature compliments module. - Added test ipwhitelist configuration directive. -- Added test for calendar module: default, basic-auth, backward compability, fail-basic-auth. +- Added test for calendar module: default, basic-auth, backward compatibility, fail-basic-auth. - Added meta tags to support fullscreen mode on iOS (for server mode) - Added `ignoreOldItems` and `ignoreOlderThan` options to the News Feed module -- Added test for MM_PORT enviroment variable. +- Added test for MM_PORT environment variable. - Added a configurable Week section to the clock module. ### Fixed @@ -396,7 +425,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Module currentWeather: check if temperature received from api is defined. - Fix an issue with module hidden status changing to `true` although lock string prevented showing it. - Fix newsfeed module bug (removeStartTags) -- Fix when is set MM_PORT enviroment variable. +- Fix when is set MM_PORT environment variable. - Fixed missing animation on `this.show(speed)` when module is alone in a region. ## [2.1.0] - 2016-12-31 @@ -418,8 +447,8 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/calendar) for more information. - Possibility to use the the calendar feed as the source for the weather (currentweather & weatherforecast) location data. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/weatherforecast) for more information. - Added option to show rain amount in the weatherforecast default module -- Add module `updatenotification` to get an update whenever a new version is availabe. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/updatenotification) for more information. -- Add the abilty to set timezone on the date display in the Clock Module +- Add module `updatenotification` to get an update whenever a new version is available. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/updatenotification) for more information. +- Add the ability to set timezone on the date display in the Clock Module - Ability to set date format in calendar module - Possibility to use currentweather for the compliments - Added option `disabled` for modules. @@ -458,7 +487,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Added ability to define "the day after tomorrow" for calendar events (Definition for German and Dutch already included). - Added CII Badge (we are compliant with the CII Best Practices) - Add support for doing http basic auth when loading calendars -- Add the abilty to turn off and on the date display in the Clock Module +- Add the ability to turn off and on the date display in the Clock Module ### Fixed - Fix typo in installer. @@ -481,8 +510,8 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed - Prevent `getModules()` selectors from returning duplicate entries. -- Append endpoints of weather modules with `/` to retreive the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337)) -- Corrected grammer in `module.js` from 'suspend' to 'suspended'. +- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337)) +- Corrected grammar in `module.js` from 'suspend' to 'suspended'. - Fixed openweathermap.org URL in config sample. - Prevent currentweather module from crashing when received data object is incorrect. - Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MichMich/MagicMirror/issues/388)) diff --git a/README.md b/README.md index 1cadc57a..ee92ca92 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ The following wiki links are helpful for the initial configuration of your Magic **Note:** If you used the installer script. This step is already done for you. 2. Modify your required settings. \ - Note: You'll can check your configuration running `npm run config:check` in `/home/pi/MagicMirror`. + Note: You can check your configuration running `npm run config:check` in `/home/pi/MagicMirror`. The following properties can be configured: diff --git a/installers/raspberry.sh b/installers/raspberry.sh index 1551b5fb..c698bb83 100644 --- a/installers/raspberry.sh +++ b/installers/raspberry.sh @@ -82,7 +82,7 @@ if $NODE_INSTALL; then # The NODE_STABLE_BRANCH variable will need to be manually adjusted when a new branch is released. (e.g. 7.x) # Only tested (stable) versions are recommended as newer versions could break MagicMirror. - NODE_STABLE_BRANCH="9.x" + NODE_STABLE_BRANCH="10.x" curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash - sudo apt-get install -y nodejs echo -e "\e[92mNode.js installation Done!\e[0m" diff --git a/js/app.js b/js/app.js index bfec5baf..4a10ba6d 100644 --- a/js/app.js +++ b/js/app.js @@ -70,7 +70,7 @@ var App = function() { if (e.code == "ENOENT") { console.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration.")); } else if (e instanceof ReferenceError || e instanceof SyntaxError) { - console.error(Utils.colors.error("WARNING! Could not validate config file. Please correct syntax errors. Starting with default configuration.")); + console.error(Utils.colors.error("WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: " + e.stack)); } else { console.error(Utils.colors.error("WARNING! Could not load config file. Starting with default configuration. Error found: " + e)); } @@ -263,6 +263,15 @@ var App = function() { this.stop(); process.exit(0); }); + + /* We also need to listen to SIGTERM signals so we stop everything when we are asked to stop by the OS. + */ + process.on("SIGTERM", () => { + console.log("[SIGTERM] Received. Shutting down server..."); + setTimeout(() => { process.exit(0); }, 3000); // Force quit after 3 seconds + this.stop(); + process.exit(0); + }); }; module.exports = new App(); diff --git a/js/main.js b/js/main.js index 21a882f8..2330d3ee 100644 --- a/js/main.js +++ b/js/main.js @@ -39,9 +39,9 @@ var MM = (function() { dom.opacity = 0; wrapper.appendChild(dom); - if (typeof module.data.header !== "undefined" && module.data.header !== "") { + if (typeof module.getHeader() !== "undefined" && module.getHeader() !== "") { var moduleHeader = document.createElement("header"); - moduleHeader.innerHTML = module.data.header; + moduleHeader.innerHTML = module.getHeader(); moduleHeader.className = "module-header"; dom.appendChild(moduleHeader); } diff --git a/js/module.js b/js/module.js index 907a7f61..3e39dd5c 100644 --- a/js/module.js +++ b/js/module.js @@ -212,7 +212,7 @@ var Module = Class.extend({ /* setData(data) * Set the module data. * - * argument data obejct - Module data. + * argument data object - Module data. */ setData: function (data) { this.data = data; @@ -226,7 +226,7 @@ var Module = Class.extend({ /* setConfig(config) * Set the module config and combine it with the module defaults. * - * argument config obejct - Module config. + * argument config object - Module config. */ setConfig: function (config) { this.config = Object.assign({}, this.defaults, config); diff --git a/modules/default/alert/README.md b/modules/default/alert/README.md index c57ba793..4c6e4333 100644 --- a/modules/default/alert/README.md +++ b/modules/default/alert/README.md @@ -43,10 +43,11 @@ self.sendNotification("SHOW_ALERT", {}); ``` ### Notification params -| Option | Description -| --------- | ----------- -| `title` | The title of the notification.

**Possible values:** `text` or `html` -| `message` | The message of the notification.

**Possible values:** `text` or `html` +| Option | Description +| ------------------ | ----------- +| `title` | The title of the notification.

**Possible values:** `text` or `html` +| `message` | The message of the notification.

**Possible values:** `text` or `html` +| `timer` (optional) | How long the notification should stay visible in ms.
If absent, the default `display_time` is used.
**Possible values:** `int` `float` ### Alert params @@ -61,4 +62,4 @@ self.sendNotification("SHOW_ALERT", {}); ## Open Source Licenses ### [NotificationStyles](https://github.com/codrops/NotificationStyles) -See [ympanus.net](http://tympanus.net/codrops/licensing/) for license. +See [tympanus.net](http://tympanus.net/codrops/licensing/) for license. diff --git a/modules/default/alert/alert.js b/modules/default/alert/alert.js index 9c0d91a7..0f47bc3f 100644 --- a/modules/default/alert/alert.js +++ b/modules/default/alert/alert.js @@ -51,7 +51,7 @@ Module.register("alert",{ message: msg, layout: "growl", effect: this.config.effect, - ttl: this.config.display_time + ttl: message.timer !== undefined ? message.timer : this.config.display_time }).show(); }, show_alert: function(params, sender) { diff --git a/modules/default/alert/modernizr.custom.js b/modules/default/alert/modernizr.custom.js index 3d33a8be..83c3d3f1 100644 --- a/modules/default/alert/modernizr.custom.js +++ b/modules/default/alert/modernizr.custom.js @@ -1,5 +1,3 @@ -/* Modernizr 2.8.3 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-cssanimations-shiv-cssclasses-prefixed-testprop-testallprops-domprefixes-load - */ -// jscs:disable -;window.Modernizr = function(a, b, c) {function x(a) {j.cssText = a;}function y(a, b) {return x(prefixes.join(a + ";") + (b || ""));}function z(a, b) {return typeof a === b;}function A(a, b) {return !!~("" + a).indexOf(b);}function B(a, b) {for (var d in a) {var e = a[d];if (!A(e,"-") && j[e] !== c)return b == "pfx" ? e : !0;}return !1;}function C(a, b, d) {for (var e in a) {var f = b[a[e]];if (f !== c)return d === !1 ? a[e] : z(f,"function") ? f.bind(d || b) : f;}return !1;}function D(a, b, c) {var d = a.charAt(0).toUpperCase() + a.slice(1),e = (a + " " + n.join(d + " ") + d).split(" ");return z(b,"string") || z(b,"undefined") ? B(e,b) : (e = (a + " " + o.join(d + " ") + d).split(" "),C(e,b,c));}var d = "2.8.3",e = {},f = !0,g = b.documentElement,h = "modernizr",i = b.createElement(h),j = i.style,k,l = {}.toString,m = "Webkit Moz O ms",n = m.split(" "),o = m.toLowerCase().split(" "),p = {},q = {},r = {},s = [],t = s.slice,u,v = {}.hasOwnProperty,w;!z(v,"undefined") && !z(v.call,"undefined") ? w = function(a, b) {return v.call(a,b);} : w = function(a, b) {return b in a && z(a.constructor.prototype[b],"undefined");},Function.prototype.bind || (Function.prototype.bind = function(b) {var c = this;if (typeof c != "function")throw new TypeError;var d = t.call(arguments,1),e = function() {if (this instanceof e) {var a = function() {};a.prototype = c.prototype;var f = new a,g = c.apply(f,d.concat(t.call(arguments)));return Object(g) === g ? g : f;}return c.apply(b,d.concat(t.call(arguments)));};return e;}),p.cssanimations = function() {return D("animationName");};for (var E in p)w(p,E) && (u = E.toLowerCase(),e[u] = p[E](),s.push((e[u] ? "" : "no-") + u));return e.addTest = function(a, b) {if (typeof a == "object")for (var d in a)w(a,d) && e.addTest(d,a[d]);else {a = a.toLowerCase();if (e[a] !== c)return e;b = typeof b == "function" ? b() : b,typeof f != "undefined" && f && (g.className += " " + (b ? "" : "no-") + a),e[a] = b;}return e;},x(""),i = k = null,function(a, b) {function l(a, b) {var c = a.createElement("p"),d = a.getElementsByTagName("head")[0] || a.documentElement;return c.innerHTML = "x",d.insertBefore(c.lastChild,d.firstChild);}function m() {var a = s.elements;return typeof a == "string" ? a.split(" ") : a;}function n(a) {var b = j[a[h]];return b || (b = {},i++,a[h] = i,j[i] = b),b;}function o(a, c, d) {c || (c = b);if (k)return c.createElement(a);d || (d = n(c));var g;return d.cache[a] ? g = d.cache[a].cloneNode() : f.test(a) ? g = (d.cache[a] = d.createElem(a)).cloneNode() : g = d.createElem(a),g.canHaveChildren && !e.test(a) && !g.tagUrn ? d.frag.appendChild(g) : g;}function p(a, c) {a || (a = b);if (k)return a.createDocumentFragment();c = c || n(a);var d = c.frag.cloneNode(),e = 0,f = m(),g = f.length;for (; e < g; e++)d.createElement(f[e]);return d;}function q(a, b) {b.cache || (b.cache = {},b.createElem = a.createElement,b.createFrag = a.createDocumentFragment,b.frag = b.createFrag()),a.createElement = function(c) {return s.shivMethods ? o(c,a,b) : b.createElem(c);},a.createDocumentFragment = Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(" + m().join().replace(/[\w\-]+/g,function(a) {return b.createElem(a),b.frag.createElement(a),"c(\"" + a + "\")";}) + ");return n}")(s,b.frag);}function r(a) {a || (a = b);var c = n(a);return s.shivCSS && !g && !c.hasCSS && (c.hasCSS = !!l(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k || q(a,c),a;}var c = "3.7.0",d = a.html5 || {},e = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,f = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,g,h = "_html5shiv",i = 0,j = {},k;(function() {try {var a = b.createElement("a");a.innerHTML = "",g = "hidden"in a,k = a.childNodes.length == 1 || function() {b.createElement("a");var a = b.createDocumentFragment();return typeof a.cloneNode == "undefined" || typeof a.createDocumentFragment == "undefined" || typeof a.createElement == "undefined";}();}catch (c) {g = !0,k = !0;}})();var s = {elements: d.elements || "abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version: c,shivCSS: d.shivCSS !== !1,supportsUnknownElements: k,shivMethods: d.shivMethods !== !1,type: "default",shivDocument: r,createElement: o,createDocumentFragment: p};a.html5 = s,r(b);}(this,b),e._version = d,e._domPrefixes = o,e._cssomPrefixes = n,e.testProp = function(a) {return B([a]);},e.testAllProps = D,e.prefixed = function(a, b, c) {return b ? D(a,b,c) : D(a,"pfx");},g.className = g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2") + (f ? " js " + s.join(" ") : ""),e;}(this,this.document),function(a, b, c) {function d(a) {return "[object Function]" == o.call(a);}function e(a) {return "string" == typeof a;}function f() {}function g(a) {return !a || "loaded" == a || "complete" == a || "uninitialized" == a;}function h() {var a = p.shift();q = 1,a ? a.t ? m(function() {("c" == a.t ? B.injectCss : B.injectJs)(a.s,0,a.a,a.x,a.e,1);},0) : (a(),h()) : q = 0;}function i(a, c, d, e, f, i, j) {function k(b) {if (!o && g(l.readyState) && (u.r = o = 1,!q && h(),l.onload = l.onreadystatechange = null,b)) {"img" != a && m(function() {t.removeChild(l);},50);for (var d in y[c])y[c].hasOwnProperty(d) && y[c][d].onload();}}var j = j || B.errorTimeout,l = b.createElement(a),o = 0,r = 0,u = {t: d,s: c,e: f,a: i,x: j};1 === y[c] && (r = 1,y[c] = []),"object" == a ? l.data = c : (l.src = c,l.type = a),l.width = l.height = "0",l.onerror = l.onload = l.onreadystatechange = function() {k.call(this,r);},p.splice(e,0,u),"img" != a && (r || 2 === y[c] ? (t.insertBefore(l,s ? null : n),m(k,j)) : y[c].push(l));}function j(a, b, c, d, f) {return q = 0,b = b || "j",e(a) ? i("c" == b ? v : u,a,b,this.i++,c,d,f) : (p.splice(this.i++,0,a),1 == p.length && h()),this;}function k() {var a = B;return a.loader = {load: j,i: 0},a;}var l = b.documentElement,m = a.setTimeout,n = b.getElementsByTagName("script")[0],o = {}.toString,p = [],q = 0,r = "MozAppearance"in l.style,s = r && !!b.createRange().compareNode,t = s ? l : n.parentNode,l = a.opera && "[object Opera]" == o.call(a.opera),l = !!b.attachEvent && !l,u = r ? "object" : l ? "script" : "img",v = l ? "script" : u,w = Array.isArray || function(a) {return "[object Array]" == o.call(a);},x = [],y = {},z = {timeout: function(a, b) {return b.length && (a.timeout = b[0]),a;}},A,B;B = function(a) {function b(a) {var a = a.split("!"),b = x.length,c = a.pop(),d = a.length,c = {url: c,origUrl: c,prefixes: a},e,f,g;for (f = 0; f < d; f++)g = a[f].split("="),(e = z[g.shift()]) && (c = e(c,g));for (f = 0; f < b; f++)c = x[f](c);return c;}function g(a, e, f, g, h) {var i = b(a),j = i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass || (e && (e = d(e) ? e : e[a] || e[g] || e[a.split("/").pop().split("?")[0]]),i.instead ? i.instead(a,e,f,g,h) : (y[i.url] ? i.noexec = !0 : y[i.url] = 1,f.load(i.url,i.forceCSS || !i.forceJS && "css" == i.url.split(".").pop().split("?").shift() ? "c" : c,i.noexec,i.attrs,i.timeout),(d(e) || d(j)) && f.load(function() {k(),e && e(i.origUrl,h,g),j && j(i.origUrl,h,g),y[i.url] = 2;})));}function h(a, b) {function c(a, c) {if (a) {if (e(a))c || (j = function() {var a = [].slice.call(arguments);k.apply(this,a),l();}),g(a,j,b,0,h);else if (Object(a) === a)for (n in m = function() {var b = 0,c;for (c in a)a.hasOwnProperty(c) && b++;return b;}(),a)a.hasOwnProperty(n) && (!c && !--m && (d(j) ? j = function() {var a = [].slice.call(arguments);k.apply(this,a),l();} : j[n] = function(a) {return function() {var b = [].slice.call(arguments);a && a.apply(this,b),l();};}(k[n])),g(a[n],j,b,n,h));}else !c && l();}var h = !!a.test,i = a.load || a.both,j = a.callback || f,k = j,l = a.complete || f,m,n;c(h ? a.yep : a.nope,!!i),i && c(i);}var i,j,l = this.yepnope.loader;if (e(a))g(a,0,l,0);else if (w(a))for (i = 0; i < a.length; i++)j = a[i],e(j) ? g(j,0,l,0) : w(j) ? B(j) : Object(j) === j && h(j,l);else Object(a) === a && h(a,l);},B.addPrefix = function(a, b) {z[a] = b;},B.addFilter = function(a) {x.push(a);},B.errorTimeout = 1e4,null == b.readyState && b.addEventListener && (b.readyState = "loading",b.addEventListener("DOMContentLoaded",A = function() {b.removeEventListener("DOMContentLoaded",A,0),b.readyState = "complete";},0)),a.yepnope = k(),a.yepnope.executeStack = h,a.yepnope.injectJs = function(a, c, d, e, i, j) {var k = b.createElement("script"),l,o,e = e || B.errorTimeout;k.src = a;for (o in d)k.setAttribute(o,d[o]);c = j ? h : c || f,k.onreadystatechange = k.onload = function() {!l && g(k.readyState) && (l = 1,c(),k.onload = k.onreadystatechange = null);},m(function() {l || (l = 1,c(1));},e),i ? k.onload() : n.parentNode.insertBefore(k,n);},a.yepnope.injectCss = function(a, c, d, e, g, i) {var e = b.createElement("link"),j,c = i ? h : c || f;e.href = a,e.rel = "stylesheet",e.type = "text/css";for (j in d)e.setAttribute(j,d[j]);g || (n.parentNode.insertBefore(e,n),m(c,0));};}(this,document),Modernizr.load = function() {yepnope.apply(window,[].slice.call(arguments,0));}; +/*! modernizr 3.7.0 (Custom Build) | MIT * + * https://modernizr.com/download/?-cssanimations-domprefixes-prefixed-setclasses-shiv-testallprops-testprop !*/ +!function(e,t,n){function r(e,t){return typeof e===t}function o(e,t){return!!~(""+e).indexOf(t)}function i(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):E?t.createElementNS.call(t,"http://www.w3.org/2000/svg",arguments[0]):t.createElement.apply(t,arguments)}function a(){var e=t.body;return e||(e=i(E?"svg":"body"),e.fake=!0),e}function s(e,n,r,o){var s,l,c,u,f="modernizr",d=i("div"),p=a();if(parseInt(r,10))for(;r--;)c=i("div"),c.id=o?o[r]:f+(r+1),d.appendChild(c);return s=i("style"),s.type="text/css",s.id="s"+f,(p.fake?p:d).appendChild(s),p.appendChild(d),s.styleSheet?s.styleSheet.cssText=e:s.appendChild(t.createTextNode(e)),d.id=f,p.fake&&(p.style.background="",p.style.overflow="hidden",u=S.style.overflow,S.style.overflow="hidden",S.appendChild(p)),l=n(d,e),p.fake?(p.parentNode.removeChild(p),S.style.overflow=u,S.offsetHeight):d.parentNode.removeChild(d),!!l}function l(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function c(t,n,r){var o;if("getComputedStyle"in e){o=getComputedStyle.call(e,t,n);var i=e.console;if(null!==o)r&&(o=o.getPropertyValue(r));else if(i){var a=i.error?"error":"log";i[a].call(i,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}}else o=!n&&t.currentStyle&&t.currentStyle[r];return o}function u(t,r){var o=t.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(l(t[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+l(t[o])+":"+r+")");return i=i.join(" or "),s("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"===c(e,null,"position")})}return n}function f(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function d(e,t,a,s){function l(){d&&(delete N.style,delete N.modElem)}if(s=!r(s,"undefined")&&s,!r(a,"undefined")){var c=u(e,a);if(!r(c,"undefined"))return c}for(var d,p,m,h,v,g=["modernizr","tspan","samp"];!N.style&&g.length;)d=!0,N.modElem=i(g.shift()),N.style=N.modElem.style;for(m=e.length,p=0;p",r.insertBefore(n.lastChild,r.firstChild)}function r(){var e=y.elements;return"string"==typeof e?e.split(" "):e}function o(e,t){var n=y.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof e&&(e=e.join(" ")),y.elements=n+" "+e,c(t)}function i(e){var t=g[e[h]];return t||(t={},v++,e[h]=v,g[v]=t),t}function a(e,n,r){if(n||(n=t),f)return n.createElement(e);r||(r=i(n));var o;return o=r.cache[e]?r.cache[e].cloneNode():m.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e),!o.canHaveChildren||p.test(e)||o.tagUrn?o:r.frag.appendChild(o)}function s(e,n){if(e||(e=t),f)return e.createDocumentFragment();n=n||i(e);for(var o=n.frag.cloneNode(),a=0,s=r(),l=s.length;a",u="hidden"in e,f=1==e.childNodes.length||function(){t.createElement("a");var e=t.createDocumentFragment();return void 0===e.cloneNode||void 0===e.createDocumentFragment||void 0===e.createElement}()}catch(e){u=!0,f=!0}}();var y={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:"3.7.3",shivCSS:!1!==d.shivCSS,supportsUnknownElements:f,shivMethods:!1!==d.shivMethods,type:"default",shivDocument:c,createElement:a,createDocumentFragment:s,addElements:o};e.html5=y,c(t),"object"==typeof module&&module.exports&&(module.exports=y)}(void 0!==e?e:this,t);var w=y._config.usePrefixes?x.split(" "):[];y._cssomPrefixes=w;var _={elem:i("modernizr")};Modernizr._q.push(function(){delete _.elem});var N={style:_.elem.style};Modernizr._q.unshift(function(){delete N.style}),y.testAllProps=h;var j=function(t){var r,o=prefixes.length,i=e.CSSRule;if(void 0===i)return n;if(!t)return!1;if(t=t.replace(/^@/,""),(r=t.replace(/-/g,"_").toUpperCase()+"_RULE")in i)return"@"+t;for(var a=0;a0&&(t+=" "+n+e.join(" "+n)),E?S.className.baseVal=t:S.className=t)}(C),delete y.addTest,delete y.addAsyncTest;for(var z=0;z
**Default value:** `365` | `displaySymbol` | Display a symbol in front of an entry.

**Possible values:** `true` or `false`
**Default value:** `true` | `defaultSymbol` | The default symbol.

**Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website.
**Default value:** `calendar` +| `showLocation` | Whether to show event locations.

**Possible values:** `true` or `false`
**Default value:** `false` | `maxTitleLength` | The maximum title length.

**Possible values:** `10` - `50`
**Default value:** `25` | `wrapEvents` | Wrap event titles to multiple lines. Breaks lines at the length defined by `maxTitleLength`.

**Possible values:** `true` or `false`
**Default value:** `false` | `maxTitleLines` | The maximum number of lines a title will wrap vertically before being cut (Only enabled if `wrapEvents` is also enabled).

**Possible values:** `0` - `10`
**Default value:** `3` @@ -53,7 +54,7 @@ The following properties can be configured: | `hidePrivate` | Hides private calendar events.

**Possible values:** `true` or `false`
**Default value:** `false` | `hideOngoing` | Hides calendar events that have already started.

**Possible values:** `true` or `false`
**Default value:** `false` | `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown.

Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.
**Required**
`filterBy` - string used to determine if filter is applied.
**Optional**
`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]
`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity
`regex` - set to `true` if filterBy is a regex. For those not familiar with regex it is used for pattern matching, please see [here](https://regexr.com/) for more info.

**Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}, {filterBy: '^[0-9]{1,}.*', regex: true}]`
**Default value:** `[]` -| `sliceMultiDayEvents` | If this is set to true, events exceeding at least one midnight will be sliced into separate events including a counter like (1/2). This is especially helpful in "dateheaders" mode. Events will be sliced at midnight, end time for all events but the last will be 23:59 **Default value:** `true` +| `sliceMultiDayEvents` | If this is set to true, events exceeding at least one midnight will be sliced into separate events including a counter like (1/2). This is especially helpful in "dateheaders" mode. Events will be sliced at midnight, end time for all events but the last will be 23:59 **Default value:** `false` ### Calendar configuration @@ -90,6 +91,7 @@ config: { | `repeatingCountTitle` | The count title for yearly repating events in this calendar.

**Example:** `'Birthday'` | `maximumEntries` | The maximum number of events shown. Overrides global setting. **Possible values:** `0` - `100` | `maximumNumberOfDays` | The maximum number of days in the future. Overrides global setting +| `name` | The name of the calendar. Included in event broadcasts as `calendarName`. | `auth` | The object containing options for authentication against the calendar. | `symbolClass` | Add a class to the cell of symbol. | `titleClass` | Add a class to the title's cell. diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index a6eeb226..3aaed2ae 100755 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -15,6 +15,7 @@ Module.register("calendar", { maximumNumberOfDays: 365, displaySymbol: true, defaultSymbol: "calendar", // Fontawesome Symbol see http://fontawesome.io/cheatsheet/ + showLocation: false, displayRepeatingCountTitle: false, defaultRepeatingCountTitle: "", maxTitleLength: 25, @@ -379,6 +380,31 @@ Module.register("calendar", { currentFadeStep = e - startFade; eventWrapper.style.opacity = 1 - (1 / fadeSteps * currentFadeStep); } + + if (this.config.showLocation) { + if (event.location !== false) { + var locationRow = document.createElement("tr"); + locationRow.className = "normal xsmall light"; + + if (this.config.displaySymbol) { + var symbolCell = document.createElement("td"); + locationRow.appendChild(symbolCell); + } + + var descCell = document.createElement("td"); + descCell.className = "location"; + descCell.colSpan = "2"; + descCell.innerHTML = event.location; + locationRow.appendChild(descCell); + + wrapper.appendChild(locationRow); + + if (e >= startFade) { + currentFadeStep = e - startFade; + locationRow.style.opacity = 1 - (1 / fadeSteps * currentFadeStep); + } + } + } } return wrapper; @@ -436,10 +462,11 @@ Module.register("calendar", { var events = []; var today = moment().startOf("day"); var now = new Date(); + var future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate(); for (var c in this.calendarData) { var calendar = this.calendarData[c]; for (var e in calendar) { - var event = calendar[e]; + var event = JSON.parse(JSON.stringify(calendar[e])); // clone object if(this.config.hidePrivate) { if(event.class === "PRIVATE") { // do not add the current event, skip it @@ -461,23 +488,30 @@ Module.register("calendar", { * otherwise, esp. in dateheaders mode it is not clear how long these events are. */ if (this.config.sliceMultiDayEvents) { - var midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x"); //next midnight + var splitEvents = []; + var midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x"); var count = 1; - var maxCount = Math.ceil(((event.endDate - 1) - moment(event.startDate, "x").endOf("day").format("x"))/(1000*60*60*24)) + 1 - if (event.endDate > midnight) { - while (event.endDate > midnight) { - var nextEvent = JSON.parse(JSON.stringify(event)); //make a copy without reference to the original event - nextEvent.startDate = midnight; - event.endDate = midnight; - event.title += " (" + count + "/" + maxCount + ")"; - events.push(event); - event = nextEvent; - count += 1; - midnight = moment(midnight, "x").add(1, "day").format("x"); //move further one day for next split - } - event.title += " ("+count+"/"+maxCount+")"; - } - events.push(event); + var maxCount = Math.ceil(((event.endDate - 1) - moment(event.startDate, "x").endOf("day").format("x"))/(1000*60*60*24)) + 1; + while (event.endDate > midnight) { + var thisEvent = JSON.parse(JSON.stringify(event)) // clone object + thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < (today + 24 * 60 * 60 * 1000); + thisEvent.endDate = midnight; + thisEvent.title += " (" + count + "/" + maxCount + ")"; + splitEvents.push(thisEvent); + + event.startDate = midnight; + count += 1; + midnight = moment(midnight, "x").add(1, "day").format("x"); // next day + } + // Last day + event.title += " ("+count+"/"+maxCount+")"; + splitEvents.push(event); + + for (event of splitEvents) { + if ((event.endDate > now) && (event.endDate <= future)) { + events.push(event); + } + } } else { events.push(event); } @@ -487,7 +521,6 @@ Module.register("calendar", { events.sort(function (a, b) { return a.startDate - b.startDate; }); - return events.slice(0, this.config.maximumEntries); }, @@ -569,6 +602,17 @@ Module.register("calendar", { return this.getCalendarProperty(url, "timeClass", ""); }, + /* calendarNameForUrl(url) + * Retrieves the calendar name for a specific url. + * + * argument url string - Url to look for. + * + * return string - The name of the calendar + */ + calendarNameForUrl: function (url) { + return this.getCalendarProperty(url, "name", ""); + }, + /* colorForUrl(url) * Retrieves the color for a specific url. * @@ -709,6 +753,7 @@ Module.register("calendar", { for (var e in calendar) { var event = cloneObject(calendar[e]); event.symbol = this.symbolsForUrl(url); + event.calendarName = this.calendarNameForUrl(url); event.color = this.colorForUrl(url); delete event.url; eventList.push(event); diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index a1e4aa8d..0076a605 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -273,7 +273,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri /* isFullDayEvent(event) * Checks if an event is a fullday event. * - * argument event obejct - The event object to check. + * argument event object - The event object to check. * * return bool - The event is a fullday event. */ diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 03528bce..23b801d0 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -26,7 +26,6 @@ Module.register("clock",{ analogShowDate: "top", // options: false, 'top', or 'bottom' secondsColor: "#888888", timezone: null, - autoTimezone: false }, // Define required scripts. getScripts: function() { @@ -40,31 +39,16 @@ Module.register("clock",{ start: function() { Log.info("Starting module: " + this.name); - if (this.config.autoTimezone) { - this.sendSocketNotification("AUTO_TIMEZONE"); - } else { - // Schedule update interval. - var self = this; - setInterval(function() { - self.updateDom(); - }, 1000); - } + // Schedule update interval. + var self = this; + setInterval(function() { + self.updateDom(); + }, 1000); // Set locale. moment.locale(config.language); }, - - socketNotificationReceived: function (notification, payload) { - if (notification === "UPDATE_TIMEZONE") { - var self = this; - self.config.timezone = payload.timezone; - setInterval(function() { - self.updateDom(); - }, 1000); - } - }, - // Override dom generator. getDom: function() { diff --git a/modules/default/clock/node_helper.js b/modules/default/clock/node_helper.js deleted file mode 100644 index 68258b0a..00000000 --- a/modules/default/clock/node_helper.js +++ /dev/null @@ -1,29 +0,0 @@ -var http = require("http"); -var NodeHelper = require("node_helper"); - -module.exports = NodeHelper.create({ - start: function () { - }, - - socketNotificationReceived: function (notification, payload) { - var self = this; - - if (notification === "AUTO_TIMEZONE") { - console.log("Loading timezone..."); - http.get("http://ip-api.com/json", function (req) { - var data = ""; - req.on("data", function (d) { - data += d; - }); - req.on("end", function () { - var body = JSON.parse(data); - payload.timezone = body.timezone; - self.sendSocketNotification("UPDATE_TIMEZONE", payload); - }); - }).on("error", function () { - payload.error = "Could not figure out the timezone."; - self.sendSocketNotification("UPDATE_TIMEZONE", payload); - }); - } - } -}); diff --git a/modules/default/currentweather/README.md b/modules/default/currentweather/README.md index ac883a93..ce8cd19e 100644 --- a/modules/default/currentweather/README.md +++ b/modules/default/currentweather/README.md @@ -50,7 +50,7 @@ The following properties can be configured: | `showIndoorTemperature` | If you have another module that emits the INDOOR_TEMPERATURE notification, the indoor temperature will be displayed
**Default value:** `false` | `onlyTemp` | Show only current Temperature and weather icon without windspeed, sunset, sunrise time and feels like.

**Possible values:** `true` or `false`
**Default value:** `false` | `showFeelsLike` | Shows the Feels like temperature weather.

**Possible values:**`true` or `false`
**Default value:** `true` -| `useKMPHWind` | Uses KMPH as units for windspeed.

**Possible values:**`true` or `false`
**Default value:** `false` +| `useKMPHwind` | Uses KMPH as units for windspeed.

**Possible values:**`true` or `false`
**Default value:** `false` | `useBeaufort` | Pick between using the Beaufort scale for wind speed or using the default units.

**Possible values:** `true` or `false`
**Default value:** `true` | `lang` | The language of the days.

**Possible values:** `en`, `nl`, `ru`, etc ...
**Default value:** uses value of _config.language_ | `decimalSymbol` | The decimal symbol to use.

**Possible values:** `.`, `,` or any other symbol.
**Default value:** `.` diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index 0472b7a1..2ccc23b7 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -11,7 +11,6 @@ Module.register("currentweather",{ // Default module config. defaults: { - autoLocation: false, location: false, locationID: false, appid: "", @@ -72,7 +71,7 @@ Module.register("currentweather",{ firstEvent: false, // create a variable to hold the location name based on the API result. - fetchedLocatioName: "", + fetchedLocationName: "", // Define required scripts. getScripts: function() { @@ -110,19 +109,8 @@ Module.register("currentweather",{ this.weatherType = null; this.feelsLike = null; this.loaded = false; + this.scheduleUpdate(this.config.initialLoadDelay); - if (this.config.autoLocation) { - this.sendSocketNotification("AUTO_LOCATION"); - } else { - this.scheduleUpdate(this.config.initialLoadDelay); - } - }, - - socketNotificationReceived: function (notification, payload) { - if (notification === "UPDATE_LOCATION") { - this.config.location = payload.location; - this.scheduleUpdate(this.config.initialLoadDelay); - } }, // add extra information of current weather @@ -277,8 +265,8 @@ Module.register("currentweather",{ // Override getHeader method. getHeader: function() { - if (this.config.appendLocationNameToHeader) { - return this.data.header + " " + this.fetchedLocatioName; + if (this.config.appendLocationNameToHeader && this.data.header !== undefined) { + return this.data.header + " " + this.fetchedLocationName; } return this.data.header; diff --git a/modules/default/currentweather/node_helper.js b/modules/default/currentweather/node_helper.js deleted file mode 100644 index 53956f62..00000000 --- a/modules/default/currentweather/node_helper.js +++ /dev/null @@ -1,29 +0,0 @@ -var http = require("http"); -var NodeHelper = require("node_helper"); - -module.exports = NodeHelper.create({ - start: function () { - }, - - socketNotificationReceived: function (notification, payload) { - var self = this; - - if (notification === "AUTO_LOCATION") { - console.log("Loading timezone..."); - http.get("http://ip-api.com/json", function (req) { - var data = ""; - req.on("data", function (d) { - data += d; - }); - req.on("end", function () { - var body = JSON.parse(data); - payload.location = body.city + ", " + body.regionName; - self.sendSocketNotification("UPDATE_LOCATION", payload); - }); - }).on("error", function () { - payload.error = "Could not figure out the timezone."; - self.sendSocketNotification("UPDATE_LOCATION", payload); - }); - } - } -}); diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index c06c3f07..b14a7ac6 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -46,6 +46,7 @@ MagicMirror's [notification mechanism](https://github.com/MichMich/MagicMirror/t | `ARTICLE_MORE_DETAILS` | When received the _first time_, shows the corresponding description of the currently displayed news title.
The module expects that the module's configuration option `showDescription` is set to `false` (default value).

When received a _second consecutive time_, shows the full news article in an IFRAME.
This requires that the news page can be embedded in an IFRAME, e.g. doesn't have the HTTP response header [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) set to e.g. `DENY`.

When received the _next consecutive times_, reloads the page and scrolls down by `scrollLength` pixels to paginate through the article. | `ARTICLE_LESS_DETAILS` | Hides the summary or full news article and only displays the news title of the currently viewed news item. | `ARTICLE_TOGGLE_FULL` | Toogles article in fullscreen. +| `ARTICLE_INFO_REQUEST` | Causes `newsfeed` to respond with the notification `ARTICLE_INFO_RESPONSE`, the payload of which provides the `title`, `source`, `date`, `desc` and `url` of the current news title. Note the payload of the sent notification event is ignored. diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 212a6a0f..3bb38d0a 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -189,7 +189,7 @@ Module.register("newsfeed",{ fullArticle.style.top = "0"; fullArticle.style.left = "0"; fullArticle.style.border = "none"; - fullArticle.src = typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href; + fullArticle.src = this.getActiveItemURL() fullArticle.style.zIndex = 1; wrapper.appendChild(fullArticle); } @@ -210,6 +210,10 @@ Module.register("newsfeed",{ return wrapper; }, + getActiveItemURL: function() { + return typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href; + }, + /* registerFeeds() * registers the feeds to be used by the backend. */ @@ -387,6 +391,14 @@ Module.register("newsfeed",{ } else { this.showFullArticle(); } + } else if (notification === "ARTICLE_INFO_REQUEST"){ + this.sendNotification("ARTICLE_INFO_RESPONSE", { + title: this.newsItems[this.activeItem].title, + source: this.newsItems[this.activeItem].sourceTitle, + date: this.newsItems[this.activeItem].pubdate, + desc: this.newsItems[this.activeItem].description, + url: this.getActiveItemURL() + }) } else { Log.info(this.name + " - unknown notification, ignoring: " + notification); } diff --git a/modules/default/weatherforecast/node_helper.js b/modules/default/weatherforecast/node_helper.js deleted file mode 100644 index 53956f62..00000000 --- a/modules/default/weatherforecast/node_helper.js +++ /dev/null @@ -1,29 +0,0 @@ -var http = require("http"); -var NodeHelper = require("node_helper"); - -module.exports = NodeHelper.create({ - start: function () { - }, - - socketNotificationReceived: function (notification, payload) { - var self = this; - - if (notification === "AUTO_LOCATION") { - console.log("Loading timezone..."); - http.get("http://ip-api.com/json", function (req) { - var data = ""; - req.on("data", function (d) { - data += d; - }); - req.on("end", function () { - var body = JSON.parse(data); - payload.location = body.city + ", " + body.regionName; - self.sendSocketNotification("UPDATE_LOCATION", payload); - }); - }).on("error", function () { - payload.error = "Could not figure out the timezone."; - self.sendSocketNotification("UPDATE_LOCATION", payload); - }); - } - } -}); diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js index c32821db..67193696 100644 --- a/modules/default/weatherforecast/weatherforecast.js +++ b/modules/default/weatherforecast/weatherforecast.js @@ -11,7 +11,6 @@ Module.register("weatherforecast",{ // Default module config. defaults: { - autoLocation: false, location: false, locationID: false, appid: "", @@ -96,20 +95,10 @@ Module.register("weatherforecast",{ this.forecast = []; this.loaded = false; + this.scheduleUpdate(this.config.initialLoadDelay); + this.updateTimer = null; - if (this.config.autoLocation) { - this.sendSocketNotification("AUTO_LOCATION"); - } else { - this.scheduleUpdate(this.config.initialLoadDelay); - } - }, - - socketNotificationReceived: function (notification, payload) { - if (notification === "UPDATE_LOCATION") { - this.config.location = payload.location; - this.scheduleUpdate(this.config.initialLoadDelay); - } }, // Override dom generator. diff --git a/package-lock.json b/package-lock.json index 124aa864..d87793e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.7.0-develop", + "version": "2.8.0-develop", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1368,7 +1368,7 @@ "require-from-string": "^2.0.1", "rfc6902": "^2.2.2", "supports-hyperlinks": "^1.0.1", - "vm2": "github:patriksimek/vm2#7e82f90ac705fc44fad044147cb0df09b4c79a57", + "vm2": "github:patriksimek/vm2#custom_files", "voca": "^1.4.0" }, "dependencies": { @@ -1427,6 +1427,11 @@ "requires": { "has-flag": "^2.0.0" } + }, + "vm2": { + "version": "github:patriksimek/vm2#468bc1e54e75e766b842830ea775669992a979e0", + "from": "github:patriksimek/vm2#custom_files", + "dev": true } } }, @@ -2247,7 +2252,7 @@ }, "eventemitter2": { "version": "0.4.14", - "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, @@ -2593,7 +2598,7 @@ }, "findup-sync": { "version": "0.3.0", - "resolved": "http://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", "dev": true, "requires": { @@ -2906,7 +2911,7 @@ }, "grunt-cli": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", "dev": true, "requires": { @@ -4667,9 +4672,9 @@ } }, "moment": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz", - "integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==" + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, "ms": { "version": "2.0.0", @@ -5813,7 +5818,7 @@ }, "require-uncached": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { @@ -5823,7 +5828,7 @@ }, "resolve": { "version": "1.1.7", - "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, @@ -7219,11 +7224,6 @@ "unist-util-stringify-position": "^1.1.1" } }, - "vm2": { - "version": "github:patriksimek/vm2#7e82f90ac705fc44fad044147cb0df09b4c79a57", - "from": "vm2@github:patriksimek/vm2#7e82f90ac705fc44fad044147cb0df09b4c79a57", - "dev": true - }, "voca": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/voca/-/voca-1.4.0.tgz", diff --git a/package.json b/package.json index 3180f70d..37fc0a69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.7.0-develop", + "version": "2.8.0-develop", "description": "The open source modular smart mirror platform.", "main": "js/electron.js", "scripts": { diff --git a/translations/fi.json b/translations/fi.json index aa20759d..495439c1 100644 --- a/translations/fi.json +++ b/translations/fi.json @@ -7,6 +7,8 @@ "RUNNING": "Päättyy {timeUntilEnd} päästä", "EMPTY": "Ei tulevia tapahtumia.", + "WEEK": "Viikko {weekNumber}", + "N": "P", "NNE": "PPI", "NE": "PI", @@ -25,5 +27,7 @@ "NNW": "PPL", "UPDATE_NOTIFICATION": "MagicMirror² päivitys saatavilla.", - "UPDATE_NOTIFICATION_MODULE": "Päivitys saatavilla moduulille {MODULE_NAME}." + "UPDATE_NOTIFICATION_MODULE": "Päivitys saatavilla moduulille {MODULE_NAME}.", + + "FEELS": "Tuntuu kuin" } diff --git a/translations/ru.json b/translations/ru.json index cf2e5c5f..0512e14b 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -25,6 +25,7 @@ "WNW": "ЗСЗ", "NW": "СЗ", "NNW": "ССЗ", + "FEELS": "По ощущению", "UPDATE_NOTIFICATION": "Есть обновление для MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Есть обновление для {MODULE_NAME} модуля.", diff --git a/translations/tlh.json b/translations/tlh.json new file mode 100644 index 00000000..c13f4019 --- /dev/null +++ b/translations/tlh.json @@ -0,0 +1,35 @@ +{ + "LOADING": "loS …", + + "TODAY": "DaHjaj", + "TOMORROW": "wa'leS", + "DAYAFTERTOMORROW": "cha'leS", + "RUNNING": "Dor", + "EMPTY": "Sumbe' wanI'.", + + "WEEK": "Hogh (terran) {weekNumber}", + + "N": "N", + "NNE": "NNE", + "NE": "NE", + "ENE": "ENE", + "E": "chan", + "ESE": "ESE", + "SE": "SE", + "SSE": "SSE", + "S": "S", + "SSW": "SSW", + "SW": "tIng", + "WSW": "WSW", + "W": "W", + "WNW": "WNW", + "NW": "'ev", + "NNW": "NNW", + + "UPDATE_NOTIFICATION": " De'chu' MagicMirror² lI'laH.", + "UPDATE_NOTIFICATION_MODULE": "bobcho' {MODULE_NAME} lI'laH De'chu.", + "UPDATE_INFO_SINGLE": "The current installation is {COMMIT_COUNT} commit behind on the {BRANCH_NAME} branch.", + "UPDATE_INFO_MULTIPLE": "The current installation is {COMMIT_COUNT} commits behind on the {BRANCH_NAME} branch.", + + "FEELS": "jem" +} diff --git a/translations/translations.js b/translations/translations.js index 39bf8d5b..3d719cc3 100644 --- a/translations/translations.js +++ b/translations/translations.js @@ -39,7 +39,8 @@ var translations = { "bg" : "translations/bg.json", // Bulgarian "cs" : "translations/cs.json", // Czech "hr" : "translations/hr.json", // Croatian - "sk" : "translations/sk.json" // Slovak + "sk" : "translations/sk.json", // Slovak + "tlh" : "translations/tlh.json" // Klingon }; if (typeof module !== "undefined") {module.exports = translations;} diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 9ad15ee5..3ce96fc2 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -193,11 +193,6 @@ "repeat-string": "^1.5.2" } }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" - }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -230,7 +225,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -248,11 +244,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -265,15 +263,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -376,7 +377,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -386,6 +388,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -398,17 +401,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -425,6 +431,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -497,7 +504,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -507,6 +515,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -582,7 +591,8 @@ }, "safe-buffer": { "version": "5.1.1", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -612,6 +622,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -629,6 +640,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -667,11 +679,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.2", - "bundled": true + "bundled": true, + "optional": true } } }, @@ -689,6 +703,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "optional": true, "requires": { "is-glob": "^2.0.0" } @@ -702,7 +717,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "optional": true }, "invert-kv": { "version": "1.0.0", @@ -721,7 +737,8 @@ "is-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "optional": true }, "is-dotfile": { "version": "1.0.3", @@ -747,7 +764,8 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -761,6 +779,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -789,7 +808,8 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true }, "isobject": { "version": "2.1.0", @@ -804,6 +824,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "optional": true, "requires": { "is-buffer": "^1.1.5" } @@ -869,6 +890,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "optional": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -1017,12 +1039,14 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "optional": true }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "optional": true }, "repeat-string": { "version": "1.6.1", @@ -1033,7 +1057,8 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "optional": true }, "set-immediate-shim": { "version": "1.0.1",