From a7db8cf7cdb818516b6e3a97f044ce65a44ce302 Mon Sep 17 00:00:00 2001 From: Andrew McOlash Date: Wed, 17 Aug 2016 21:51:48 -0500 Subject: [PATCH 001/120] Humidity data to the current weather module --- modules/default/currentweather/README.md | 11 ++- .../default/currentweather/currentweather.css | 4 + .../default/currentweather/currentweather.js | 85 +++++++++++-------- 3 files changed, 64 insertions(+), 36 deletions(-) diff --git a/modules/default/currentweather/README.md b/modules/default/currentweather/README.md index 2a6f7844..1cafd11a 100644 --- a/modules/default/currentweather/README.md +++ b/modules/default/currentweather/README.md @@ -14,7 +14,7 @@ modules: [ config: { // See 'Configuration options' for more information. location: 'Amsterdam,Netherlands', - locationID: '', //Location ID from http://bulk.openweather.org/sample/ + locationID: '', //Location ID from http://bulk.openweather.org/sample/ appid: 'abcde12345abcde12345abcde12345ab' //openweathermap.org API key. } } @@ -35,7 +35,7 @@ The following properties can be configured: - + location The location used for weather information.
@@ -106,6 +106,13 @@ The following properties can be configured: + showHumidity + Show the current humidity
+
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 diff --git a/modules/default/currentweather/currentweather.css b/modules/default/currentweather/currentweather.css index 9e9d9ed3..08c040d6 100644 --- a/modules/default/currentweather/currentweather.css +++ b/modules/default/currentweather/currentweather.css @@ -6,3 +6,7 @@ -webkit-transform: translate(0, -3px); /* Safari */ transform: translate(0, -3px); } + +.currentweather .humidity-padding { + padding-bottom: 6px; +} diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index db3d5de2..5875c121 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -23,6 +23,7 @@ Module.register("currentweather",{ showWindDirection: true, useBeaufort: true, lang: config.language, + showHumidity: false, initialLoadDelay: 0, // 0 seconds delay retryDelay: 2500, @@ -142,6 +143,21 @@ Module.register("currentweather",{ sunriseSunsetTime.innerHTML = " " + this.sunriseSunsetTime; small.appendChild(sunriseSunsetTime); + wrapper.appendChild(small); + + if (this.config.showHumidity) { + var middle = document.createElement("div"); + middle.className = "normal small humidity-padding"; + + var humidity = document.createElement("span"); + humidity.innerHTML = "Humidity: " + this.humidity + "%"; // TODO: Localization + var br = document.createElement("br"); + + middle.appendChild(humidity); + middle.appendChild(br); + wrapper.appendChild(middle); + } + var large = document.createElement("div"); large.className = "large light"; @@ -154,8 +170,8 @@ Module.register("currentweather",{ temperature.innerHTML = " " + this.temperature + "°"; large.appendChild(temperature); - wrapper.appendChild(small); wrapper.appendChild(large); + return wrapper; }, @@ -224,6 +240,7 @@ Module.register("currentweather",{ return; } + this.humidity = parseFloat(data.main.humidity); this.temperature = this.roundValue(data.main.temp); if (this.config.useBeaufort){ @@ -315,39 +332,39 @@ Module.register("currentweather",{ */ deg2Cardinal: function(deg) { - if (deg>11.25 && deg<=33.75){ - return "NNE"; - } else if (deg > 33.75 && deg <= 56.25) { - return "NE"; - } else if (deg > 56.25 && deg <= 78.75) { - return "ENE"; - } else if (deg > 78.75 && deg <= 101.25) { - return "E"; - } else if (deg > 101.25 && deg <= 123.75) { - return "ESE"; - } else if (deg > 123.75 && deg <= 146.25) { - return "SE"; - } else if (deg > 146.25 && deg <= 168.75) { - return "SSE"; - } else if (deg > 168.75 && deg <= 191.25) { - return "S"; - } else if (deg > 191.25 && deg <= 213.75) { - return "SSW"; - } else if (deg > 213.75 && deg <= 236.25) { - return "SW"; - } else if (deg > 236.25 && deg <= 258.75) { - return "WSW"; - } else if (deg > 258.75 && deg <= 281.25) { - return "W"; - } else if (deg > 281.25 && deg <= 303.75) { - return "WNW"; - } else if (deg > 303.75 && deg <= 326.25) { - return "NW"; - } else if (deg > 326.25 && deg <= 348.75) { - return "NNW"; - } else { - return "N"; - } + if (deg>11.25 && deg<=33.75){ + return "NNE"; + } else if (deg > 33.75 && deg <= 56.25) { + return "NE"; + } else if (deg > 56.25 && deg <= 78.75) { + return "ENE"; + } else if (deg > 78.75 && deg <= 101.25) { + return "E"; + } else if (deg > 101.25 && deg <= 123.75) { + return "ESE"; + } else if (deg > 123.75 && deg <= 146.25) { + return "SE"; + } else if (deg > 146.25 && deg <= 168.75) { + return "SSE"; + } else if (deg > 168.75 && deg <= 191.25) { + return "S"; + } else if (deg > 191.25 && deg <= 213.75) { + return "SSW"; + } else if (deg > 213.75 && deg <= 236.25) { + return "SW"; + } else if (deg > 236.25 && deg <= 258.75) { + return "WSW"; + } else if (deg > 258.75 && deg <= 281.25) { + return "W"; + } else if (deg > 281.25 && deg <= 303.75) { + return "WNW"; + } else if (deg > 303.75 && deg <= 326.25) { + return "NW"; + } else if (deg > 326.25 && deg <= 348.75) { + return "NNW"; + } else { + return "N"; + } }, From c6f424201b7b3fe9d8d444250937074d1179eee7 Mon Sep 17 00:00:00 2001 From: Andrew McOlash Date: Thu, 18 Aug 2016 09:32:19 -0500 Subject: [PATCH 002/120] Fix indentation and spacing --- modules/default/currentweather/README.md | 6 +- .../default/currentweather/currentweather.js | 67 +++++++++---------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/modules/default/currentweather/README.md b/modules/default/currentweather/README.md index 1cafd11a..3df88173 100644 --- a/modules/default/currentweather/README.md +++ b/modules/default/currentweather/README.md @@ -14,7 +14,7 @@ modules: [ config: { // See 'Configuration options' for more information. location: 'Amsterdam,Netherlands', - locationID: '', //Location ID from http://bulk.openweather.org/sample/ + locationID: '', //Location ID from http://bulk.openweather.org/sample/ appid: 'abcde12345abcde12345abcde12345ab' //openweathermap.org API key. } } @@ -35,7 +35,7 @@ The following properties can be configured: - + location The location used for weather information.
@@ -112,7 +112,7 @@ The following properties can be configured:
Default value: false - + useBeaufort Pick between using the Beaufort scale for wind speed or using the default units.

Possible values: true or false diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index 5875c121..57884ad7 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -171,7 +171,6 @@ Module.register("currentweather",{ large.appendChild(temperature); wrapper.appendChild(large); - return wrapper; }, @@ -332,39 +331,39 @@ Module.register("currentweather",{ */ deg2Cardinal: function(deg) { - if (deg>11.25 && deg<=33.75){ - return "NNE"; - } else if (deg > 33.75 && deg <= 56.25) { - return "NE"; - } else if (deg > 56.25 && deg <= 78.75) { - return "ENE"; - } else if (deg > 78.75 && deg <= 101.25) { - return "E"; - } else if (deg > 101.25 && deg <= 123.75) { - return "ESE"; - } else if (deg > 123.75 && deg <= 146.25) { - return "SE"; - } else if (deg > 146.25 && deg <= 168.75) { - return "SSE"; - } else if (deg > 168.75 && deg <= 191.25) { - return "S"; - } else if (deg > 191.25 && deg <= 213.75) { - return "SSW"; - } else if (deg > 213.75 && deg <= 236.25) { - return "SW"; - } else if (deg > 236.25 && deg <= 258.75) { - return "WSW"; - } else if (deg > 258.75 && deg <= 281.25) { - return "W"; - } else if (deg > 281.25 && deg <= 303.75) { - return "WNW"; - } else if (deg > 303.75 && deg <= 326.25) { - return "NW"; - } else if (deg > 326.25 && deg <= 348.75) { - return "NNW"; - } else { - return "N"; - } + if (deg>11.25 && deg<=33.75){ + return "NNE"; + } else if (deg > 33.75 && deg <= 56.25) { + return "NE"; + } else if (deg > 56.25 && deg <= 78.75) { + return "ENE"; + } else if (deg > 78.75 && deg <= 101.25) { + return "E"; + } else if (deg > 101.25 && deg <= 123.75) { + return "ESE"; + } else if (deg > 123.75 && deg <= 146.25) { + return "SE"; + } else if (deg > 146.25 && deg <= 168.75) { + return "SSE"; + } else if (deg > 168.75 && deg <= 191.25) { + return "S"; + } else if (deg > 191.25 && deg <= 213.75) { + return "SSW"; + } else if (deg > 213.75 && deg <= 236.25) { + return "SW"; + } else if (deg > 236.25 && deg <= 258.75) { + return "WSW"; + } else if (deg > 258.75 && deg <= 281.25) { + return "W"; + } else if (deg > 281.25 && deg <= 303.75) { + return "WNW"; + } else if (deg > 303.75 && deg <= 326.25) { + return "NW"; + } else if (deg > 326.25 && deg <= 348.75) { + return "NNW"; + } else { + return "N"; + } }, From b90f1f786efbf34f80842cb29f2982ec710f2f75 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 24 Aug 2016 08:51:49 +0200 Subject: [PATCH 003/120] Update nl.json Corrected typo --- translations/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/nl.json b/translations/nl.json index ab84807b..c6094a3c 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -5,7 +5,7 @@ /* CALENDAR */ "TODAY": "Vandaag", "TOMORROW": "Morgen", - "RUNNING": "Eindigd over", + "RUNNING": "Eindigt over", "EMPTY": "Geen geplande afspraken.", /* WEATHER */ From 45cb770e41cbdd4a4af9501a7b8ccb3289d31e73 Mon Sep 17 00:00:00 2001 From: yo-less Date: Fri, 26 Aug 2016 22:06:03 +0200 Subject: [PATCH 004/120] Added option to remove "more" tags in description Many feed descriptions end with with a link tag to the actual article online (see http://www.deutschlandfunk.de/die-nachrichten.353.de.rss, for example). The mirror news description looks strange with this tag in the end. I have added an option to remove the tag from the description and updated the readme.md accordingly. --- modules/default/newsfeed/README.md | 15 ++++++++++++++- modules/default/newsfeed/newsfeed.js | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index 882ef94a..365d8a6e 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -108,7 +108,20 @@ The following properties can be configured:
Default value: 0 - + + showMore + Remove "more..." tags from the end of the item description.
+
Possible values:true or false +
Default value: false + + + + moreTag + Specify the exact wording of the "more..." tag.
+
Possible values: 'YOUR_MORE_TAG_HERE' +
Default value: '' + + diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index a9664085..5a6c8b70 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -24,7 +24,9 @@ Module.register("newsfeed",{ reloadInterval: 5 * 60 * 1000, // every 5 minutes updateInterval: 10 * 1000, animationSpeed: 2.5 * 1000, - maxNewsItems: 0 // 0 for unlimited + maxNewsItems: 0, // 0 for unlimited + more: false, + moreTag: 'more' }, // Define required scripts. @@ -100,7 +102,16 @@ Module.register("newsfeed",{ title.className = "bright medium light"; title.innerHTML = this.newsItems[this.activeItem].title; wrapper.appendChild(title); - + + //Remove "more" tag from description of rss feeds + + if (this.config.showMore) { + if (this.newsItems[this.activeItem].description.slice(-this.config.moreTag.length)==this.config.moreTag) { + this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(0,-this.config.moreTag.length); + } + } + + if (this.config.showDescription) { var description = document.createElement("div"); description.className = "small light"; From e720efabdcbd9b99bb726d97c378a80588d2ae52 Mon Sep 17 00:00:00 2001 From: yo-less Date: Fri, 26 Aug 2016 22:08:23 +0200 Subject: [PATCH 005/120] Updated readme.md / Included more tag --- modules/default/newsfeed/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index 365d8a6e..e2a4c6f1 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -119,7 +119,7 @@ The following properties can be configured: moreTag Specify the exact wording of the "more..." tag.

Possible values: 'YOUR_MORE_TAG_HERE' -
Default value: '' +
Default value: 'more' From 6f104f505609c13637a3182d10f6ea29a4111331 Mon Sep 17 00:00:00 2001 From: yo-less Date: Sat, 27 Aug 2016 00:32:47 +0200 Subject: [PATCH 006/120] Allow for the removal of feed tags User-specified feed tags in description and title can be removed --- modules/default/newsfeed/README.md | 33 +++++++++++---- modules/default/newsfeed/newsfeed.js | 61 ++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index e2a4c6f1..12fe8e7c 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -108,18 +108,35 @@ The following properties can be configured:
Default value: 0 + removeStartTags: false, + removeEndTags: false, + startTags: [], + endTags: [] + + - showMore - Remove "more..." tags from the end of the item description.
-
Possible values:true or false -
Default value: false + removeStartTags + Some newsfeeds feature tags at the beginning of their titles or descriptions, such as "[VIDEO]". + This setting allows for the removal of specified tags from the beginning of an item's description and / or title.
+
Possible values:'none',description, title, both - moreTag - Specify the exact wording of the "more..." tag.
-
Possible values: 'YOUR_MORE_TAG_HERE' -
Default value: 'more' + startTags + List the tags you would like to have removed at the beginning of the feed item
+
Possible values: ['TAG'] or ['TAG1','TAG2',...] + + + + removeEndTags + Remove specified tags from the end of an item's description and / or title.
+
Possible values:description, title, both + + + + endTags + List the tags you would like to have removed at the end of the feed item
+
Possible values: ['TAG'] or ['TAG1','TAG2',...] diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 5a6c8b70..a61ba640 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -25,8 +25,11 @@ Module.register("newsfeed",{ updateInterval: 10 * 1000, animationSpeed: 2.5 * 1000, maxNewsItems: 0, // 0 for unlimited - more: false, - moreTag: 'more' + removeStartTags: false, + removeEndTags: false, + startTags: [], + endTags: [] + }, // Define required scripts. @@ -98,20 +101,50 @@ Module.register("newsfeed",{ wrapper.appendChild(sourceAndTimestamp); } + //Remove selected tags from the beginning of rss feed items (title or description) + + if (this.config.removeStartTags) { + + for (f=0; f Date: Sat, 27 Aug 2016 00:35:27 +0200 Subject: [PATCH 007/120] Allow for removal of feed tags Updated README.md for legibility --- modules/default/newsfeed/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index 12fe8e7c..1815e567 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -116,8 +116,8 @@ The following properties can be configured: removeStartTags - Some newsfeeds feature tags at the beginning of their titles or descriptions, such as "[VIDEO]". - This setting allows for the removal of specified tags from the beginning of an item's description and / or title.
+ Some newsfeeds feature tags at the beginning of their titles or descriptions, such as VIDEO. + This setting allows for the removal of specified tags from the beginning of an item's description and/or title.

Possible values:'none',description, title, both @@ -129,7 +129,7 @@ The following properties can be configured: removeEndTags - Remove specified tags from the end of an item's description and / or title.
+ Remove specified tags from the end of an item's description and/or title.

Possible values:description, title, both From 43a0829f44aa64a6edb45831ed4b25d8af2b41ff Mon Sep 17 00:00:00 2001 From: yo-less Date: Sat, 27 Aug 2016 00:37:19 +0200 Subject: [PATCH 008/120] Allow for the removal of feed tags legibility update --- modules/default/newsfeed/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index 1815e567..a8ac40dd 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -116,7 +116,7 @@ The following properties can be configured: removeStartTags - Some newsfeeds feature tags at the beginning of their titles or descriptions, such as VIDEO. + Some newsfeeds feature tags at the beginning of their titles or descriptions, such as [VIDEO]. This setting allows for the removal of specified tags from the beginning of an item's description and/or title.

Possible values:'none',description, title, both @@ -124,7 +124,7 @@ The following properties can be configured: startTags List the tags you would like to have removed at the beginning of the feed item
-
Possible values: ['TAG'] or ['TAG1','TAG2',...] +
Possible values: ['TAG'] or ['TAG1','TAG2',...] @@ -136,7 +136,7 @@ The following properties can be configured: endTags List the tags you would like to have removed at the end of the feed item
-
Possible values: ['TAG'] or ['TAG1','TAG2',...] +
Possible values: ['TAG'] or ['TAG1','TAG2',...] From c427050a92be5c2fea16281c91798260b62a4049 Mon Sep 17 00:00:00 2001 From: yo-less Date: Sat, 27 Aug 2016 01:16:31 +0200 Subject: [PATCH 009/120] Allow for the removal of feed tags Added options: both, description, title --- modules/default/newsfeed/newsfeed.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index a61ba640..7d8d08c7 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -25,8 +25,8 @@ Module.register("newsfeed",{ updateInterval: 10 * 1000, animationSpeed: 2.5 * 1000, maxNewsItems: 0, // 0 for unlimited - removeStartTags: false, - removeEndTags: false, + removeStartTags: '', + removeEndTags: '', startTags: [], endTags: [] @@ -103,7 +103,7 @@ Module.register("newsfeed",{ //Remove selected tags from the beginning of rss feed items (title or description) - if (this.config.removeStartTags) { + if (this.config.removeStartTags == 'title' || 'both') { for (f=0; f Date: Sat, 27 Aug 2016 12:59:00 +0200 Subject: [PATCH 010/120] Updated README.md Fixed inconsistencies in tag removal instructions. --- modules/default/newsfeed/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index a8ac40dd..f88322c4 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -118,7 +118,7 @@ The following properties can be configured: removeStartTags Some newsfeeds feature tags at the beginning of their titles or descriptions, such as [VIDEO]. This setting allows for the removal of specified tags from the beginning of an item's description and/or title.
-
Possible values:'none',description, title, both +
Possible values:'title', 'description', 'both' From a08704e8edf0772f660b4fb93586a346cc473531 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 27 Aug 2016 13:12:08 +0200 Subject: [PATCH 011/120] Updated CHANGELOG.md Added tag removal description for newsfeed items --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df710e02..243b7d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Updated - Force fullscreen when kioskmode is active. +- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js' ## [2.0.4] - 2016-08-07 From d248b11ffc876d0107fd2fc3f785b3f8be4a922d Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 27 Aug 2016 13:48:33 +0200 Subject: [PATCH 012/120] Updated README.md Fixed inconsistencies in tag removal instructions. --- modules/default/newsfeed/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index f88322c4..89e3fd1b 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -130,7 +130,7 @@ The following properties can be configured: removeEndTags Remove specified tags from the end of an item's description and/or title.
-
Possible values:description, title, both +
Possible values:'title', 'description', 'both' From bf5587fe09e9aa80ee30b10aaa2cf7645001c6de Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 27 Aug 2016 20:35:00 +0200 Subject: [PATCH 013/120] Updated README.md Fixed minor typo --- modules/default/calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 05d12de8..3189d92c 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -173,7 +173,7 @@ config: { symbol The symbol to show in front of an event. This property is optional.
-
Possible values: See Font Awsome website. +
Possible values: See Font Awesome website. From a592ca25ffb7a578f36981e77ce27b16a47048d1 Mon Sep 17 00:00:00 2001 From: Andrew McOlash Date: Sun, 28 Aug 2016 01:52:08 -0500 Subject: [PATCH 014/120] Add in icon for the current humidity --- modules/default/currentweather/currentweather.css | 4 ++++ modules/default/currentweather/currentweather.js | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/default/currentweather/currentweather.css b/modules/default/currentweather/currentweather.css index 08c040d6..768b0f8d 100644 --- a/modules/default/currentweather/currentweather.css +++ b/modules/default/currentweather/currentweather.css @@ -7,6 +7,10 @@ transform: translate(0, -3px); } +.currentweather .humidityIcon { + padding-right: 8px; +} + .currentweather .humidity-padding { padding-bottom: 6px; } diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index 57884ad7..87e4d04a 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -149,10 +149,15 @@ Module.register("currentweather",{ var middle = document.createElement("div"); middle.className = "normal small humidity-padding"; + var humidityIcon = document.createElement("span"); + humidityIcon.className = "wi wi-humidity humidityIcon"; + small.appendChild(sunriseSunsetIcon); + var humidity = document.createElement("span"); - humidity.innerHTML = "Humidity: " + this.humidity + "%"; // TODO: Localization + humidity.innerHTML = this.humidity + "%"; var br = document.createElement("br"); + middle.appendChild(humidityIcon); middle.appendChild(humidity); middle.appendChild(br); wrapper.appendChild(middle); From 853fa870121f89905ab8e8bebb676cceb3e876bb Mon Sep 17 00:00:00 2001 From: Andrew McOlash Date: Sun, 28 Aug 2016 01:58:56 -0500 Subject: [PATCH 015/120] Slight change to padding of humidity icon, just too much before --- modules/default/currentweather/currentweather.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/currentweather/currentweather.css b/modules/default/currentweather/currentweather.css index 768b0f8d..a40be878 100644 --- a/modules/default/currentweather/currentweather.css +++ b/modules/default/currentweather/currentweather.css @@ -8,7 +8,7 @@ } .currentweather .humidityIcon { - padding-right: 8px; + padding-right: 4px; } .currentweather .humidity-padding { From 177d113cd9224e53674186bfd24e3cfb7c534d98 Mon Sep 17 00:00:00 2001 From: Platimir Date: Tue, 30 Aug 2016 15:57:52 +0200 Subject: [PATCH 016/120] Update README.md --- modules/default/newsfeed/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index 89e3fd1b..951fa51c 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -98,7 +98,7 @@ The following properties can be configured: animationSpeed Speed of the update animation. (Milliseconds)

Possible values:0 - 5000 -
Default value: 2000 (2.5 seconds) +
Default value: 2000 (2 seconds) From 1b69e62e2e25497959614bb3e0d83b5af05659ce Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 31 Aug 2016 14:39:37 +0200 Subject: [PATCH 017/120] Added "DAYAFTERTOMORROW" tag if config language is German --- modules/default/calendar/calendar.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index c90153a0..cf2c97cb 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -150,6 +150,12 @@ Module.register("calendar",{ timeWrapper.innerHTML = this.translate("TODAY"); } else if (event.startDate - now < one_day && event.startDate - now > 0) { timeWrapper.innerHTML = this.translate("TOMORROW"); + } else if (event.startDate - now < 2*one_day && event.startDate - now > 0) { + if (config.language == 'de') { + timeWrapper.innerHTML = this.translate("DAYAFTERTOMORROW"); + } else { + timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + } } else { /* Check to see if the user displays absolute or relative dates with their events * Also check to see if an event is happening within an 'urgency' time frameElement From 76d6dca63fdafea8128bfa9d9d91b3da655ef183 Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 31 Aug 2016 14:41:49 +0200 Subject: [PATCH 018/120] =?UTF-8?q?Added=20"=C3=9Cbermorgen"=20to=20show?= =?UTF-8?q?=20in=20calendar.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/de.json | 1 + 1 file changed, 1 insertion(+) diff --git a/translations/de.json b/translations/de.json index d4c20d10..d8a254a9 100644 --- a/translations/de.json +++ b/translations/de.json @@ -5,6 +5,7 @@ /* CALENDAR */ "TODAY": "Heute", "TOMORROW": "Morgen", + "DAYAFTERTOMORROW": "Übermorgen", "RUNNING": "noch", "EMPTY": "Keine Termine.", From f5be159187e63f11dc3a879aeaaf6a9091794b76 Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 31 Aug 2016 22:11:31 +0200 Subject: [PATCH 019/120] Added "DAYAFTERTOMORROW" tag if available --- modules/default/calendar/calendar.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index cf2c97cb..d4871338 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -151,10 +151,14 @@ Module.register("calendar",{ } else if (event.startDate - now < one_day && event.startDate - now > 0) { timeWrapper.innerHTML = this.translate("TOMORROW"); } else if (event.startDate - now < 2*one_day && event.startDate - now > 0) { - if (config.language == 'de') { - timeWrapper.innerHTML = this.translate("DAYAFTERTOMORROW"); + /*Provide ability to show "the day after tomorrow" instead of "in a day" + *if "DAYAFTERTOMORROW" is configured in a language's translation .json file, + *,which can be found in MagicMirror/translations/ + */ + if (this.translate('DAYAFTERTOMORROW') !== 'DAYAFTERTOMORROW') { + timeWrapper.innerHTML = this.translate("DAYAFTERTOMORROW"); } else { - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); } } else { /* Check to see if the user displays absolute or relative dates with their events From 88266ec4e302fcbdce43b5f770e411dc2b2e8d7e Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 31 Aug 2016 22:17:43 +0200 Subject: [PATCH 020/120] Added "day after tomorrow" changes to calendar.js --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c76d0362..e9e14d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## Unpublished + +### Updated +- Force fullscreen when kioskmode is active. + +### Added +- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js' +- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included) + ## [2.0.4] - 2016-08-07 ### Added From 104c1ecbec9815d87d1b9740dfbe3b35bd9544d7 Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 31 Aug 2016 22:18:30 +0200 Subject: [PATCH 021/120] Added "day after tomorrow" changes to calendar.js --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9e14d7b..661eda5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Force fullscreen when kioskmode is active. ### Added -- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js' -- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included) +- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. +- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included). ## [2.0.4] - 2016-08-07 From 3d97e26cde73e7bc6d0a1fa6317842c6cbe485fe Mon Sep 17 00:00:00 2001 From: Jens Date: Wed, 31 Aug 2016 22:40:50 +0200 Subject: [PATCH 022/120] Delete CHANGELOG.md --- CHANGELOG.md | 83 ---------------------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 661eda5f..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,83 +0,0 @@ -# MagicMirror² Change Log -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -## Unpublished - -### Updated -- Force fullscreen when kioskmode is active. - -### Added -- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. -- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included). - -## [2.0.4] - 2016-08-07 - -### Added -- Brazilian Portuguese Translation. -- Option to enable Kios mode. -- Added ability to start the app with Dev Tools. -- Added ability to turn off the date display in `clock.js` when in analog mode. -- Greek Translation - -### 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'. -- 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)) - -### Updated -- Updated package.json to fix possible vulnerabilities. (Using Snyk) -- Updated weathericons -- Updated default weatherforecast to work with the new icons. -- More detailed error message in case config file couldn't be loaded. - -## [2.0.3] - 2016-07-12 -### Added -- Add max newsitems parameter to the newsfeed module. -- Translations for Simplified Chinese, Traditional Chinese and Japanese. -- Polish Translation -- Add an analog clock in addition to the digital one. - -### Fixed -- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300)) -- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319)) - -### Changed -- Added default string to calendar titleReplace. - -## [2.0.2] - 2016-06-05 -### Added -- Norwegian Translations (nb and nn) -- Portuguese Translation -- Swedish Translation - -### Fixed -- Added reference to Italian Translation. -- Added the missing NE translation to all languages. [#334](https://github.com/MichMich/MagicMirror/issues/344) -- Added proper User-Agent string to calendar call. - -### Changed -- Add option to use locationID in weather modules. - -## [2.0.1] - 2016-05-18 -### Added -- Changelog -- Italian Translation - -### Changed -- Improve the installer by fetching the latest Node.js without any 3rd party interferences. - -## [2.0.0] - 2016-05-03 -### Initial release of MagicMirror² -It includes (but is not limited to) the following features: -- Modular system allowing 3rd party plugins. -- An Node/Electron based application taking away the need for external servers or browsers. -- A complete development API documentation. -- Small cute fairies that kiss you while you sleep. - -## [1.0.0] - 2014-02-16 -### Initial release of MagicMirror. -This was part of the blogpost: http://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the From 91dd308952308aeeaad7b4fe66dbf0b94e5b139e Mon Sep 17 00:00:00 2001 From: yo-less Date: Wed, 31 Aug 2016 22:43:27 +0200 Subject: [PATCH 023/120] Added 'day after tomorrow' changes to calendar.js --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 661eda5f..64afe07c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## Unpublished ### Updated -- Force fullscreen when kioskmode is active. +- Force fullscreen when kioskmode is active. ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. From 1bba75881f396873dd00274c4b5a7e78272e90bb Mon Sep 17 00:00:00 2001 From: yo-less Date: Wed, 31 Aug 2016 22:46:54 +0200 Subject: [PATCH 024/120] Added 'day after tomorrow'changes to calendar.js --- CHANGELOG.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..64afe07c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,83 @@ +# MagicMirror² Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## Unpublished + +### Updated +- Force fullscreen when kioskmode is active. + +### Added +- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. +- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included). + +## [2.0.4] - 2016-08-07 + +### Added +- Brazilian Portuguese Translation. +- Option to enable Kios mode. +- Added ability to start the app with Dev Tools. +- Added ability to turn off the date display in `clock.js` when in analog mode. +- Greek Translation + +### 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'. +- 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)) + +### Updated +- Updated package.json to fix possible vulnerabilities. (Using Snyk) +- Updated weathericons +- Updated default weatherforecast to work with the new icons. +- More detailed error message in case config file couldn't be loaded. + +## [2.0.3] - 2016-07-12 +### Added +- Add max newsitems parameter to the newsfeed module. +- Translations for Simplified Chinese, Traditional Chinese and Japanese. +- Polish Translation +- Add an analog clock in addition to the digital one. + +### Fixed +- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300)) +- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319)) + +### Changed +- Added default string to calendar titleReplace. + +## [2.0.2] - 2016-06-05 +### Added +- Norwegian Translations (nb and nn) +- Portuguese Translation +- Swedish Translation + +### Fixed +- Added reference to Italian Translation. +- Added the missing NE translation to all languages. [#334](https://github.com/MichMich/MagicMirror/issues/344) +- Added proper User-Agent string to calendar call. + +### Changed +- Add option to use locationID in weather modules. + +## [2.0.1] - 2016-05-18 +### Added +- Changelog +- Italian Translation + +### Changed +- Improve the installer by fetching the latest Node.js without any 3rd party interferences. + +## [2.0.0] - 2016-05-03 +### Initial release of MagicMirror² +It includes (but is not limited to) the following features: +- Modular system allowing 3rd party plugins. +- An Node/Electron based application taking away the need for external servers or browsers. +- A complete development API documentation. +- Small cute fairies that kiss you while you sleep. + +## [1.0.0] - 2014-02-16 +### Initial release of MagicMirror. +This was part of the blogpost: http://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the From f795ee7fd90cd7b31392ed36366321d7e9a21aa7 Mon Sep 17 00:00:00 2001 From: yo-less Date: Wed, 31 Aug 2016 22:46:54 +0200 Subject: [PATCH 025/120] Added "day after tomorrow" changes to calendar.js --- CHANGELOG.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..64afe07c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,83 @@ +# MagicMirror² Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## Unpublished + +### Updated +- Force fullscreen when kioskmode is active. + +### Added +- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. +- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included). + +## [2.0.4] - 2016-08-07 + +### Added +- Brazilian Portuguese Translation. +- Option to enable Kios mode. +- Added ability to start the app with Dev Tools. +- Added ability to turn off the date display in `clock.js` when in analog mode. +- Greek Translation + +### 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'. +- 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)) + +### Updated +- Updated package.json to fix possible vulnerabilities. (Using Snyk) +- Updated weathericons +- Updated default weatherforecast to work with the new icons. +- More detailed error message in case config file couldn't be loaded. + +## [2.0.3] - 2016-07-12 +### Added +- Add max newsitems parameter to the newsfeed module. +- Translations for Simplified Chinese, Traditional Chinese and Japanese. +- Polish Translation +- Add an analog clock in addition to the digital one. + +### Fixed +- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300)) +- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319)) + +### Changed +- Added default string to calendar titleReplace. + +## [2.0.2] - 2016-06-05 +### Added +- Norwegian Translations (nb and nn) +- Portuguese Translation +- Swedish Translation + +### Fixed +- Added reference to Italian Translation. +- Added the missing NE translation to all languages. [#334](https://github.com/MichMich/MagicMirror/issues/344) +- Added proper User-Agent string to calendar call. + +### Changed +- Add option to use locationID in weather modules. + +## [2.0.1] - 2016-05-18 +### Added +- Changelog +- Italian Translation + +### Changed +- Improve the installer by fetching the latest Node.js without any 3rd party interferences. + +## [2.0.0] - 2016-05-03 +### Initial release of MagicMirror² +It includes (but is not limited to) the following features: +- Modular system allowing 3rd party plugins. +- An Node/Electron based application taking away the need for external servers or browsers. +- A complete development API documentation. +- Small cute fairies that kiss you while you sleep. + +## [1.0.0] - 2014-02-16 +### Initial release of MagicMirror. +This was part of the blogpost: http://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the From a481638c030c1e1ac750aae0bc1beccb45e5c11e Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 1 Sep 2016 09:42:33 +0200 Subject: [PATCH 026/120] Add dutch translation --- CHANGELOG.md | 2 +- translations/nl.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 661eda5f..1e2cda42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. -- Added ability to define "the day after tomorrow" for calendar events (Definition for German already included). +- Added ability to define "the day after tomorrow" for calendar events (Definition for German and Dutch already included). ## [2.0.4] - 2016-08-07 diff --git a/translations/nl.json b/translations/nl.json index c6094a3c..e4e882ea 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -5,6 +5,7 @@ /* CALENDAR */ "TODAY": "Vandaag", "TOMORROW": "Morgen", + "DAYAFTERTOMORROW": "Overmorgen", "RUNNING": "Eindigt over", "EMPTY": "Geen geplande afspraken.", From c1b8fc123350f6a14f845b69f31529d18d81d002 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 00:39:46 +0200 Subject: [PATCH 027/120] calendar dates are uniformly capitalized This is an attempt at standardizing the calendar layout. Currently the calendar times are only partly capitalized, some time phrases start with lower-case letters, some don't (The ones pulled from the TRANSLATIONS folder start with upper-case letters, the others don't). Behavior has been changed to create a more standardized layout. --- modules/default/calendar/calendar.js | 39 ++++++++++++++++------------ 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index d4871338..9b83e3c5 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -147,18 +147,14 @@ Module.register("calendar",{ var one_day = one_hour * 24; if (event.fullDayEvent) { if (event.today) { - timeWrapper.innerHTML = this.translate("TODAY"); + timeWrapper.innerHTML = this.capFirst(this.translate("TODAY")); } else if (event.startDate - now < one_day && event.startDate - now > 0) { - timeWrapper.innerHTML = this.translate("TOMORROW"); + timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW")); } else if (event.startDate - now < 2*one_day && event.startDate - now > 0) { - /*Provide ability to show "the day after tomorrow" instead of "in a day" - *if "DAYAFTERTOMORROW" is configured in a language's translation .json file, - *,which can be found in MagicMirror/translations/ - */ if (this.translate('DAYAFTERTOMORROW') !== 'DAYAFTERTOMORROW') { - timeWrapper.innerHTML = this.translate("DAYAFTERTOMORROW"); + timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); } else { - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } else { /* Check to see if the user displays absolute or relative dates with their events @@ -171,12 +167,12 @@ Module.register("calendar",{ if (this.config.timeFormat === "absolute") { if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * one_day))) { // This event falls within the config.urgency period that the user has set - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { - timeWrapper.innerHTML = moment(event.startDate, "x").format("MMM Do"); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format("MMM Do")); } } else { - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } } else { @@ -185,10 +181,10 @@ Module.register("calendar",{ // This event is within the next 48 hours (2 days) if (event.startDate - now < 6 * one_hour) { // If event is within 6 hour, display 'in xxx' time format or moment.fromNow() - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { // Otherwise just say 'Today/Tomorrow at such-n-such time' - timeWrapper.innerHTML = moment(event.startDate, "x").calendar(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar()); } } else { /* Check to see if the user displays absolute or relative dates with their events @@ -201,16 +197,16 @@ Module.register("calendar",{ if (this.config.timeFormat === "absolute") { if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * one_day))) { // This event falls within the config.urgency period that the user has set - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { - timeWrapper.innerHTML = moment(event.startDate, "x").format("MMM Do"); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format("MMM Do")); } } else { - timeWrapper.innerHTML = moment(event.startDate, "x").fromNow(); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } } else { - timeWrapper.innerHTML = this.translate("RUNNING") + ' ' + moment(event.endDate,"x").fromNow(true); + timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + ' ' + this.capFirst(moment(event.endDate,"x").fromNow(true)); } } //timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll'); @@ -346,6 +342,15 @@ Module.register("calendar",{ return string; }, + /* capFirst(string) + * Capitalize the first letter of a string + * Eeturn capitalized string + */ + + capFirst: function(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + /* titleTransform(title) * Transforms the title of an event for usage. * Replaces parts of the text as defined in config.titleReplace. From c3f97a0cf1360bb8487feb04d4782350cf42d632 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Fri, 2 Sep 2016 21:58:22 -0400 Subject: [PATCH 028/120] Add CII Badge, Remove Node Version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d5f7176..0b9e00ed 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

Dependency Status devDependency Status - Node Version + License Travis Known Vulnerabilities From a4ba7f277e94b7f014fa8350c71d754892e3b079 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Fri, 2 Sep 2016 22:00:37 -0400 Subject: [PATCH 029/120] Add Change to Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e2cda42..b87473dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. - 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) ## [2.0.4] - 2016-08-07 From 8f4effbb8df33e01e276936455a7158c192b2ad3 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:17:46 +0200 Subject: [PATCH 030/120] poinst of time when calendar event gets relative now customizable --- modules/default/calendar/calendar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 9b83e3c5..31395c4f 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -23,6 +23,7 @@ Module.register("calendar",{ fade: true, urgency: 7, timeFormat: "relative", + getRelative: '6', fadePoint: 0.25, // Start on 1/4th of the list. calendars: [ { @@ -179,7 +180,7 @@ Module.register("calendar",{ if (event.startDate >= new Date()) { if (event.startDate - now < 2 * one_day) { // This event is within the next 48 hours (2 days) - if (event.startDate - now < 6 * one_hour) { + if (event.startDate - now < this.config.getRelative * one_hour) { // If event is within 6 hour, display 'in xxx' time format or moment.fromNow() timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { From 4ca185cf45fedbf5eac85ec0d79c61ac9653c20a Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:22:37 +0200 Subject: [PATCH 031/120] point of time when calendar event gets relative now customizable --- modules/default/calendar/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 31395c4f..e4827b10 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -21,7 +21,7 @@ Module.register("calendar",{ fetchInterval: 5 * 60 * 1000, // Update every 5 minutes. animationSpeed: 2000, fade: true, - urgency: 7, + urgency: 7, timeFormat: "relative", getRelative: '6', fadePoint: 0.25, // Start on 1/4th of the list. From 493367da5ea73a4b54fb3f7efe49c15b64d325dc Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:22:51 +0200 Subject: [PATCH 032/120] point of time when calendar event gets relative now customizable --- modules/default/calendar/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index e4827b10..31395c4f 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -21,7 +21,7 @@ Module.register("calendar",{ fetchInterval: 5 * 60 * 1000, // Update every 5 minutes. animationSpeed: 2000, fade: true, - urgency: 7, + urgency: 7, timeFormat: "relative", getRelative: '6', fadePoint: 0.25, // Start on 1/4th of the list. From f47b8084787bc3a398a067c78e3b9eb0569292d2 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:28:07 +0200 Subject: [PATCH 033/120] Added calendar.js tweaks (capitalization / 'getRelative' tag) --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e2cda42..63acbfa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. - Added ability to define "the day after tomorrow" for calendar events (Definition for German and Dutch already included). +- Added ability to change the point of time when calendar events get relative. + +### Changed +- Calendar times are now uniformly capitalized + ## [2.0.4] - 2016-08-07 From c4c8955bc28cf9276c6d48116b7b69b56c01d1d8 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:36:29 +0200 Subject: [PATCH 034/120] Added 'getRelative' tag --- modules/default/calendar/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 3189d92c..2a9573d0 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -126,6 +126,13 @@ The following properties can be configured:
Default value: relative + + getRelative + Determine how much time (in hours) should be left when calendar events start getting relative (If you want this to start half an hour before an event occurs)
+
Possible values: 0 (never) - 48 (48 hours before the event) +
Default value: 6 + + urgency When using a timeFormat of absolute, the urgency setting allows you to display events within a specific time frame as relative From 4e47f9eb6831022d8f5c38aaaf57d90a7badb532 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:37:09 +0200 Subject: [PATCH 035/120] Added 'getRelative' tag --- modules/default/calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 2a9573d0..5bd3aceb 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -129,7 +129,7 @@ The following properties can be configured: getRelative Determine how much time (in hours) should be left when calendar events start getting relative (If you want this to start half an hour before an event occurs)
-
Possible values: 0 (never) - 48 (48 hours before the event) +
Possible values: 0 (never) - 48 (48 hours before the event)
Default value: 6 From e1fa5fb18044c458e390781d9ebbb5d379934e44 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:39:32 +0200 Subject: [PATCH 036/120] Added 'getRelative' tag --- modules/default/calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 5bd3aceb..1f22dae4 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -128,7 +128,7 @@ The following properties can be configured: getRelative - Determine how much time (in hours) should be left when calendar events start getting relative (If you want this to start half an hour before an event occurs)
+ Determine how much time (in hours) should be left until calendar events start getting relative

Possible values: 0 (never) - 48 (48 hours before the event)
Default value: 6 From 2dfdedf7b0accd2132a48849fba58f9e4984be26 Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:40:29 +0200 Subject: [PATCH 037/120] Update README.md --- modules/default/calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 1f22dae4..01dc6645 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -129,7 +129,7 @@ The following properties can be configured: getRelative Determine how much time (in hours) should be left until calendar events start getting relative
-
Possible values: 0 (never) - 48 (48 hours before the event) +
Possible values: 0 (events stay absolute) - 48 (48 hours before the event starts)
Default value: 6 From 0ff4884d3a2519dc1fa3caea547c8f1ad763371b Mon Sep 17 00:00:00 2001 From: Jens Date: Sat, 3 Sep 2016 23:42:24 +0200 Subject: [PATCH 038/120] Added 'getRelative' tag --- modules/default/calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 01dc6645..611c6be4 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -128,7 +128,7 @@ The following properties can be configured: getRelative - Determine how much time (in hours) should be left until calendar events start getting relative
+ How much time (in hours) should be left until calendar events start getting relative?

Possible values: 0 (events stay absolute) - 48 (48 hours before the event starts)
Default value: 6 From 4630740ac7d6baf1adf22128102066f833ebef3a Mon Sep 17 00:00:00 2001 From: Jens Date: Sun, 4 Sep 2016 00:05:02 +0200 Subject: [PATCH 039/120] Added 'getRelative' tag --- modules/default/calendar/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 31395c4f..d480679f 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -23,7 +23,7 @@ Module.register("calendar",{ fade: true, urgency: 7, timeFormat: "relative", - getRelative: '6', + getRelative: 6, fadePoint: 0.25, // Start on 1/4th of the list. calendars: [ { From 63351553d840193e4280d06abe33ecba00c43035 Mon Sep 17 00:00:00 2001 From: Jens Date: Sun, 4 Sep 2016 14:24:49 +0200 Subject: [PATCH 040/120] calendar.js doesn't overcapitalize future events --- modules/default/calendar/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index d480679f..6477ac4e 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -207,7 +207,7 @@ Module.register("calendar",{ } } } else { - timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + ' ' + this.capFirst(moment(event.endDate,"x").fromNow(true)); + timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + ' ' + moment(event.endDate,"x").fromNow(true); } } //timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll'); From 25ddf2c65178e2b8afe0709b48d5d30054208c04 Mon Sep 17 00:00:00 2001 From: Phil Oakley Date: Mon, 5 Sep 2016 19:06:21 -0600 Subject: [PATCH 041/120] currentweather module api url bugfix Running this on Raspberry Pi 2, node version v6.5.0, magicmirror@2.0.0 The current url created has a typo that causes the module to only display default weather units (Kelvin). After checking the website (http://openweathermap.org/current), there is no "/" at this location in the url. Removing it fixes the issue and allows the user to see the specified units in config.js. --- modules/default/currentweather/currentweather.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index db3d5de2..5265b099 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -164,7 +164,7 @@ Module.register("currentweather",{ * Calls processWeather on succesfull response. */ updateWeather: function() { - var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.weatherEndpoint + '/' + this.getParams(); + var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.weatherEndpoint + this.getParams(); var self = this; var retry = true; From 1def12061673cb231d9862770016cfad9e0f8399 Mon Sep 17 00:00:00 2001 From: Callum Date: Mon, 5 Sep 2016 22:47:49 -0400 Subject: [PATCH 042/120] Fix typos in raspberry.sh --- installers/raspberry.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installers/raspberry.sh b/installers/raspberry.sh index 824bf7cc..f10c0ddc 100644 --- a/installers/raspberry.sh +++ b/installers/raspberry.sh @@ -68,7 +68,7 @@ else NODE_INSTALL=true fi -# Install or upgare node if nessecery. +# Install or upgrade node if necessary. if $NODE_INSTALL; then echo -e "\e[96mInstalling Node.js ...\e[90m" From 476c577bc113684f84bdf2ef112cafd92e879032 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 6 Sep 2016 10:08:12 +0200 Subject: [PATCH 043/120] Add fixes. --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b87473dc..9ac4cee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,17 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## Unpublished -### Updated -- Force fullscreen when kioskmode is active. - ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. - 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) +- +### Fixed +- Fix typo in installer. +- Fix API url for weather API. + +### Updated +- Force fullscreen when kioskmode is active. ## [2.0.4] - 2016-08-07 From 1ea7ce25890f35d256ea14298e92b061322fe6c4 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 6 Sep 2016 10:09:11 +0200 Subject: [PATCH 044/120] Fix typo. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac4cee5..dbd244a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. - 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) -- + ### Fixed - Fix typo in installer. - Fix API url for weather API. From af279df5c9845b3063d906b441ddcddef9a4493c Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Tue, 6 Sep 2016 19:23:52 -0400 Subject: [PATCH 045/120] Closes #374. ARMv6 is not supported by recent versions of Chrome, and by extent, this means recent versions of Electron as well. --- installers/raspberry.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/installers/raspberry.sh b/installers/raspberry.sh index f10c0ddc..ce37e86f 100644 --- a/installers/raspberry.sh +++ b/installers/raspberry.sh @@ -28,6 +28,7 @@ ARM=$(uname -m) if [ "$ARM" != "armv7l" ]; then echo -e "\e[91mSorry, your Raspberry Pi is not supported." echo -e "\e[91mPlease run MagicMirror on a Raspberry Pi 2 or 3." + echo -e "\e[91mIf this is a Pi Zero, you are in the same boat as the original Raspberry Pi. You must run in server only mode." exit; fi From c01c882081e6a6972713217a710bc3867d88ce19 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Tue, 6 Sep 2016 19:25:16 -0400 Subject: [PATCH 046/120] Update the Changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbd244a5..e402e066 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix typo in installer. +- Add message to unsupported Pi error to mention that Pi Zeros must use server only mode, as ARMv6 is unsupported. Closes #374. - Fix API url for weather API. ### Updated @@ -20,7 +21,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Brazilian Portuguese Translation. -- Option to enable Kios mode. +- Option to enable Kiosk mode. - Added ability to start the app with Dev Tools. - Added ability to turn off the date display in `clock.js` when in analog mode. - Greek Translation From 3cc186f7e4dcd9ba77d197efdfdb0aac7d528c9d Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:10:17 -0400 Subject: [PATCH 047/120] Clean Up the Contributing Documentation and Process: Part I * Remove the HTML Validator * Replace JSCS with ESLint * Replace `npm` commands with equivalent `grunt` commands --- .github/CONTRIBUTING.md | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7025dd7c..49c00ccb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -5,34 +5,21 @@ Thanks for contributing to MagicMirror²! We hold our code to standard, and these standards are documented below. -First, before you run the linters, you will need to install them all **and** install the development dependencies: +### JavaScript: Run ESLint -```bash -(sudo) npm install -g jscs stylelint html-validator-cli -npm install -``` +We use [ESLint](http://eslint.org) on our JavaScript files. -### JavaScript: Run JSCS +Our ESLint configuration is in our .eslintrc.json and .eslintignore files. -We use [JSCS](http://jscs.info) on our JavaScript files. - -Our JSCS configuration is in our .jscsrc file. - -To run JSCS, use `npm run jscs`. +To run ESLint, use `grunt eslint`. ### CSS: Run StyleLint We use [StyleLint](http://stylelint.io) to lint our CSS. Our configuration is in our .stylelintrc file. -To run StyleLint, use `npm run stylelint`. +To run StyleLint, use `grunt postcss:lint`. -### HTML: Run HTML Validator - -We use [NU Validator](https://validator.w3.org/nu) to validate our HTML. The configuration is in the command in the package.json file. - -To run HTML Validator, use `npm run htmlvalidator`. - -## Submitting Issues +### Submitting Issues Please only submit reproducible issues. From 1a54bafdd55505675dca2d080d463217dadde902 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:14:00 -0400 Subject: [PATCH 048/120] Clean Up the Contributing Documentation and Process: Part II * Add `grunt-stylelint` over the complicated PostCSS method previously used. * Remove PostCSS dependencies. --- package.json | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 8c2b226b..977a4bb1 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,6 @@ "main": "js/electron.js", "scripts": { "start": "electron js/electron.js", - "jscs": "jscs **/**/**/**/*.js", - "stylelint": "stylelint css/main.css fonts/roboto.css", - "htmlvalidator": "html-validator --file=index.html", "test": "snyk test", "snyk-protect": "snyk protect", "prepublish": "npm run snyk-protect" @@ -33,11 +30,9 @@ "electron-prebuilt": "latest", "grunt": "latest", "grunt-eslint": "latest", - "grunt-postcss": "latest", - "postcss-reporter": "latest", - "stylelint": "latest", "stylelint-config-standard": "latest", - "time-grunt": "latest" + "time-grunt": "latest", + "grunt-stylelint": "latest" }, "dependencies": { "express": "^4.14.0", @@ -52,4 +47,4 @@ "walk": "latest" }, "snyk": true -} \ No newline at end of file +} From a90f2cb1560956ab3354a370ad881a61f5bc91dc Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:17:20 -0400 Subject: [PATCH 049/120] Clean Up the Contributing Documentation and Process: Part III * Remove PostCSS from Grunt. * Add StyleLint to Grunt. --- Gruntfile.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index ac499fe3..ff1552a8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -8,21 +8,16 @@ module.exports = function(grunt) { }, target: ["js/*.js", "modules/default/*.js", "serveronly/*.js", "*.js"] }, - postcss: { - lint: { + stylelint: { + simple: { options: { - processors: [ - require("stylelint")({"extends": "stylelint-config-standard", "font-family-name-quotes": "double-where-recommended"}), - require("postcss-reporter")({ clearMessages: true }) - ] + configFile: ".stylelintrc" }, - dist: { - src: "**/**/**/**/**/**/**/**.css" - } + src: "**/**/**/**/**/**/**/**/*.css" } } }); grunt.loadNpmTasks("grunt-eslint"); - grunt.loadNpmTasks("grunt-postcss"); - grunt.registerTask("default", ["eslint", "postcss:lint"]); -}; \ No newline at end of file + grunt.loadNpmTasks("grunt-stylelint"); + grunt.registerTask("default", ["eslint", "stylelint"]); +}; From 83ed298eba1c8827c34733b8777a16fa9f7d2987 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:22:40 -0400 Subject: [PATCH 050/120] Clean Up the Contributing Documentation and Process: Part IV * Replace `postcss:lint` with `stylelint`. * Update the contribution instructions. --- .github/CONTRIBUTING.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 49c00ccb..ee3b7219 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -3,7 +3,9 @@ Contribution Policy for MagicMirror² Thanks for contributing to MagicMirror²! -We hold our code to standard, and these standards are documented below. +We hold our code to standard, and these standards are documented below. + +If you wish to run both linters, use `grunt` without any arguments. ### JavaScript: Run ESLint @@ -17,30 +19,31 @@ To run ESLint, use `grunt eslint`. We use [StyleLint](http://stylelint.io) to lint our CSS. Our configuration is in our .stylelintrc file. -To run StyleLint, use `grunt postcss:lint`. +To run StyleLint, use `grunt stylelint`. ### Submitting Issues Please only submit reproducible issues. -If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: https://forum.magicmirror.builders/category/15/bug-hunt - Problems installing or configuring your MagicMirror? Check out: https://forum.magicmirror.builders/category/10/troubleshooting +If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt) +Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting) When submitting a new issue, please supply the following information: -**Platform** [ Raspberry Pi 2/3, Windows, Mac OS X, Linux, Etc ... ]: +**Platform**: Place your platform here... give us your web browser/Electron version *and* your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX). -**Node Version** [ 0.12.13 or later ]: +**Node Version**: Make sure it's version 0.12.13 or later. -**MagicMirror Version** [ V1 / V2-Beta ]: +**MagicMirror Version**: Now that the versions have split, tell us if you are using the PHP version (v1) or the newer JavaScript version (v2). -**Description:** Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem. +**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem. -**Steps to Reproduce:** List the step by step process to reproduce the issue. +**Steps to Reproduce**: List the step by step process to reproduce the issue. -**Expected Results:** Describe what you expected to see. +**Expected Results**: Describe what you expected to see. -**Actual Results:** Describe what you actually saw. +**Actual Results**: Describe what you actually saw. -**Configuration:** What does the used config.js file look like? (Don't forget to remove any sensitive information.) +**Configuration**: What does the used config.js file look like? Don't forget to remove any sensitive information! -**Additional Notes:** Provide any other relevant notes not previously mentioned (optional) +**Additional Notes**: Provide any other relevant notes not previously mentioned. This is optional. From 504d3cd13148558aa647f6ca603b718f6917aa39 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:23:45 -0400 Subject: [PATCH 051/120] Clean Up the Contributing Documentation and Process: Part V * Replace the contribution instructions with the ones from CONTRIBUTING.md. --- .github/ISSUE_TEMPLATE.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 6d039bf1..736795d7 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,21 +1,24 @@ Please only submit reproducible issues. -If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: https://forum.magicmirror.builders/category/15/bug-hunt - Problems installing or configuring your MagicMirror? Check out: https://forum.magicmirror.builders/category/10/troubleshooting +If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt) +Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting) -**Platform** [ Raspberry Pi 2/3, Windows, Mac OS X, Linux, Etc ... ]: +When submitting a new issue, please supply the following information: -**Node Version** [ 0.12.13 or later ]: +**Platform**: Place your platform here... give us your web browser/Electron version *and* your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX). -**MagicMirror Version** [ V1 / V2-Beta ]: +**Node Version**: Make sure it's version 0.12.13 or later. -**Description:** Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem. +**MagicMirror Version**: Now that the versions have split, tell us if you are using the PHP version (v1) or the newer JavaScript version (v2). -**Steps to Reproduce:** List the step by step process to reproduce the issue. +**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem. -**Expected Results:** Describe what you expected to see. +**Steps to Reproduce**: List the step by step process to reproduce the issue. -**Actual Results:** Describe what you actually saw. +**Expected Results**: Describe what you expected to see. -**Configuration:** What does the used config.js file look like? (Don't forget to remove any sensitive information.) +**Actual Results**: Describe what you actually saw. -**Additional Notes:** Provide any other relevant notes not previously mentioned (optional) +**Configuration**: What does the used config.js file look like? Don't forget to remove any sensitive information! + +**Additional Notes**: Provide any other relevant notes not previously mentioned. This is optional. From 8549aeb466781393cec1af0cc93fee2de475a7a8 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:24:52 -0400 Subject: [PATCH 052/120] Clean Up the Contributing Documentation and Process: Part VI * Alter the pull request template to look a little better. --- .github/PULL_REQUEST_TEMPLATE.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1ac9aaa1..215950e0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,7 @@ -> Please send your PR's the develop branch. -> Don't forget to add the change to changelog.md. +> Please send your pull requests the develop branch. +> Don't forget to add the change to CHANGELOG.md. -* Does the pull request solve a **related** issue? [yes | no] +* Does the pull request solve a **related** issue? * If so, can you reference the issue? -* What does the pull request accomplish? (please list) +* What does the pull request accomplish? Use a list if needed. * If it includes major visual changes please add screenshots. - - From 0ec5371b617c1106438cfccf4f485518f555ed14 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:26:50 -0400 Subject: [PATCH 053/120] Clean Up the Contributing Documentation and Process: Part VII * Update the changelog to mention my changes. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e402e066..5659ae66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Updated - Force fullscreen when kioskmode is active. +- Update the .github templates and information with more modern information. +- Update the Gruntfile with a more functional StyleLint implementation. ## [2.0.4] - 2016-08-07 From 90207f9b68bab127f2df1f83d1367b8de415c193 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Sep 2016 17:36:30 +0200 Subject: [PATCH 054/120] add support for http basic auth for calendars --- CHANGELOG.md | 1 + modules/default/calendar/README.md | 8 ++++++++ modules/default/calendar/calendar.js | 8 +++++--- modules/default/calendar/calendarfetcher.js | 13 +++++++++++-- modules/default/calendar/node_helper.js | 6 +++--- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e402e066..1e787e90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. - 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 ### Fixed - Fix typo in installer. diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index 3189d92c..936abdde 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -183,5 +183,13 @@ config: { 'Birthday' + + user + The username for HTTP Basic authentication. + + + pass + The password for HTTP Basic authentication. + diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index d4871338..3151467a 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -64,7 +64,7 @@ Module.register("calendar",{ for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; calendar.url = calendar.url.replace("webcal://", "http://"); - this.addCalendar(calendar.url); + this.addCalendar(calendar.url, calendar.user, calendar.pass); } this.calendarData = {}; @@ -285,12 +285,14 @@ Module.register("calendar",{ * * argument url sting - Url to add. */ - addCalendar: function(url) { + addCalendar: function(url, user, pass) { this.sendSocketNotification("ADD_CALENDAR", { url: url, maximumEntries: this.config.maximumEntries, maximumNumberOfDays: this.config.maximumNumberOfDays, - fetchInterval: this.config.fetchInterval + fetchInterval: this.config.fetchInterval, + user: user, + pass: pass }); }, diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index f7f68b7e..214e2e5a 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -8,7 +8,7 @@ var ical = require("./vendor/ical.js"); var moment = require("moment"); -var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumberOfDays) { +var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumberOfDays, user, pass) { var self = this; var reloadTimer = null; @@ -29,7 +29,16 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe headers: { 'User-Agent': 'Mozilla/5.0 (Node.js 6.0.0) MagicMirror/v2 (https://github.com/MichMich/MagicMirror/)' } + }; + + if (user && pass) { + opts.auth = { + user: user, + pass: pass, + sendImmediately: true + } } + ical.fromURL(url, opts, function(err, data) { if (err) { fetchFailedCallback(self, err); @@ -239,4 +248,4 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe }; -module.exports = CalendarFetcher; \ No newline at end of file +module.exports = CalendarFetcher; diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index 47a0231b..a1b8db09 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -25,7 +25,7 @@ module.exports = NodeHelper.create({ socketNotificationReceived: function(notification, payload) { if (notification === "ADD_CALENDAR") { //console.log('ADD_CALENDAR: '); - this.createFetcher(payload.url, payload.fetchInterval, payload.maximumEntries, payload.maximumNumberOfDays); + this.createFetcher(payload.url, payload.fetchInterval, payload.maximumEntries, payload.maximumNumberOfDays, payload.user, payload.pass); } }, @@ -37,7 +37,7 @@ module.exports = NodeHelper.create({ * attribute reloadInterval number - Reload interval in milliseconds. */ - createFetcher: function(url, fetchInterval, maximumEntries, maximumNumberOfDays) { + createFetcher: function(url, fetchInterval, maximumEntries, maximumNumberOfDays, user, pass) { var self = this; if (!validUrl.isUri(url)) { @@ -48,7 +48,7 @@ module.exports = NodeHelper.create({ var fetcher; if (typeof self.fetchers[url] === "undefined") { console.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval); - fetcher = new CalendarFetcher(url, fetchInterval, maximumEntries, maximumNumberOfDays); + fetcher = new CalendarFetcher(url, fetchInterval, maximumEntries, maximumNumberOfDays, user, pass); fetcher.onReceive(function(fetcher) { //console.log('Broadcast events.'); From c76f2c8483b3f9fee80f020927d086f9a2087d71 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:41:12 -0400 Subject: [PATCH 055/120] Clean Up the Contributing Documentation and Process: Part VII * Fix the globbing error in the previous commits. --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index ff1552a8..3c7c00cc 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,7 +13,7 @@ module.exports = function(grunt) { options: { configFile: ".stylelintrc" }, - src: "**/**/**/**/**/**/**/**/*.css" + src: ["css/custom.css", "css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"] } } }); From 17452cd5b65bc9d1e23da42a984ec93c9ba2a1b2 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:44:43 -0400 Subject: [PATCH 056/120] Clean Up the Contributing Documentation and Process: Part VII.XXXIII * Fix the css/custom.css issues. --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 3c7c00cc..38f7247b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,7 +13,7 @@ module.exports = function(grunt) { options: { configFile: ".stylelintrc" }, - src: ["css/custom.css", "css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"] + src: ["css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"] } } }); From e023a68780745239c077d020f243264ddaff712c Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:47:16 -0400 Subject: [PATCH 057/120] Clean Up the Contributing Documentation and Process: Part VII.LXVI * Fix the issues in css/main.css. --- css/main.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/css/main.css b/css/main.css index 93d6a7ee..7ae902d6 100644 --- a/css/main.css +++ b/css/main.css @@ -1,10 +1,10 @@ html { cursor: none; - overflow:hidden; + overflow: hidden; } -::-webkit-scrollbar { - display: none; +::-webkit-scrollbar { + display: none; } body { From 4e919199907b87f022d92c24cdd251dc4d3fc350 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:49:24 -0400 Subject: [PATCH 058/120] Clean Up the Contributing Documentation and Process: Part VII.LXVI.I * Fix the StyleLint config to allow the empty blocks in the clock module CSS. --- .stylelintrc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.stylelintrc b/.stylelintrc index 02300404..db05c713 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -1,4 +1,5 @@ { "extends": "stylelint-config-standard", - "font-family-name-quotes": "double-where-recommended" -} \ No newline at end of file + "font-family-name-quotes": "double-where-recommended", + "block-no-empty": false +} From 0ca903a146a5ba94ab164fce5857c5337a4e2fb2 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:51:58 -0400 Subject: [PATCH 059/120] Clean Up the Contributing Documentation and Process: Part VII.LXVI.II * Fix the indentation in the clock CSS. --- modules/default/clock/clock_styles.css | 102 ++++++++++++------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/modules/default/clock/clock_styles.css b/modules/default/clock/clock_styles.css index 6020e579..b6eba047 100644 --- a/modules/default/clock/clock_styles.css +++ b/modules/default/clock/clock_styles.css @@ -5,70 +5,70 @@ } .clockCircle { - margin: 0 auto; - position: relative; - border-radius: 50%; - background-size: 100%; + margin: 0 auto; + position: relative; + border-radius: 50%; + background-size: 100%; } .clockFace { - width: 100%; - height: 100%; + width: 100%; + height: 100%; } .clockFace:after { - position: absolute; - top: 50%; - left: 50%; - width: 6px; - height: 6px; - margin: -3px 0 0 -3px; - background: white; - border-radius: 3px; - content: ""; - display: block; + position: absolute; + top: 50%; + left: 50%; + width: 6px; + height: 6px; + margin: -3px 0 0 -3px; + background: white; + border-radius: 3px; + content: ""; + display: block; } .clockHour { - width: 0; - height: 0; - position: absolute; - top: 50%; - left: 50%; - margin: -2px 0 -2px -25%; /* numbers much match negative length & thickness */ - padding: 2px 0 2px 25%; /* indicator length & thickness */ - background: white; - -webkit-transform-origin: 100% 50%; - -ms-transform-origin: 100% 50%; - transform-origin: 100% 50%; - border-radius: 3px 0 0 3px; + width: 0; + height: 0; + position: absolute; + top: 50%; + left: 50%; + margin: -2px 0 -2px -25%; /* numbers much match negative length & thickness */ + padding: 2px 0 2px 25%; /* indicator length & thickness */ + background: white; + -webkit-transform-origin: 100% 50%; + -ms-transform-origin: 100% 50%; + transform-origin: 100% 50%; + border-radius: 3px 0 0 3px; } .clockMinute { - width: 0; - height: 0; - position: absolute; - top: 50%; - left: 50%; - margin: -35% -2px 0; /* numbers must match negative length & thickness */ - padding: 35% 2px 0; /* indicator length & thickness */ - background: white; - -webkit-transform-origin: 50% 100%; - -ms-transform-origin: 50% 100%; - transform-origin: 50% 100%; - border-radius: 3px 0 0 3px; + width: 0; + height: 0; + position: absolute; + top: 50%; + left: 50%; + margin: -35% -2px 0; /* numbers must match negative length & thickness */ + padding: 35% 2px 0; /* indicator length & thickness */ + background: white; + -webkit-transform-origin: 50% 100%; + -ms-transform-origin: 50% 100%; + transform-origin: 50% 100%; + border-radius: 3px 0 0 3px; } .clockSecond { - width: 0; - height: 0; - position: absolute; - top: 50%; - left: 50%; - margin: -38% -1px 0 0; /* numbers must match negative length & thickness */ - padding: 38% 1px 0 0; /* indicator length & thickness */ - background: #888888; - -webkit-transform-origin: 50% 100%; - -ms-transform-origin: 50% 100%; - transform-origin: 50% 100%; + width: 0; + height: 0; + position: absolute; + top: 50%; + left: 50%; + margin: -38% -1px 0 0; /* numbers must match negative length & thickness */ + padding: 38% 1px 0 0; /* indicator length & thickness */ + background: #888888; + -webkit-transform-origin: 50% 100%; + -ms-transform-origin: 50% 100%; + transform-origin: 50% 100%; } From 5ab4b5741150675f124a1114c50a187432b6cf24 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 15:57:25 -0400 Subject: [PATCH 060/120] Clean Up the Contributing Documentation and Process: Part VII.LXVI.III * Fix the errors that popped up out of the blue from Stylelint. --- modules/default/clock/clock_styles.css | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/modules/default/clock/clock_styles.css b/modules/default/clock/clock_styles.css index b6eba047..7dc2d2a8 100644 --- a/modules/default/clock/clock_styles.css +++ b/modules/default/clock/clock_styles.css @@ -1,9 +1,3 @@ -#analog { -} - -#digital { -} - .clockCircle { margin: 0 auto; position: relative; @@ -16,7 +10,7 @@ height: 100%; } -.clockFace:after { +.clockFace::after { position: absolute; top: 50%; left: 50%; @@ -31,6 +25,7 @@ .clockHour { width: 0; + height: 0; position: absolute; top: 50%; @@ -67,7 +62,7 @@ left: 50%; margin: -38% -1px 0 0; /* numbers must match negative length & thickness */ padding: 38% 1px 0 0; /* indicator length & thickness */ - background: #888888; + background: #888; -webkit-transform-origin: 50% 100%; -ms-transform-origin: 50% 100%; transform-origin: 50% 100%; From c87c588c799ecafe5dfe0db4f4715d2328fa5055 Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Thu, 8 Sep 2016 16:00:48 -0400 Subject: [PATCH 061/120] Clean Up the Contributing Documentation and Process: Part VII.LXVI.IV * Fix yet another out-of-the-blue error that Stylelint found. --- modules/default/clock/clock_styles.css | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/default/clock/clock_styles.css b/modules/default/clock/clock_styles.css index 7dc2d2a8..1df9bf83 100644 --- a/modules/default/clock/clock_styles.css +++ b/modules/default/clock/clock_styles.css @@ -25,7 +25,6 @@ .clockHour { width: 0; - height: 0; position: absolute; top: 50%; From 88572e90d48333ddf0c64f4839bf985766d7d68f Mon Sep 17 00:00:00 2001 From: Nicholas Hubbard Date: Sat, 10 Sep 2016 16:41:57 -0400 Subject: [PATCH 062/120] Add all the linters --- .eslintignore | 1 - CHANGELOG.md | 2 +- Gruntfile.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- README.md | 16 ++++++++-------- package.json | 13 ++++++++----- 5 files changed, 63 insertions(+), 17 deletions(-) diff --git a/.eslintignore b/.eslintignore index 25422889..2e1f92d3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,5 @@ vendor/ !/vendor/vendor.js -/modules/** !/modules/default/** !/modules/node_helper !/modules/node_helper/** diff --git a/CHANGELOG.md b/CHANGELOG.md index 5659ae66..efb93cd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,4 +88,4 @@ It includes (but is not limited to) the following features: ## [1.0.0] - 2014-02-16 ### Initial release of MagicMirror. -This was part of the blogpost: http://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the +This was part of the blogpost: [http://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the](http://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the) diff --git a/Gruntfile.js b/Gruntfile.js index 38f7247b..e5bc690b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -15,9 +15,53 @@ module.exports = function(grunt) { }, src: ["css/main.css", "modules/default/calendar/calendar.css", "modules/default/clock/clock_styles.css", "modules/default/currentweather/currentweather.css", "modules/default/weatherforcast/weatherforcast.css"] } + }, + jsonlint: { + main: { + src: ["package.json", ".eslintrc.json", ".stylelint"], + options: { + reporter: "jshint" + } + } + }, + markdownlint: { + all: { + options: { + config: { + "default": true, + "line-length": false, + "blanks-around-headers": false, + "no-duplicate-header": false, + "no-inline-html": false, + "MD010": false, + "MD001": false, + "MD031": false, + "MD040": false, + "MD002": false, + "MD029": false, + "MD041": false, + "MD032": false, + "MD036": false, + "MD037": false, + "MD009": false, + "MD018": false, + "MD012": false, + "MD026": false, + "MD036": false, + "MD038": false + } + }, + src: ["README.md", "CHANGELOG.md", "LICENSE.md", "modules/README.md", "modules/default/**/*.md", "!modules/default/calendar/vendor/ical.js/readme.md"] + } + }, + yamllint: { + all: [".travis.yml"] } }); grunt.loadNpmTasks("grunt-eslint"); grunt.loadNpmTasks("grunt-stylelint"); - grunt.registerTask("default", ["eslint", "stylelint"]); -}; + grunt.loadNpmTasks("grunt-jsonlint"); + grunt.loadNpmTasks("grunt-yamllint"); + grunt.loadNpmTasks("grunt-markdownlint"); + grunt.registerTask("default", ["eslint", "stylelint", "jsonlint", "markdownlint", "yamllint"]); +}; \ No newline at end of file diff --git a/README.md b/README.md index 0b9e00ed..d86cca7c 100644 --- a/README.md +++ b/README.md @@ -24,17 +24,17 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](http://elec ## Usage -#### Raspberry Pi Support +### Raspberry Pi Support Electron, the app wrapper around MagicMirror², only supports the Raspberry Pi 2 & 3. The Raspberry Pi 1 is currently **not** supported. If you want to run this on a Raspberry Pi 1, use the [server only](#server-only) feature and setup a fullscreen browser yourself. -#### Automatic Installer (Raspberry Pi Only!) +### Automatic Installer (Raspberry Pi Only!) Execute the following command on your Raspberry Pi to install MagicMirror²: ```` curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/raspberry.sh | bash ```` -#### Manual Installation +### Manual Installation 1. Download and install the latest Node.js version. 2. Clone the repository and check out the beta branch: `git clone https://github.com/MichMich/MagicMirror` @@ -45,23 +45,23 @@ curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installer **Note:** if you want to debug on Raspberry Pi you can use `npm start dev` which will start the MagicMirror app with Dev Tools enabled. -#### Server Only +### Server Only In some cases, you want to start the application without an actual app window. In this case, execute the following command from the MagicMirror folder: `node serveronly`. This will start the server, after which you can open the application in your browser of choice. -#### Raspberry Configuration & Auto Start. +### Raspberry Configuration & Auto Start. The following wiki links are helpful in the configuration of your MagicMirror² operating system: - [Configuring the Raspberry Pi](https://github.com/MichMich/MagicMirror/wiki/Configuring-the-Raspberry-Pi) - [Auto Starting MagicMirror](https://github.com/MichMich/MagicMirror/wiki/Auto-Starting-MagicMirror) -#### Updating you MagicMirror² +### Updating your MagicMirror² If you want to update your MagicMirror² to the latest version, use your terminal to go to your Magic Mirror folder and type the following command: -```` +```bash git pull -```` +``` If you changed nothing more than the config or the modules, this should work without any problems. Type `git status` to see your changes, if there are any, you can reset them with `git reset --hard`. After that, git pull should be possible. diff --git a/package.json b/package.json index 977a4bb1..ad2c0109 100644 --- a/package.json +++ b/package.json @@ -27,24 +27,27 @@ }, "homepage": "https://github.com/MichMich/MagicMirror#readme", "devDependencies": { - "electron-prebuilt": "latest", "grunt": "latest", "grunt-eslint": "latest", + "grunt-jsonlint": "latest", + "grunt-markdownlint": "^1.0.4", + "grunt-stylelint": "latest", + "grunt-yamllint": "latest", "stylelint-config-standard": "latest", - "time-grunt": "latest", - "grunt-stylelint": "latest" + "time-grunt": "latest" }, "dependencies": { + "electron-prebuilt": "latest", "express": "^4.14.0", "feedme": "latest", "iconv-lite": "latest", "moment": "latest", "request": "^2.74.0", "rrule": "latest", - "snyk": "^1.14.1", "socket.io": "^1.4.6", "valid-url": "latest", - "walk": "latest" + "walk": "latest", + "snyk": "^1.14.1" }, "snyk": true } From f468dbf4271204685bdfaef5d433fa4ed9b5b18e Mon Sep 17 00:00:00 2001 From: Andrew Chumchal Date: Sun, 11 Sep 2016 08:04:33 -0700 Subject: [PATCH 063/120] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e787e90..65239356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - 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 ### Fixed - Fix typo in installer. From 747e1a818d36a0c831207d2f9f5f81c336391dd8 Mon Sep 17 00:00:00 2001 From: Andrew Chumchal Date: Sun, 11 Sep 2016 08:14:28 -0700 Subject: [PATCH 064/120] Able to turn off and on the clock module --- modules/default/clock/README.md | 9 ++++++++- modules/default/clock/clock.js | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/default/clock/README.md b/modules/default/clock/README.md index c7ec6bcb..6eca1efb 100644 --- a/modules/default/clock/README.md +++ b/modules/default/clock/README.md @@ -66,6 +66,13 @@ The following properties can be configured:
Default value: false + + showDate + Turn off or on the Date section.
+
Possible values: true or false +
Default value: true + + displayType Display a digital clock, analog clock, or both together.
@@ -109,4 +116,4 @@ The following properties can be configured: - + \ No newline at end of file diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index e3415375..db41d7e0 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -15,6 +15,7 @@ Module.register("clock",{ showPeriod: true, showPeriodUpper: false, clockBold: false, + showDate: true, /* specific to the analog clock */ analogSize: '200px', @@ -85,7 +86,9 @@ Module.register("clock",{ timeString = moment().format("h:mm"); } } + if(this.config.showDate){ dateWrapper.innerHTML = moment().format("dddd, LL"); + } timeWrapper.innerHTML = timeString; secondsWrapper.innerHTML = moment().format("ss"); if (this.config.showPeriodUpper) { @@ -224,4 +227,4 @@ Module.register("clock",{ // Return the wrapper to the dom. return wrapper; } -}); +}); \ No newline at end of file From 5dfecfdee3e205bc825158e4114c25fbdb6b0c31 Mon Sep 17 00:00:00 2001 From: contra Date: Sat, 17 Sep 2016 17:54:38 -0400 Subject: [PATCH 065/120] fix typo --- modules/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/README.md b/modules/README.md index 39072db5..f4a8debd 100644 --- a/modules/README.md +++ b/modules/README.md @@ -4,7 +4,7 @@ This document describes the way to develop your own MagicMirror² modules. ## Module structure -All modules are loaded in de `modules` folder. The default modules are grouped together in the `modules/default` folder. Your module should be placed in a subfolder of `modules`. Note that any file or folder your create in the `modules` folder will be ignored by git, allowing you to upgrade the MagicMirror² without the loss of your files. +All modules are loaded in the `modules` folder. The default modules are grouped together in the `modules/default` folder. Your module should be placed in a subfolder of `modules`. Note that any file or folder your create in the `modules` folder will be ignored by git, allowing you to upgrade the MagicMirror² without the loss of your files. A module can be placed in one single folder. Or multiple modules can be grouped in a subfoler. Note that name of the module must be unique. Even when a module with a similar name is placed in a different folder, they can't be loaded at the same time. From 749475799ad1d6f860e02360dc0a7fc59563ebcb Mon Sep 17 00:00:00 2001 From: valmassoi Date: Sun, 18 Sep 2016 10:54:20 -0700 Subject: [PATCH 066/120] Fix default weather forecast module api URL --- modules/default/weatherforecast/weatherforecast.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js index 706da252..a8a8ca6c 100644 --- a/modules/default/weatherforecast/weatherforecast.js +++ b/modules/default/weatherforecast/weatherforecast.js @@ -102,7 +102,7 @@ Module.register("weatherforecast",{ } if (!this.loaded) { - wrapper.innerHTML = this.translate('LOADING'); + wrapper.innerHTML = this.translate("LOADING"); wrapper.className = "dimmed light small"; return wrapper; } @@ -161,7 +161,7 @@ Module.register("weatherforecast",{ * Calls processWeather on succesfull response. */ updateWeather: function() { - var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.forecastEndpoint + '/' + this.getParams(); + var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.forecastEndpoint + this.getParams(); var self = this; var retry = true; From c916472b2263f4940c8f200af9a42f917c00c603 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 20 Sep 2016 16:32:45 +0200 Subject: [PATCH 067/120] Release 2.0.5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f75d45ab..20f95c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## Unpublished +## [2.0.5] - 2016-09-20 ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. From b2a7d3584bad2752d59d2325c581f5018e875306 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 20 Sep 2016 17:22:24 +0200 Subject: [PATCH 068/120] Add getHeader functionlity.. --- CHANGELOG.md | 8 +++++++- js/main.js | 44 +++++++++++++++++++++++++++++++------------- js/module.js | 11 +++++++++++ modules/README.md | 17 +++++++++++++++++ 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20f95c84..859ca30d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,19 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). + +## [2.1.0] - Unreleased + +### Added +- Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) + ## [2.0.5] - 2016-09-20 ### Added - Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'. - 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 support for doing http basic auth when loading calendars - Add the abilty to turn off and on the date display in the Clock Module ### Fixed diff --git a/js/main.js b/js/main.js index abd93e40..c0c63006 100644 --- a/js/main.js +++ b/js/main.js @@ -40,6 +40,7 @@ var MM = (function() { if (typeof module.data.header !== "undefined" && module.data.header !== "") { var moduleHeader = document.createElement("header"); moduleHeader.innerHTML = module.data.header; + moduleHeader.className = "module-header"; dom.appendChild(moduleHeader); } @@ -94,26 +95,27 @@ var MM = (function() { */ var updateDom = function(module, speed) { var newContent = module.getDom(); + var newHeader = module.getHeader(); if (!module.hidden) { - if (!moduleNeedsUpdate(module, newContent)) { + if (!moduleNeedsUpdate(module, newHeader, newContent)) { return; } if (!speed) { - updateModuleContent(module, newContent); + updateModuleContent(module, newHeader, newContent); return; } hideModule(module, speed / 2, function() { - updateModuleContent(module, newContent); + updateModuleContent(module, newHeader, newContent); if (!module.hidden) { showModule(module, speed / 2); } }); } else { - updateModuleContent(module, newContent); + updateModuleContent(module, newHeader, newContent); } }; @@ -125,14 +127,23 @@ var MM = (function() { * * return bool - Does the module need an update? */ - var moduleNeedsUpdate = function(module, newContent) { + var moduleNeedsUpdate = function(module, newHeader, newContent) { var moduleWrapper = document.getElementById(module.identifier); - var contentWrapper = moduleWrapper.getElementsByClassName("module-content")[0]; + var contentWrapper = moduleWrapper.getElementsByClassName("module-content"); + var headerWrapper = moduleWrapper.getElementsByClassName("module-header"); - var tempWrapper = document.createElement("div"); - tempWrapper.appendChild(newContent); + var headerNeedsUpdate = false; + var contentNeedsUpdate = false; - return tempWrapper.innerHTML !== contentWrapper.innerHTML; + if (headerWrapper.length > 0) { + headerNeedsUpdate = newHeader !== headerWrapper.innerHTML; + } + + var tempContentWrapper = document.createElement("div"); + tempContentWrapper.appendChild(newContent); + contentNeedsUpdate = tempContentWrapper.innerHTML !== contentWrapper[0].innerHTML; + + return headerNeedsUpdate || contentNeedsUpdate; }; /* moduleNeedsUpdate(module, newContent) @@ -141,12 +152,19 @@ var MM = (function() { * argument module Module - The module to check. * argument newContent Domobject - The new content that is generated. */ - var updateModuleContent = function(module, content) { + var updateModuleContent = function(module, newHeader, newContent) { var moduleWrapper = document.getElementById(module.identifier); - var contentWrapper = moduleWrapper.getElementsByClassName("module-content")[0]; + var headerWrapper = moduleWrapper.getElementsByClassName("module-header"); + var contentWrapper = moduleWrapper.getElementsByClassName("module-content"); + + contentWrapper[0].innerHTML = ""; + contentWrapper[0].appendChild(newContent); + + if( headerWrapper.length > 0 && newHeader) { + headerWrapper[0].innerHTML = newHeader; + } + - contentWrapper.innerHTML = ""; - contentWrapper.appendChild(content); }; /* hideModule(module, speed, callback) diff --git a/js/module.js b/js/module.js index 293d00b5..9c26bc7b 100644 --- a/js/module.js +++ b/js/module.js @@ -84,6 +84,17 @@ var Module = Class.extend({ return div; }, + /* getHeader() + * This method generates the header string which needs to be displayed if a user has a header configured for this module. + * This method is called by the Magic Mirror core, but only if the user has configured a default header for the module. + * This method needs to be subclassed if the module wants to display modified headers on the mirror. + * + * return string - The header to display above the header. + */ + getHeader: function() { + return this.data.header; + }, + /* notificationReceived(notification, payload, sender) * This method is called when a notification arrives. * This method is called by the Magic Mirror core. diff --git a/modules/README.md b/modules/README.md index f4a8debd..61989a93 100644 --- a/modules/README.md +++ b/modules/README.md @@ -166,6 +166,23 @@ getDom: function() { ```` +####`getHeader()` +**Should return:** String + +Whenever the MagicMirror needs to update the information on screen (because it starts, or because your module asked a refresh using `this.updateDom()`), the system calls the getHeader method to retrieve the module's header. This method should therefor return a string. If this method is not subclassed, this function will return the user's configured header. + +If you want to use the original user's configured header, reference `this.data.header`. + +**NOTE:** If the user did not confiugure a default header, no header will be displayed and thus this method will not be called. + +**Example:** +````javascript +getHeader: function() { + return this.data.header + ' Foo Bar'; +} + +```` + ####`notificationReceived(notification, payload, sender)` That MagicMirror core has the ability to send notifications to modules. Or even better: the modules have the possibility to send notifications to other modules. When this module is called, it has 3 arguments: From 56a45977840257de78e909e6e0cd58a1b2d0b149 Mon Sep 17 00:00:00 2001 From: Wilco Land Date: Wed, 21 Sep 2016 09:57:47 +0200 Subject: [PATCH 069/120] Update fy.json Added "DAYAFTERTOMORROW" --- translations/fy.json | 1 + 1 file changed, 1 insertion(+) diff --git a/translations/fy.json b/translations/fy.json index af6bcde8..770ae3a1 100644 --- a/translations/fy.json +++ b/translations/fy.json @@ -5,6 +5,7 @@ /* CALENDAR */ "TODAY": "Hjoed", "TOMORROW": "Moarn", + "DAYAFTERTOMORROW": "Oaremoarn", "RUNNING": "Einigest oer", "EMPTY": "Gjin plande ôfspraken.", From 30eaec29d34af1048db3c8c7c967384b16fb448a Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Wed, 21 Sep 2016 10:29:34 +0200 Subject: [PATCH 070/120] Modified translations for Frysk. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 859ca30d..1f78e9ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) +### Updated +- Modified translations for Frysk. + ## [2.0.5] - 2016-09-20 ### Added From 4ff86795b9a6c55ab16023609fb7e6e5e304646c Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 22 Sep 2016 19:56:54 +0200 Subject: [PATCH 071/120] Snyk security update. --- CHANGELOG.md | 3 ++- package.json | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f78e9ed..326bfc49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [2.1.0] - Unreleased ### Added -- Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) +- Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) ### Updated - Modified translations for Frysk. +- Updated package.json as a result of Snyk security update. ## [2.0.5] - 2016-09-20 diff --git a/package.json b/package.json index ad2c0109..afdad5f6 100644 --- a/package.json +++ b/package.json @@ -37,17 +37,17 @@ "time-grunt": "latest" }, "dependencies": { - "electron-prebuilt": "latest", + "electron-prebuilt": "^0.37.2", "express": "^4.14.0", "feedme": "latest", "iconv-lite": "latest", "moment": "latest", "request": "^2.74.0", "rrule": "latest", + "snyk": "^1.14.1", "socket.io": "^1.4.6", "valid-url": "latest", - "walk": "latest", - "snyk": "^1.14.1" + "walk": "latest" }, "snyk": true } From ca95c75df3b3e52e5d1f5f832d1a4c5bf402736e Mon Sep 17 00:00:00 2001 From: Kasper Wandahl Fogh Date: Sat, 24 Sep 2016 10:41:44 +0200 Subject: [PATCH 072/120] Added danish translation --- translations/da.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 translations/da.json diff --git a/translations/da.json b/translations/da.json new file mode 100644 index 00000000..06827ea1 --- /dev/null +++ b/translations/da.json @@ -0,0 +1,28 @@ +{ + /* GENERAL */ + "LOADING": "Indlæser …", + + /* CALENDAR */ + "TODAY": "I dag", + "TOMORROW": "I morgen", + "RUNNING": "Slutter om", + "EMPTY": "Ingen kommende begivenheder.", + + /* WEATHER */ + "N": "N", + "NNE": "NNØ", + "NE": "NØ", + "ENE": "ØNØ", + "E": "Ø", + "ESE": "ØSØ", + "SE": "SØ", + "SSE": "SSØ", + "S": "S", + "SSW": "SSV", + "SW": "SV", + "WSW": "VSV", + "W": "V", + "WNW": "VNV", + "NW": "NV", + "NNW": "NNV" +} From 02ac9fa0d7d467492158ccbad688449fc70627ec Mon Sep 17 00:00:00 2001 From: Kasper Wandahl Fogh Date: Sat, 24 Sep 2016 10:57:02 +0200 Subject: [PATCH 073/120] Added danish in translations.js and updated changelog --- CHANGELOG.md | 5 +++++ translations/translations.js | 1 + 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20f95c84..8fc21516 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [unreleased] - 2016-09-24 + +### Added +- Danish translation + ## [2.0.5] - 2016-09-20 ### Added diff --git a/translations/translations.js b/translations/translations.js index 2a458ef2..c9d5db0a 100644 --- a/translations/translations.js +++ b/translations/translations.js @@ -23,4 +23,5 @@ var translations = { "ja" : "translations/ja.json", // Japanese "pl" : "translations/pl.json", // Polish "gr" : "translations/gr.json", // Greek + "da" : "translations/da.json", // Danish }; From fc0c706100ba39ad6b8ba575692d1baadc284456 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 29 Sep 2016 11:05:37 +0200 Subject: [PATCH 074/120] Add MagPi Logo --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index d86cca7c..8e44f42b 100644 --- a/README.md +++ b/README.md @@ -129,3 +129,8 @@ Please keep the following in mind: - **New Features**: please please discuss in a GitHub issue before you start to alter a big part of the code. Without discussion upfront, the pull request will not be accepted / merged. Thanks for your help in making MagicMirror² better! + +

+
+ MagPi Top 50 +

From 54f04c9141c3acf7cdca2d3d1ebb5b8c4f98e478 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 29 Sep 2016 11:12:49 +0200 Subject: [PATCH 075/120] Fix ESLint issues --- js/class.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/js/class.js b/js/class.js index b1793f16..9d04944e 100644 --- a/js/class.js +++ b/js/class.js @@ -25,24 +25,22 @@ for (var name in prop) { // Check if we're overwriting an existing function prototype[name] = typeof prop[name] == "function" && - typeof _super[name] == "function" && fnTest.test(prop[name]) ? - (function(name, fn) { - return function() { - var tmp = this._super; + typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn) { + return function() { + var tmp = this._super; - // Add a new ._super() method that is the same method - // but on the super-class - this._super = _super[name]; + // Add a new ._super() method that is the same method + // but on the super-class + this._super = _super[name]; - // The method only need to be bound temporarily, so we - // remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; + // The method only need to be bound temporarily, so we + // remove it when we're done executing + var ret = fn.apply(this, arguments); + this._super = tmp; - return ret; - }; - })(name, prop[name]) : - prop[name]; + return ret; + }; + })(name, prop[name]) : prop[name]; } // The dummy class constructor From 5d29fa5e626c7f990d84fa81c556d824f8761d41 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 29 Sep 2016 16:34:57 +0200 Subject: [PATCH 076/120] ip address filtering --- CHANGELOG.md | 1 + config/config.js.sample | 3 +++ js/server.js | 6 ++++++ package.json | 1 + 4 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 326bfc49..74cb3f7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) +- Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)) ### Updated - Modified translations for Frysk. diff --git a/config/config.js.sample b/config/config.js.sample index 04c7fba9..b10c9915 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -6,6 +6,9 @@ var config = { port: 8080, + ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1'], + // you use ips with subnet mask: ['127.0.0.1', '127.0.0.1/24'] + // you use also use ip ranges: ['127.0.0.1', ['192.168.0.1', '192.168.0.100']] language: 'en', timeFormat: 24, diff --git a/js/server.js b/js/server.js index 2ab0b1b9..b8dcec59 100644 --- a/js/server.js +++ b/js/server.js @@ -10,11 +10,17 @@ var app = require("express")(); var server = require("http").Server(app); var io = require("socket.io")(server); var path = require("path"); +var ipfilter = require('express-ipfilter').IpFilter; var Server = function(config, callback) { console.log("Starting server op port " + config.port + " ... "); server.listen(config.port); + if (config.ipWhitelist === undefined) { + config.ipWhitelist = ['127.0.0.1', '::ffff:127.0.0.1']; + console.log("Warning: Missing value (ipWhitelist) from config.js, assuming default (localhost access only): " + config.ipWhitelist); + } + app.use(ipfilter(config.ipWhitelist, {mode: 'allow', log: false})); app.use("/js", express.static(__dirname)); app.use("/config", express.static(path.resolve(__dirname + "/../config"))); app.use("/css", express.static(path.resolve(__dirname + "/../css"))); diff --git a/package.json b/package.json index afdad5f6..cfef5f85 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "dependencies": { "electron-prebuilt": "^0.37.2", "express": "^4.14.0", + "express-ipfilter": "latest", "feedme": "latest", "iconv-lite": "latest", "moment": "latest", From f378c93dd3e7a558d6835fd9f4a29e6e42405e8a Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 29 Sep 2016 17:07:22 +0200 Subject: [PATCH 077/120] replace ugly error message --- js/server.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/js/server.js b/js/server.js index b8dcec59..ddcf1dd3 100644 --- a/js/server.js +++ b/js/server.js @@ -20,7 +20,16 @@ var Server = function(config, callback) { config.ipWhitelist = ['127.0.0.1', '::ffff:127.0.0.1']; console.log("Warning: Missing value (ipWhitelist) from config.js, assuming default (localhost access only): " + config.ipWhitelist); } - app.use(ipfilter(config.ipWhitelist, {mode: 'allow', log: false})); + + app.use(function(req, res, next) { + var result = ipfilter(config.ipWhitelist, {mode: 'allow', log: false})(req, res, function(err) { + if (err === undefined) { + return next(); + } + res.status(403).send("This device is not allowed to access your mirror.
Please check your config.js or config.js.sample to change this."); + }); + }); + app.use("/js", express.static(__dirname)); app.use("/config", express.static(path.resolve(__dirname + "/../config"))); app.use("/css", express.static(path.resolve(__dirname + "/../css"))); From b58314007794d92e7e33dcc5e30a82cd9f2b6ab8 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 29 Sep 2016 17:26:32 +0200 Subject: [PATCH 078/120] fix double quotes and config.js.sample --- config/config.js.sample | 4 ++-- js/defaults.js | 1 + js/server.js | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/config/config.js.sample b/config/config.js.sample index b10c9915..933b62fd 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -7,8 +7,8 @@ var config = { port: 8080, ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1'], - // you use ips with subnet mask: ['127.0.0.1', '127.0.0.1/24'] - // you use also use ip ranges: ['127.0.0.1', ['192.168.0.1', '192.168.0.100']] + // you can use ips with subnet mask: ['127.0.0.1', '127.0.0.1/24'] + // you can also use ip ranges: ['127.0.0.1', ['192.168.0.1', '192.168.0.100']] language: 'en', timeFormat: 24, diff --git a/js/defaults.js b/js/defaults.js index 0688595c..d1d78bce 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -10,6 +10,7 @@ var defaults = { port: 8080, kioskmode: false, + ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1'], language: "en", timeFormat: 24, diff --git a/js/server.js b/js/server.js index ddcf1dd3..edae0e12 100644 --- a/js/server.js +++ b/js/server.js @@ -10,19 +10,19 @@ var app = require("express")(); var server = require("http").Server(app); var io = require("socket.io")(server); var path = require("path"); -var ipfilter = require('express-ipfilter').IpFilter; +var ipfilter = require("express-ipfilter").IpFilter; var Server = function(config, callback) { console.log("Starting server op port " + config.port + " ... "); server.listen(config.port); if (config.ipWhitelist === undefined) { - config.ipWhitelist = ['127.0.0.1', '::ffff:127.0.0.1']; + config.ipWhitelist = ["127.0.0.1", "::ffff:127.0.0.1"]; console.log("Warning: Missing value (ipWhitelist) from config.js, assuming default (localhost access only): " + config.ipWhitelist); } app.use(function(req, res, next) { - var result = ipfilter(config.ipWhitelist, {mode: 'allow', log: false})(req, res, function(err) { + var result = ipfilter(config.ipWhitelist, {mode: "allow", log: false})(req, res, function(err) { if (err === undefined) { return next(); } From 66eb99e5068cd69d394946d0c635e4d8012f0b13 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 29 Sep 2016 17:49:54 +0200 Subject: [PATCH 079/120] transfer usage information to readme --- README.md | 2 ++ config/config.js.sample | 4 +--- js/defaults.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d86cca7c..986e600b 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,8 @@ The following properties can be configured: | **Option** | **Description** | | --- | --- | | `port` | The port on which the MagicMirror² server will run on. The default value is `8080`. | +| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1"]`.It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`). + | | `kioskmode` | This allows MagicMirror² to run in Kiosk Mode. It protects from other programs popping on top of your screen. The default value is `false`| | `language` | The language of the interface. (Note: Not all elements will be localized.) Possible values are `en`, `nl`, `ru`, `fr`, etc., but the default value is `en`. | | `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. | diff --git a/config/config.js.sample b/config/config.js.sample index 933b62fd..269492ba 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -6,9 +6,7 @@ var config = { port: 8080, - ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1'], - // you can use ips with subnet mask: ['127.0.0.1', '127.0.0.1/24'] - // you can also use ip ranges: ['127.0.0.1', ['192.168.0.1', '192.168.0.100']] + ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1"], language: 'en', timeFormat: 24, diff --git a/js/defaults.js b/js/defaults.js index d1d78bce..e2ee6151 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -10,7 +10,7 @@ var defaults = { port: 8080, kioskmode: false, - ipWhitelist: ['127.0.0.1', '::ffff:127.0.0.1'], + ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1"], language: "en", timeFormat: 24, From 2c758a9981a8b586639b6218c8c44f5e984fcfae Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 29 Sep 2016 17:52:22 +0200 Subject: [PATCH 080/120] remove warning message --- js/server.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/server.js b/js/server.js index edae0e12..cd3d77f2 100644 --- a/js/server.js +++ b/js/server.js @@ -16,10 +16,6 @@ var Server = function(config, callback) { console.log("Starting server op port " + config.port + " ... "); server.listen(config.port); - if (config.ipWhitelist === undefined) { - config.ipWhitelist = ["127.0.0.1", "::ffff:127.0.0.1"]; - console.log("Warning: Missing value (ipWhitelist) from config.js, assuming default (localhost access only): " + config.ipWhitelist); - } app.use(function(req, res, next) { var result = ipfilter(config.ipWhitelist, {mode: "allow", log: false})(req, res, function(err) { From 5899497aa73bbbf1deb3297f8fe29b7c044b4671 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 29 Sep 2016 17:55:32 +0200 Subject: [PATCH 081/120] log denied access attempts on server --- js/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/server.js b/js/server.js index cd3d77f2..e1a90946 100644 --- a/js/server.js +++ b/js/server.js @@ -22,6 +22,7 @@ var Server = function(config, callback) { if (err === undefined) { return next(); } + console.log(err.message); res.status(403).send("This device is not allowed to access your mirror.
Please check your config.js or config.js.sample to change this."); }); }); From c4048f4c7b6155c01681456f33002a1a279f2a41 Mon Sep 17 00:00:00 2001 From: Doug McInnes Date: Fri, 23 Sep 2016 21:48:49 -0700 Subject: [PATCH 082/120] fix typos in the module dev docs --- modules/README.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/modules/README.md b/modules/README.md index 61989a93..e7a23abd 100644 --- a/modules/README.md +++ b/modules/README.md @@ -6,11 +6,11 @@ This document describes the way to develop your own MagicMirror² modules. All modules are loaded in the `modules` folder. The default modules are grouped together in the `modules/default` folder. Your module should be placed in a subfolder of `modules`. Note that any file or folder your create in the `modules` folder will be ignored by git, allowing you to upgrade the MagicMirror² without the loss of your files. -A module can be placed in one single folder. Or multiple modules can be grouped in a subfoler. Note that name of the module must be unique. Even when a module with a similar name is placed in a different folder, they can't be loaded at the same time. +A module can be placed in one single folder. Or multiple modules can be grouped in a subfolder. Note that name of the module must be unique. Even when a module with a similar name is placed in a different folder, they can't be loaded at the same time. ### Files - **modulename/modulename.js** - This is your core module script. -- **modulename/node_helper.js** - This is an optional helper that whill be loaded by the node script. The node helper and module script can communicate with each other using an intergrated socket system. +- **modulename/node_helper.js** - This is an optional helper that will be loaded by the node script. The node helper and module script can communicate with each other using an intergrated socket system. - **modulename/public** - Any files in this folder can be accesed via the browser on `/modulename/filename.ext`. - **modulename/anyfileorfolder** Any other file or folder in the module folder can be used by the core module script. For example: *modulename/css/modulename.css* would be a good path for your additional module styles. @@ -104,7 +104,7 @@ The getScripts method is called to request any additional scripts that need to b getScripts: function() { return [ 'script.js', // will try to load it from the vendor folder, otherwise it will load is from the module folder. - 'moment.js', // this file is available in the vendor folder, so it doesn't need to be avialable in the module folder. + 'moment.js', // this file is available in the vendor folder, so it doesn't need to be available in the module folder. this.file('anotherfile.js'), // this file will be loaded straight from the module folder. 'https://code.jquery.com/jquery-2.2.3.min.js', // this file will be loaded from the jquery servers. ] @@ -154,7 +154,7 @@ getTranslations: function() { ####`getDom()` **Should return:** Dom Object -Whenever the MagicMirror needs to update the information on screen (because it starts, or because your module asked a refresh using `this.updateDom()`), the system calls the getDom method. This method should therefor return a dom object. +Whenever the MagicMirror needs to update the information on screen (because it starts, or because your module asked a refresh using `this.updateDom()`), the system calls the getDom method. This method should therefore return a dom object. **Example:** ````javascript @@ -202,7 +202,7 @@ notificationReceived: function(notification, payload, sender) { } ```` -**Note:** the system sends two notifiations when starting up. These notifications could come in handy! +**Note:** the system sends two notifications when starting up. These notifications could come in handy! - `ALL_MODULES_STARTED` - All modules are started. You can now send notifications to other modules. @@ -215,8 +215,8 @@ When using a node_helper, the node helper can send your module notifications. Wh - `notification` - String - The notification identifier. - `payload` - AnyType - The payload of a notification. -**Note 1:** When a node helper send a notification, all modules of that module type receive the same notifications.
-**Note 2:** The socket connection is established as soon as the module sends it's first message using [sendSocketNotification](thissendsocketnotificationnotification-payload). +**Note 1:** When a node helper sends a notification, all modules of that module type receive the same notifications.
+**Note 2:** The socket connection is established as soon as the module sends its first message using [sendSocketNotification](thissendsocketnotificationnotification-payload). **Example:** ````javascript @@ -234,7 +234,7 @@ When a module will be shown after it was previously hidden (using the `module.sh ### Module instance methods -Each module instance has some handy methods which can be helpfull building your module. +Each module instance has some handy methods which can be helpful building your module. ####`this.file(filename)` @@ -246,7 +246,7 @@ If you want to create a path to a file in your module folder, use the `file()` m ####`this.updateDom(speed)` ***speed* Number** - Optional. Animation speed in milliseconds.
-Whenever your module need to be updated, call the `updateDom(speed)` method. It requests the MagicMirror core to update it's dom object. If you define the speed, the content update will be animated, but only if the content will realy change. +Whenever your module need to be updated, call the `updateDom(speed)` method. It requests the MagicMirror core to update its dom object. If you define the speed, the content update will be animated, but only if the content will really change. As an example: the clock modules calls this method every second: @@ -265,7 +265,7 @@ start: function() { ***notification* String** - The notification identifier.
***payload* AnyType** - Optional. A notification payload.
-If you want to send a notification to all other modules, use the `sendNotification(notification, payload)`. All other modules will receive the message via the [notificationReceived](#notificationreceivednotification-payload-sender) method. In that case, the sender is automaticly set to the instance calling the sendNotification method. +If you want to send a notification to all other modules, use the `sendNotification(notification, payload)`. All other modules will receive the message via the [notificationReceived](#notificationreceivednotification-payload-sender) method. In that case, the sender is automatically set to the instance calling the sendNotification method. **Example:** ````javascript @@ -276,7 +276,7 @@ this.sendNotification('MYMODULE_READY_FOR_ACTION', {foo:bar}); ***notification* String** - The notification identifier.
***payload* AnyType** - Optional. A notification payload.
-If you want to send a notification to the node_helper, use the `sendSocketNotification(notification, payload)`. Only the node_helper of this module will recieve the socket notification. +If you want to send a notification to the node_helper, use the `sendSocketNotification(notification, payload)`. Only the node_helper of this module will receive the socket notification. **Example:** ````javascript @@ -287,7 +287,7 @@ this.sendSocketNotification('SET_CONFIG', this.config); ***speed* Number** - Optional, The speed of the hide animation in milliseconds. ***callback* Function** - Optional, The callback after the hide animation is finished. -To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itselve using `this.hide()`, but of course you can also hide an other module using `anOtherModule.hide()`. +To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itself using `this.hide()`, but of course you can also hide another module using `anOtherModule.hide()`. **Note 1:** If the hide animation is canceled, for instance because the show method is called before the hide animation was finished, the callback will not be called.
**Note 2:** If the hide animation is hijacked (an other method calls hide on the same module), the callback will not be called.
@@ -297,7 +297,7 @@ To hide a module, you can call the `hide(speed, callback)` method. You can call ***speed* Number** - Optional, The speed of the show animation in milliseconds. ***callback* Function** - Optional, The callback after the show animation is finished. -To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itselve using `this.show()`, but of course you can also show an other module using `anOtherModule.show()`. +To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itself using `this.show()`, but of course you can also show another module using `anOtherModule.show()`. **Note 1:** If the show animation is canceled, for instance because the hide method is called before the show animation was finished, the callback will not be called.
**Note 2:** If the show animation is hijacked (an other method calls show on the same module), the callback will not be called.
@@ -345,7 +345,7 @@ var NodeHelper = require("node_helper"); module.exports = NodeHelper.create({}); ```` -Of course, the above helper would not do anything usefull. So with the information above, you should be able to make it a bit more sophisticated. +Of course, the above helper would not do anything useful. So with the information above, you should be able to make it a bit more sophisticated. ### Available module instance properties @@ -389,7 +389,7 @@ This is a link to the IO instance. It will allow you to do some Socket.IO magic. This method is called when a node helper gets instantiated. In most cases you do not need to subclass this method. ####`start()` -This method is called when all node helper are loaded an the system is ready to boot up. The start method is a perfect place to define any additional module properties: +This method is called when all node helpers are loaded and the system is ready to boot up. The start method is a perfect place to define any additional module properties: **Example:** ````javascript @@ -400,12 +400,12 @@ start: function() { ```` ####`socketNotificationReceived: function(notification, payload)` -With this method, your node helper can receive notifications form your modules. When this method is called, it has 2 arguments: +With this method, your node helper can receive notifications from your modules. When this method is called, it has 2 arguments: - `notification` - String - The notification identifier. - `payload` - AnyType - The payload of a notification. -**Note:** The socket connection is established as soon as the module sends it's first message using [sendSocketNotification](thissendsocketnotificationnotification-payload). +**Note:** The socket connection is established as soon as the module sends its first message using [sendSocketNotification](thissendsocketnotificationnotification-payload). **Example:** ````javascript @@ -416,15 +416,15 @@ socketNotificationReceived: function(notification, payload) { ### Module instance methods -Each node helper has some handy methods which can be helpfull building your module. +Each node helper has some handy methods which can be helpful building your module. ####`this.sendSocketNotification(notification, payload)` ***notification* String** - The notification identifier.
***payload* AnyType** - Optional. A notification payload.
-If you want to send a notification to all your modules, use the `sendSocketNotification(notification, payload)`. Only the module of your module type will recieve the socket notification. +If you want to send a notification to all your modules, use the `sendSocketNotification(notification, payload)`. Only the module of your module type will receive the socket notification. -**Note:** Since all instances of you module will receive the notifications, it's your task to make sure the right module responds to your messages. +**Note:** Since all instances of your module will receive the notifications, it's your task to make sure the right module responds to your messages. **Example:** ````javascript @@ -447,10 +447,10 @@ To make a selection of all currently loaded module instances, run the `MM.getMod #####`.withClass(classnames)` -***classnames* String or Array** - The class names on which you want to filer. +***classnames* String or Array** - The class names on which you want to filter. **Returns Array** - An array with module instances.
-If you want to make a selection based on one ore more class names, use the withClass method on a result of the `MM.getModules()` method. The argument of the `withClass(classname)` method can be an array, or space separated string. +If you want to make a selection based on one or more class names, use the withClass method on a result of the `MM.getModules()` method. The argument of the `withClass(classname)` method can be an array, or space separated string. **Examples:** ````javascript @@ -476,7 +476,7 @@ var modules = MM.getModules().exceptWithClass(['classname1','classname2']); ***module* Module Object** - The reference to a module you want to remove from the results. **Returns Array** - An array with module instances.
-If you to remove a specific module instance from a selection based on a classname, use the exceptWithClass method on a result of the `MM.getModules()` method. This can be helpfull if you want to select all module instances except the instance of your module. +If you to remove a specific module instance from a selection based on a classname, use the exceptWithClass method on a result of the `MM.getModules()` method. This can be helpful if you want to select all module instances except the instance of your module. **Examples:** ````javascript From 5edf377f4b030ebf2dfffcce23c7b081c1cb514e Mon Sep 17 00:00:00 2001 From: Harri Kapanen Date: Fri, 30 Sep 2016 20:44:53 +0300 Subject: [PATCH 083/120] Finnish translation --- CHANGELOG.md | 1 + translations/fi.json | 28 ++++++++++++++++++++++++++++ translations/translations.js | 1 + 3 files changed, 30 insertions(+) create mode 100644 translations/fi.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 74cb3f7e..3f40dec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [2.1.0] - Unreleased ### Added +- Finnish translation. - Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) - Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)) diff --git a/translations/fi.json b/translations/fi.json new file mode 100644 index 00000000..f370e41c --- /dev/null +++ b/translations/fi.json @@ -0,0 +1,28 @@ +{ + /* GENERAL */ + "LOADING": "Lataa …", + + /* CALENDAR */ + "TODAY": "Tänään", + "TOMORROW": "Huomenna", + "RUNNING": "Meneillään", + "EMPTY": "Ei tulevia tapahtumia.", + + /* WEATHER */ + "N": "P", + "NNE": "PPI", + "NE": "PI", + "ENE": "IPI", + "E": "I", + "ESE": "IEI", + "SE": "EI", + "SSE": "EEI", + "S": "E", + "SSW": "EEL", + "SW": "EL", + "WSW": "LEL", + "W": "L", + "WNW": "LPL", + "NW": "PL", + "NNW": "PPL" +} diff --git a/translations/translations.js b/translations/translations.js index 2a458ef2..09036efc 100644 --- a/translations/translations.js +++ b/translations/translations.js @@ -9,6 +9,7 @@ var translations = { "en" : "translations/en.json", // English "nl" : "translations/nl.json", // Dutch "de" : "translations/de.json", // German + "fi" : "translations/fi.json", // Suomi "fr" : "translations/fr.json", // French "fy" : "translations/fy.json", // Frysk "es" : "translations/es.json", // Spanish From cbb82ed63574a63727907245e37119d877b6d093 Mon Sep 17 00:00:00 2001 From: fewieden Date: Sat, 1 Oct 2016 00:38:14 +0200 Subject: [PATCH 084/120] replace system output with MagicMirror splash screen on boot --- CHANGELOG.md | 1 + installers/raspberry.sh | 28 +++++++++++++++++ splashscreen/MagicMirror.plymouth | 8 +++++ splashscreen/MagicMirror.script | 50 ++++++++++++++++++++++++++++++ splashscreen/splash.png | Bin 0 -> 19621 bytes 5 files changed, 87 insertions(+) create mode 100644 splashscreen/MagicMirror.plymouth create mode 100644 splashscreen/MagicMirror.script create mode 100644 splashscreen/splash.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f40dec2..25447243 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Finnish translation. - Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) - Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)) +- Add Splash screen on boot. ### Updated - Modified translations for Frysk. diff --git a/installers/raspberry.sh b/installers/raspberry.sh index ce37e86f..4c42dcde 100644 --- a/installers/raspberry.sh +++ b/installers/raspberry.sh @@ -113,6 +113,34 @@ else exit; fi +# Check if plymouth is installed (default with PIXEL desktop environment), then install custom splashscreen. +echo -e "\e[96mCheck plymouth installation ...\e[0m" +if command_exists plymouth; then + THEME_DIR="/usr/share/plymouth/themes" + echo -e "\e[90mSplashscreen: Checking themes directory.\e[0m" + if [ -d $THEME_DIR ]; then + echo -e "\e[90mSplashscreen: Create theme directory if not exists.\e[0m" + if [ ! -d $THEME_DIR/MagicMirror ]; then + sudo mkdir $THEME_DIR/MagicMirror + fi + + if sudo cp ~/MagicMirror/splashscreen/splash.png $THEME_DIR/MagicMirror/splash.png && sudo cp ~/MagicMirror/splashscreen/MagicMirror.plymouth $THEME_DIR/MagicMirror/MagicMirror.plymouth && sudo cp ~/MagicMirror/splashscreen/MagicMirror.script $THEME_DIR/MagicMirror/MagicMirror.script; then + echo -e "\e[90mSplashscreen: Theme copied successfully.\e[0m" + if sudo plymouth-set-default-theme -R MagicMirror; then + echo -e "\e[92mSplashscreen: Changed theme to MagicMirror successfully.\e[0m" + else + echo -e "\e[91mSplashscreen: Couldn't change theme to MagicMirror!\e[0m" + fi + else + echo -e "\e[91mSplashscreen: Copying theme failed!\e[0m" + fi + else + echo -e "\e[91mSplashscreen: Themes folder doesn't exist!\e[0m" + fi +else + echo -e "\e[93mplymouth is not installed.\e[0m"; +fi + echo " " echo -e "\e[92mWe're ready! Run \e[1m\e[97mDISPLAY=:0 npm start\e[0m\e[92m from the ~/MagicMirror directory to start your MagicMirror.\e[0m" echo " " diff --git a/splashscreen/MagicMirror.plymouth b/splashscreen/MagicMirror.plymouth new file mode 100644 index 00000000..b6887bf5 --- /dev/null +++ b/splashscreen/MagicMirror.plymouth @@ -0,0 +1,8 @@ +[Plymouth Theme] +Name=MagicMirror +Description=Mirror Splash +ModuleName=script + +[script] +ImageDir=/usr/share/plymouth/themes/MagicMirror +ScriptFile=/usr/share/plymouth/themes/MagicMirror/MagicMirror.script diff --git a/splashscreen/MagicMirror.script b/splashscreen/MagicMirror.script new file mode 100644 index 00000000..d7e7b860 --- /dev/null +++ b/splashscreen/MagicMirror.script @@ -0,0 +1,50 @@ +screen_width = Window.GetWidth(); +screen_height = Window.GetHeight(); + +theme_image = Image("splash.png"); +image_width = theme_image.GetWidth(); +image_height = theme_image.GetHeight(); + +scale_x = image_width / screen_width; +scale_y = image_height / screen_height; + +flag = 1; + +if (scale_x > 1 || scale_y > 1) +{ + if (scale_x > scale_y) + { + resized_image = theme_image.Scale (screen_width, image_height / scale_x); + image_x = 0; + image_y = (screen_height - ((image_height * screen_width) / image_width)) / 2; + } + else + { + resized_image = theme_image.Scale (image_width / scale_y, screen_height); + image_x = (screen_width - ((image_width * screen_height) / image_height)) / 2; + image_y = 0; + } +} +else +{ + resized_image = theme_image.Scale (image_width, image_height); + image_x = (screen_width - image_width) / 2; + image_y = (screen_height - image_height) / 2; +} + +if (Plymouth.GetMode() != "shutdown") +{ + sprite = Sprite (resized_image); + sprite.SetPosition (image_x, image_y, -100); +} + +message_sprite = Sprite(); +message_sprite.SetPosition(screen_width * 0.1, screen_height * 0.9, 10000); + +fun message_callback (text) { + my_image = Image.Text(text, 1, 1, 1); + message_sprite.SetImage(my_image); + sprite.SetImage (resized_image); +} + +Plymouth.SetUpdateStatusFunction(message_callback); diff --git a/splashscreen/splash.png b/splashscreen/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..f76b0cff5617be2df50daddabc4e9385d38a2ade GIT binary patch literal 19621 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 literal 0 HcmV?d00001 From 430193891fc1d0d9b033b7021b97db6a3aab64e3 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 1 Oct 2016 10:35:22 +0200 Subject: [PATCH 085/120] Fix Config keys. --- Gruntfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index e5bc690b..c47f55b9 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -47,7 +47,6 @@ module.exports = function(grunt) { "MD018": false, "MD012": false, "MD026": false, - "MD036": false, "MD038": false } }, From b267491934fcdc46e361f4876cf201a2c8785314 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 1 Oct 2016 13:49:41 +0200 Subject: [PATCH 086/120] Add IPv6 loopback IP address to default whitelist. --- config/config.js.sample | 2 +- js/defaults.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.js.sample b/config/config.js.sample index 269492ba..e611f872 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -6,7 +6,7 @@ var config = { port: 8080, - ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1"], + ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], language: 'en', timeFormat: 24, diff --git a/js/defaults.js b/js/defaults.js index e2ee6151..0ec033c3 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -10,7 +10,7 @@ var defaults = { port: 8080, kioskmode: false, - ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1"], + ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], language: "en", timeFormat: 24, From d8d425c963c412740c528a46e5ec4482db603295 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 1 Oct 2016 14:06:10 +0200 Subject: [PATCH 087/120] Visual changes. --- .../default/currentweather/currentweather.js | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index 170e9ab6..587080db 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -118,6 +118,7 @@ Module.register("currentweather",{ var small = document.createElement("div"); small.className = "normal medium"; + var windIcon = document.createElement("span"); windIcon.className = "wi wi-strong-wind dimmed"; small.appendChild(windIcon); @@ -135,6 +136,18 @@ Module.register("currentweather",{ spacer.innerHTML = " "; small.appendChild(spacer); + if (this.config.showHumidity) { + var humidity = document.createElement("span"); + humidity.innerHTML = this.humidity; + + var humidityIcon = document.createElement("sup"); + humidityIcon.className = "wi wi-humidity humidityIcon"; + humidityIcon.innerHTML = " "; + + small.appendChild(humidity); + small.appendChild(humidityIcon); + } + var sunriseSunsetIcon = document.createElement("span"); sunriseSunsetIcon.className = "wi dimmed " + this.sunriseSunsetIcon; small.appendChild(sunriseSunsetIcon); @@ -145,24 +158,6 @@ Module.register("currentweather",{ wrapper.appendChild(small); - if (this.config.showHumidity) { - var middle = document.createElement("div"); - middle.className = "normal small humidity-padding"; - - var humidityIcon = document.createElement("span"); - humidityIcon.className = "wi wi-humidity humidityIcon"; - small.appendChild(sunriseSunsetIcon); - - var humidity = document.createElement("span"); - humidity.innerHTML = this.humidity + "%"; - var br = document.createElement("br"); - - middle.appendChild(humidityIcon); - middle.appendChild(humidity); - middle.appendChild(br); - wrapper.appendChild(middle); - } - var large = document.createElement("div"); large.className = "large light"; From ee48a5660341a120e25ed737f4d8b424cd30dcdf Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 1 Oct 2016 14:08:15 +0200 Subject: [PATCH 088/120] Add info about humidity. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc4bde69..09381c6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)). - Added ability to change the point of time when calendar events get relative. - Add Splash screen on boot. +- Add option to show humidity in currentWeather module. ### Updated - Modified translations for Frysk. From c9e6af96d08ba6a836d3a4c761b530f59353990d Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 4 Oct 2016 16:19:33 +0200 Subject: [PATCH 089/120] Change update information. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 856ab6e0..9c3a3ce5 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ The following wiki links are helpful in the configuration of your MagicMirror² If you want to update your MagicMirror² to the latest version, use your terminal to go to your Magic Mirror folder and type the following command: ```bash -git pull +git pull && npm install ``` If you changed nothing more than the config or the modules, this should work without any problems. From 0671e7d456296c357999068e20d1b1a8d1619939 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 4 Oct 2016 16:21:53 +0200 Subject: [PATCH 090/120] Add update information. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09381c6a..7d95b9b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [2.1.0] - Unreleased +**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install` + ### Added - Finnish translation. - Danish translation. From 67582d388ad0cf2e80e18d7e7e5eaf8b298c3c5c Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 4 Oct 2016 16:25:39 +0200 Subject: [PATCH 091/120] Fix Table. --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9c3a3ce5..1a06ca6c 100644 --- a/README.md +++ b/README.md @@ -73,18 +73,17 @@ Type `git status` to see your changes, if there are any, you can reset them with The following properties can be configured: - | **Option** | **Description** | | --- | --- | | `port` | The port on which the MagicMirror² server will run on. The default value is `8080`. | -| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1"]`.It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`). - | +| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1"]`.It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`).| | `kioskmode` | This allows MagicMirror² to run in Kiosk Mode. It protects from other programs popping on top of your screen. The default value is `false`| | `language` | The language of the interface. (Note: Not all elements will be localized.) Possible values are `en`, `nl`, `ru`, `fr`, etc., but the default value is `en`. | | `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. | | `units` | The units that will be used in the default weather modules. Possible values are `metric` or `imperial`. The default is `metric`. | | `modules` | An array of active modules. **The array must contain objects. See the next table below for more information.** | + Module configuration: | **Option** | **Description** | From 7dab00be879f8d0f6c96e7134372a2939d2e1620 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 4 Oct 2016 16:26:35 +0200 Subject: [PATCH 092/120] Fix info about default setting. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a06ca6c..d8ee1676 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ The following properties can be configured: | **Option** | **Description** | | --- | --- | | `port` | The port on which the MagicMirror² server will run on. The default value is `8080`. | -| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1"]`.It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`).| +| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1","::1"]`. It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`).| | `kioskmode` | This allows MagicMirror² to run in Kiosk Mode. It protects from other programs popping on top of your screen. The default value is `false`| | `language` | The language of the interface. (Note: Not all elements will be localized.) Possible values are `en`, `nl`, `ru`, `fr`, etc., but the default value is `en`. | | `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. | From d5d22844ab17bbf084e560282d22f5b4bbbb702b Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Tue, 4 Oct 2016 16:27:06 +0200 Subject: [PATCH 093/120] Fix info about default setting. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8ee1676..0f9ec65d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ The following properties can be configured: | **Option** | **Description** | | --- | --- | | `port` | The port on which the MagicMirror² server will run on. The default value is `8080`. | -| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1","::1"]`. It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`).| +| `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². The default value is `["127.0.0.1", "::ffff:127.0.0.1", "::1"]`. It is possible to specify IPs with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or define ip ranges (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`).| | `kioskmode` | This allows MagicMirror² to run in Kiosk Mode. It protects from other programs popping on top of your screen. The default value is `false`| | `language` | The language of the interface. (Note: Not all elements will be localized.) Possible values are `en`, `nl`, `ru`, `fr`, etc., but the default value is `en`. | | `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. | From 2b4939a8756237f50f0dc81b40717ab8947eb4db Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 13:10:33 +0200 Subject: [PATCH 094/120] Add VSCode IntelliSense support. --- jsconfig.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 jsconfig.json diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 00000000..2b354edc --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=759670 + // for the documentation about the jsconfig.json format + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "allowSyntheticDefaultImports": true + }, + "exclude": [ + "modules", + "node_modules" + ] +} From af63f4098f5d0c58deb0523d9baafdc2fdf80927 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 13:24:56 +0200 Subject: [PATCH 095/120] Improve logger. --- js/logger.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/js/logger.js b/js/logger.js index 5b2df990..6c073720 100644 --- a/js/logger.js +++ b/js/logger.js @@ -13,35 +13,35 @@ var Log = (function() { return { - info: function(message) { - console.info(message); + info: function() { + console.info.apply(this, arguments); }, - log: function(message) { - console.log(message); + log: function() { + console.log.apply(this, arguments); }, - error: function(message) { - console.error(message); + error: function() { + console.error.apply(this, arguments); }, - warn: function(message) { - console.warn(message); + warn: function() { + console.warn.apply(this, arguments); }, - group: function(message) { - console.group(message); + group: function() { + console.group.apply(this, arguments); }, - groupCollapsed: function(message) { - console.groupCollapsed(message); + groupCollapsed: function() { + console.groupCollapsed.apply(this, arguments); }, groupEnd: function() { console.groupEnd(); }, - time: function(message) { - console.time(message); + time: function() { + console.time.apply(this, arguments); }, - timeEnd: function(message) { - console.timeEnd(message); + timeEnd: function() { + console.timeEnd.apply(this, arguments); }, - timeStamp: function(message) { - console.timeStamp(message); + timeStamp: function() { + console.timeStamp.apply(this, arguments); } }; })(); From 55371f9c78e3412707aa5368e1debf939c1cedae Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 14:25:53 +0200 Subject: [PATCH 096/120] Improve object instantiation to prevent reference errors. --- js/class.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/js/class.js b/js/class.js index 9d04944e..2b011b29 100644 --- a/js/class.js +++ b/js/class.js @@ -11,6 +11,24 @@ // The base Class implementation (does nothing) this.Class = function() {}; + //Define the clone method for later use. + function cloneObject(obj) { + if (obj === null || typeof obj !== "object") { + return obj; + } + + var temp = obj.constructor(); // give temp the original obj's constructor + for (var key in obj) { + temp[key] = cloneObject(obj[key]); + + if (key === "lockStrings") { + Log.log(key); + } + } + + return temp; + } + // Create a new Class that inherits from this class Class.extend = function(prop) { var _super = this.prototype; @@ -21,6 +39,11 @@ var prototype = new this(); initializing = false; + // Make a copy of all prototype properies, to prevent reference issues. + for (var name in prototype) { + prototype[name] = cloneObject(prototype[name]); + } + // Copy the properties over onto the new prototype for (var name in prop) { // Check if we're overwriting an existing function From 4dc5bbe6012042d9b40b6fa2c73a7cdcd5e7b396 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 15:00:59 +0200 Subject: [PATCH 097/120] First implementation of Visibility locking. --- js/main.js | 49 ++++++++++++++++++++++++++----- js/module.js | 32 +++++++++++++++++---- modules/README.md | 73 ++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 138 insertions(+), 16 deletions(-) diff --git a/js/main.js b/js/main.js index c0c63006..a8572c6a 100644 --- a/js/main.js +++ b/js/main.js @@ -174,7 +174,17 @@ var MM = (function() { * argument speed Number - The speed of the hide animation. * argument callback function - Called when the animation is done. */ - var hideModule = function(module, speed, callback) { + var hideModule = function(module, speed, callback, options) { + options = options || {}; + + // set lockString if set in options. + if (options.lockString) { + Log.log("Has lockstring: " + options.lockString); + if (module.lockStrings.indexOf(options.lockString) === -1) { + module.lockStrings.push(options.lockString); + } + } + var moduleWrapper = document.getElementById(module.identifier); if (moduleWrapper !== null) { moduleWrapper.style.transition = "opacity " + speed / 1000 + "s"; @@ -183,7 +193,7 @@ var MM = (function() { clearTimeout(module.showHideTimer); module.showHideTimer = setTimeout(function() { // To not take up any space, we just make the position absolute. - // since it"s fade out anyway, we can see it lay above or + // since it's fade out anyway, we can see it lay above or // below other modules. This works way better than adjusting // the .display property. moduleWrapper.style.position = "absolute"; @@ -200,7 +210,30 @@ var MM = (function() { * argument speed Number - The speed of the show animation. * argument callback function - Called when the animation is done. */ - var showModule = function(module, speed, callback) { + var showModule = function(module, speed, callback, options) { + options = options || {}; + + // remove lockString if set in options. + if (options.lockString) { + var index = module.lockStrings.indexOf(options.lockString) + if ( index !== -1) { + module.lockStrings.splice(index, 1); + } + } + + // Check if there are no more lockstrings set, or the force option is set. + // Otherwise cancel show action. + if (module.lockStrings.length !== 0 && options.force !== true) { + Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(",")); + return; + } + + // If forced show, clean current lockstrings. + if (module.lockStrings.length !== 0 && options.force === true) { + Log.log("Force show of module: " + module.name); + module.lockStrings = []; + } + var moduleWrapper = document.getElementById(module.identifier); if (moduleWrapper !== null) { moduleWrapper.style.transition = "opacity " + speed / 1000 + "s"; @@ -419,10 +452,11 @@ var MM = (function() { * argument module Module - The module hide. * argument speed Number - The speed of the hide animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - hideModule: function(module, speed, callback) { + hideModule: function(module, speed, callback, options) { module.hidden = true; - hideModule(module, speed, callback); + hideModule(module, speed, callback, options); }, /* showModule(module, speed, callback) @@ -431,10 +465,11 @@ var MM = (function() { * argument module Module - The module show. * argument speed Number - The speed of the show animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - showModule: function(module, speed, callback) { + showModule: function(module, speed, callback, options) { module.hidden = false; - showModule(module, speed, callback); + showModule(module, speed, callback, options); } }; diff --git a/js/module.js b/js/module.js index 9c26bc7b..fe669cee 100644 --- a/js/module.js +++ b/js/module.js @@ -20,6 +20,10 @@ var Module = Class.extend({ // Timer reference used for showHide animation callbacks. showHideTimer: null, + // Array to store lockStrings. These stings are used to lock + // visibility when hiding and showing module. + lockStrings: [], + /* init() * Is called when the module is instantiated. */ @@ -314,15 +318,24 @@ var Module = Class.extend({ * * argument speed Number - The speed of the hide animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - hide: function(speed, callback) { + hide: function(speed, callback, options) { + if (typeof callback === "object") { + options = callback; + callback = function() {}; + } + callback = callback || function() {}; + options = options || {}; var self = this; MM.hideModule(self, speed, function() { self.suspend(); callback(); - }); + }, options); + + Log.log(options); }, /* showModule(module, speed, callback) @@ -330,10 +343,19 @@ var Module = Class.extend({ * * argument speed Number - The speed of the show animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - show: function(speed, callback) { + show: function(speed, callback, options) { + if (typeof callback === "object") { + options = callback; + callback = function() {}; + } + + callback = callback || function() {}; + options = options || {}; + this.resume(); - MM.showModule(this, speed, callback); + MM.showModule(this, speed, callback, options); } }); @@ -347,7 +369,7 @@ Module.create = function(name) { return obj; } - var temp = obj.constructor(); // give temp the original obj"s constructor + var temp = obj.constructor(); // give temp the original obj's constructor for (var key in obj) { temp[key] = cloneObject(obj[key]); } diff --git a/modules/README.md b/modules/README.md index e7a23abd..ec9c018c 100644 --- a/modules/README.md +++ b/modules/README.md @@ -283,26 +283,91 @@ If you want to send a notification to the node_helper, use the `sendSocketNotifi this.sendSocketNotification('SET_CONFIG', this.config); ```` -####`this.hide(speed, callback)` -***speed* Number** - Optional, The speed of the hide animation in milliseconds. +####`this.hide(speed, callback, options)` +***speed* Number** - Optional (Required when setting callback or options), The speed of the hide animation in milliseconds. ***callback* Function** - Optional, The callback after the hide animation is finished. +***options* Function** - Optional, Object with additional options for the hide action (see below). To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itself using `this.hide()`, but of course you can also hide another module using `anOtherModule.hide()`. +Possible configurable options: +* `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. It's considered best practice to use your modules identifier as the locksString: `this.identifier`. See *visibility locking* below. + + **Note 1:** If the hide animation is canceled, for instance because the show method is called before the hide animation was finished, the callback will not be called.
**Note 2:** If the hide animation is hijacked (an other method calls hide on the same module), the callback will not be called.
**Note 3:** If the dom is not yet created, the hide method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender). -####`this.show(speed, callback)` -***speed* Number** - Optional, The speed of the show animation in milliseconds. + +####`this.show(speed, callback, options)` +***speed* Number** - Optional (Required when setting callback or options), The speed of the show animation in milliseconds. ***callback* Function** - Optional, The callback after the show animation is finished. +***options* Function** - Optional, Object with additional options for the show action (see below). To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itself using `this.show()`, but of course you can also show another module using `anOtherModule.show()`. +Possible configurable options: +* `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. See *visibility locking* below. +* `force` - Boolean - When setting the force tag to `true`, the locking mechanism will be overwritten. Use this option with caution. It's considered best practice to let the usage of the force option be user configurable. See *visibility locking* below. + **Note 1:** If the show animation is canceled, for instance because the hide method is called before the show animation was finished, the callback will not be called.
**Note 2:** If the show animation is hijacked (an other method calls show on the same module), the callback will not be called.
**Note 3:** If the dom is not yet created, the show method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender). +####Visibility locking +Visiblity locking helps the module system to prevent unwanted hide/show actions. The following scenario explains the concept: + +**Module B asks module A to hide:** +```` +moduleA.hide(0, {lockString: "module_b_identifier"}); +```` +Module A is now hidden, and has an lock array with the following strings: +```` +moduleA.lockStrings == ["module_b_identifier"] +moduleA.hidden == true +```` +**Module C asks module A to hide:** +```` +moduleA.hide(0, {lockString: "module_c_identifier"}); +```` +Module A is now hidden, and has an lock array with the following strings: +```` +moduleA.lockStrings == ["module_b_identifier", "module_c_identifier"] +moduleA.hidden == true +```` +**Module B asks module A to show:** +```` +moduleA.show(0, {lockString: "module_b_identifier"}); +```` +The lockString will be removed from moduleA’s locks array, but since there still is an other lock string available, the module remains hidden: +```` +moduleA.lockStrings == ["module_c_identifier"] +moduleA.hidden == true +```` +**Module C asks module A to show:** +```` +moduleA.show(0, {lockString: "module_c_identifier"}); +```` +The lockString will be removed from moduleA’s locks array, and since this will result in an empty lock array, the module will be visible: +```` +moduleA.lockStrings == [] +moduleA.hidden == false +```` + +**Note:** The locking mechanism can be overwritten by using the force tag: +```` +moduleA.show(0, {force: true}); +```` +This will reset the lockstring array, and will show the module. +```` +moduleA.lockStrings == [] +moduleA.hidden == false +```` + +Use this `force` method with caution. See `show()` method for more information. + + + ####`this.translate(identifier)` ***identifier* String** - Identifier of the string that should be translated. From 8d8374b8e2630d1e0cb6bb53624aecc10c0a694b Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 15:00:59 +0200 Subject: [PATCH 098/120] First implementation of Visibility locking. --- js/main.js | 49 ++++++++++++++++++++++++++----- js/module.js | 32 ++++++++++++++++---- modules/README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 140 insertions(+), 16 deletions(-) diff --git a/js/main.js b/js/main.js index c0c63006..a8572c6a 100644 --- a/js/main.js +++ b/js/main.js @@ -174,7 +174,17 @@ var MM = (function() { * argument speed Number - The speed of the hide animation. * argument callback function - Called when the animation is done. */ - var hideModule = function(module, speed, callback) { + var hideModule = function(module, speed, callback, options) { + options = options || {}; + + // set lockString if set in options. + if (options.lockString) { + Log.log("Has lockstring: " + options.lockString); + if (module.lockStrings.indexOf(options.lockString) === -1) { + module.lockStrings.push(options.lockString); + } + } + var moduleWrapper = document.getElementById(module.identifier); if (moduleWrapper !== null) { moduleWrapper.style.transition = "opacity " + speed / 1000 + "s"; @@ -183,7 +193,7 @@ var MM = (function() { clearTimeout(module.showHideTimer); module.showHideTimer = setTimeout(function() { // To not take up any space, we just make the position absolute. - // since it"s fade out anyway, we can see it lay above or + // since it's fade out anyway, we can see it lay above or // below other modules. This works way better than adjusting // the .display property. moduleWrapper.style.position = "absolute"; @@ -200,7 +210,30 @@ var MM = (function() { * argument speed Number - The speed of the show animation. * argument callback function - Called when the animation is done. */ - var showModule = function(module, speed, callback) { + var showModule = function(module, speed, callback, options) { + options = options || {}; + + // remove lockString if set in options. + if (options.lockString) { + var index = module.lockStrings.indexOf(options.lockString) + if ( index !== -1) { + module.lockStrings.splice(index, 1); + } + } + + // Check if there are no more lockstrings set, or the force option is set. + // Otherwise cancel show action. + if (module.lockStrings.length !== 0 && options.force !== true) { + Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(",")); + return; + } + + // If forced show, clean current lockstrings. + if (module.lockStrings.length !== 0 && options.force === true) { + Log.log("Force show of module: " + module.name); + module.lockStrings = []; + } + var moduleWrapper = document.getElementById(module.identifier); if (moduleWrapper !== null) { moduleWrapper.style.transition = "opacity " + speed / 1000 + "s"; @@ -419,10 +452,11 @@ var MM = (function() { * argument module Module - The module hide. * argument speed Number - The speed of the hide animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - hideModule: function(module, speed, callback) { + hideModule: function(module, speed, callback, options) { module.hidden = true; - hideModule(module, speed, callback); + hideModule(module, speed, callback, options); }, /* showModule(module, speed, callback) @@ -431,10 +465,11 @@ var MM = (function() { * argument module Module - The module show. * argument speed Number - The speed of the show animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - showModule: function(module, speed, callback) { + showModule: function(module, speed, callback, options) { module.hidden = false; - showModule(module, speed, callback); + showModule(module, speed, callback, options); } }; diff --git a/js/module.js b/js/module.js index 9c26bc7b..fe669cee 100644 --- a/js/module.js +++ b/js/module.js @@ -20,6 +20,10 @@ var Module = Class.extend({ // Timer reference used for showHide animation callbacks. showHideTimer: null, + // Array to store lockStrings. These stings are used to lock + // visibility when hiding and showing module. + lockStrings: [], + /* init() * Is called when the module is instantiated. */ @@ -314,15 +318,24 @@ var Module = Class.extend({ * * argument speed Number - The speed of the hide animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - hide: function(speed, callback) { + hide: function(speed, callback, options) { + if (typeof callback === "object") { + options = callback; + callback = function() {}; + } + callback = callback || function() {}; + options = options || {}; var self = this; MM.hideModule(self, speed, function() { self.suspend(); callback(); - }); + }, options); + + Log.log(options); }, /* showModule(module, speed, callback) @@ -330,10 +343,19 @@ var Module = Class.extend({ * * argument speed Number - The speed of the show animation. * argument callback function - Called when the animation is done. + * argument options object - Optional settings for the hide method. */ - show: function(speed, callback) { + show: function(speed, callback, options) { + if (typeof callback === "object") { + options = callback; + callback = function() {}; + } + + callback = callback || function() {}; + options = options || {}; + this.resume(); - MM.showModule(this, speed, callback); + MM.showModule(this, speed, callback, options); } }); @@ -347,7 +369,7 @@ Module.create = function(name) { return obj; } - var temp = obj.constructor(); // give temp the original obj"s constructor + var temp = obj.constructor(); // give temp the original obj's constructor for (var key in obj) { temp[key] = cloneObject(obj[key]); } diff --git a/modules/README.md b/modules/README.md index e7a23abd..d157c983 100644 --- a/modules/README.md +++ b/modules/README.md @@ -283,26 +283,93 @@ If you want to send a notification to the node_helper, use the `sendSocketNotifi this.sendSocketNotification('SET_CONFIG', this.config); ```` -####`this.hide(speed, callback)` -***speed* Number** - Optional, The speed of the hide animation in milliseconds. +####`this.hide(speed, callback, options)` +***speed* Number** - Optional (Required when setting callback or options), The speed of the hide animation in milliseconds. ***callback* Function** - Optional, The callback after the hide animation is finished. +***options* Function** - Optional, Object with additional options for the hide action (see below). To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itself using `this.hide()`, but of course you can also hide another module using `anOtherModule.hide()`. +Possible configurable options: + +- `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. It's considered best practice to use your modules identifier as the locksString: `this.identifier`. See *visibility locking* below. + + **Note 1:** If the hide animation is canceled, for instance because the show method is called before the hide animation was finished, the callback will not be called.
**Note 2:** If the hide animation is hijacked (an other method calls hide on the same module), the callback will not be called.
**Note 3:** If the dom is not yet created, the hide method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender). -####`this.show(speed, callback)` -***speed* Number** - Optional, The speed of the show animation in milliseconds. + +####`this.show(speed, callback, options)` +***speed* Number** - Optional (Required when setting callback or options), The speed of the show animation in milliseconds. ***callback* Function** - Optional, The callback after the show animation is finished. +***options* Function** - Optional, Object with additional options for the show action (see below). To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itself using `this.show()`, but of course you can also show another module using `anOtherModule.show()`. +Possible configurable options: + +- `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. See *visibility locking- below. +- `force` - Boolean - When setting the force tag to `true`, the locking mechanism will be overwritten. Use this option with caution. It's considered best practice to let the usage of the force option be use- configurable. See *visibility locking* below. + **Note 1:** If the show animation is canceled, for instance because the hide method is called before the show animation was finished, the callback will not be called.
**Note 2:** If the show animation is hijacked (an other method calls show on the same module), the callback will not be called.
**Note 3:** If the dom is not yet created, the show method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender). +####Visibility locking +Visiblity locking helps the module system to prevent unwanted hide/show actions. The following scenario explains the concept: + +**Module B asks module A to hide:** +```` +moduleA.hide(0, {lockString: "module_b_identifier"}); +```` +Module A is now hidden, and has an lock array with the following strings: +```` +moduleA.lockStrings == ["module_b_identifier"] +moduleA.hidden == true +```` +**Module C asks module A to hide:** +```` +moduleA.hide(0, {lockString: "module_c_identifier"}); +```` +Module A is now hidden, and has an lock array with the following strings: +```` +moduleA.lockStrings == ["module_b_identifier", "module_c_identifier"] +moduleA.hidden == true +```` +**Module B asks module A to show:** +```` +moduleA.show(0, {lockString: "module_b_identifier"}); +```` +The lockString will be removed from moduleA’s locks array, but since there still is an other lock string available, the module remains hidden: +```` +moduleA.lockStrings == ["module_c_identifier"] +moduleA.hidden == true +```` +**Module C asks module A to show:** +```` +moduleA.show(0, {lockString: "module_c_identifier"}); +```` +The lockString will be removed from moduleA’s locks array, and since this will result in an empty lock array, the module will be visible: +```` +moduleA.lockStrings == [] +moduleA.hidden == false +```` + +**Note:** The locking mechanism can be overwritten by using the force tag: +```` +moduleA.show(0, {force: true}); +```` +This will reset the lockstring array, and will show the module. +```` +moduleA.lockStrings == [] +moduleA.hidden == false +```` + +Use this `force` method with caution. See `show()` method for more information. + + + ####`this.translate(identifier)` ***identifier* String** - Identifier of the string that should be translated. From 0433432e6295e6cf217abda2426cfb36092d45ba Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 15:15:38 +0200 Subject: [PATCH 099/120] Add information about recent changes. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d95b9b0..08cc8850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,14 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added ability to change the point of time when calendar events get relative. - Add Splash screen on boot. - Add option to show humidity in currentWeather module. +- Add Visibility locking to module system. See [documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. +- Add VSCode IntelliSense support. ### Updated - Modified translations for Frysk. - Updated package.json as a result of Snyk security update. +- Improve object instantiation to prevent reference errors. +- Improve logger. `Log.log()` now accepts multiple arguments. ### Changed - Calendar times are now uniformly capitalized. From 15a5e3c77936e8cb4e2fff87ab458c8f705169c9 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 15:19:12 +0200 Subject: [PATCH 100/120] Fix typo. --- modules/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/README.md b/modules/README.md index d157c983..52456016 100644 --- a/modules/README.md +++ b/modules/README.md @@ -309,7 +309,7 @@ To show a module, you can call the `show(speed, callback)` method. You can call Possible configurable options: -- `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. See *visibility locking- below. +- `lockString` - String - When setting lock string, the module can not be shown without passing the correct lockstring. This way (multiple) modules can prevent a module from showing. See *visibility locking* below. - `force` - Boolean - When setting the force tag to `true`, the locking mechanism will be overwritten. Use this option with caution. It's considered best practice to let the usage of the force option be use- configurable. See *visibility locking* below. **Note 1:** If the show animation is canceled, for instance because the hide method is called before the show animation was finished, the callback will not be called.
From 95edbc16bbd2d28cb4f997e92df8bae860daed56 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 16:42:15 +0200 Subject: [PATCH 101/120] Add requiresVersion property to module API. --- CHANGELOG.md | 5 +- index.html | 4 ++ js/app.js | 37 ++++++++++++++ js/loader.js | 8 ++- js/module.js | 128 ++++++++++++++++++++++++++++++---------------- js/server.js | 10 +++- modules/README.md | 27 +++++++++- package.json | 2 +- 8 files changed, 169 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08cc8850..09c8e0a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,13 +9,14 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Finnish translation. - Danish translation. -- Method to overwrite the module's header. [See documentation.](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) - Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)). - Added ability to change the point of time when calendar events get relative. - Add Splash screen on boot. - Add option to show humidity in currentWeather module. -- Add Visibility locking to module system. See [documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. - Add VSCode IntelliSense support. +- Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. +- Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information. +- Module API: Option to define the minimumn MagicMirror verion to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresVersion) for more information. ### Updated - Modified translations for Frysk. diff --git a/index.html b/index.html index 4288eba1..86a69a4a 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,10 @@ + +
diff --git a/js/app.js b/js/app.js index 14f10e8b..84e89d13 100644 --- a/js/app.js +++ b/js/app.js @@ -10,6 +10,10 @@ var Server = require(__dirname + "/server.js"); var defaultModules = require(__dirname + "/../modules/default/defaultmodules.js"); var path = require("path"); +// Get version number. +global.version = JSON.parse(fs.readFileSync("package.json", "utf8")).version; +console.log("Starting MagicMirror: v" + global.version); + // The next part is here to prevent a major exception when there // is no internet connection. This could probable be solved better. process.on("uncaughtException", function (err) { @@ -82,6 +86,17 @@ var App = function() { if (loadModule) { var Module = require(helperPath); var m = new Module(); + + if (m.requiresVersion) { + console.log("Check MagicMirror version for node helper '" + moduleName + "' - Minimum version: " + m.requiresVersion + " - Current version: " + global.version); + if (cmpVersions(global.version, m.requiresVersion) >= 0) { + console.log("Version is ok!"); + } else { + console.log("Version is incorrect. Skip module: '" + moduleName + "'"); + return; + } + } + m.setName(moduleName); m.setPath(path.resolve(moduleFolder)); nodeHelpers.push(m); @@ -103,6 +118,28 @@ var App = function() { console.log("All module helpers loaded."); }; + /* cmpVersions(a,b) + * Compare two symantic version numbers and return the difference. + * + * argument a string - Version number a. + * argument a string - Version number b. + */ + function cmpVersions(a, b) { + var i, diff; + var regExStrip0 = /(\.0+)+$/; + var segmentsA = a.replace(regExStrip0, "").split("."); + var segmentsB = b.replace(regExStrip0, "").split("."); + var l = Math.min(segmentsA.length, segmentsB.length); + + for (i = 0; i < l; i++) { + diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10); + if (diff) { + return diff; + } + } + return segmentsA.length - segmentsB.length; + } + /* start(callback) * This methods starts the core app. * It loads the config, then it loads all modules. diff --git a/js/loader.js b/js/loader.js index 3656c7cd..84e42a0a 100644 --- a/js/loader.js +++ b/js/loader.js @@ -117,9 +117,13 @@ var Loader = (function() { var afterLoad = function() { var moduleObject = Module.create(module.name); - bootstrapModule(module, moduleObject, function() { + if (moduleObject) { + bootstrapModule(module, moduleObject, function() { + callback(); + }); + } else { callback(); - }); + } }; if (loadedModuleFiles.indexOf(url) !== -1) { diff --git a/js/module.js b/js/module.js index fe669cee..17ca9595 100644 --- a/js/module.js +++ b/js/module.js @@ -14,6 +14,9 @@ var Module = Class.extend({ * All methods (and properties) below can be subclassed. * *********************************************************/ + // Set the minimum MagicMirror module version for this module. + requiresVersion: "2.0.0", + // Module config defaults. defaults: {}, @@ -27,14 +30,14 @@ var Module = Class.extend({ /* init() * Is called when the module is instantiated. */ - init: function() { + init: function () { //Log.log(this.defaults); }, /* start() * Is called when the module is started. */ - start: function() { + start: function () { Log.info("Starting module: " + this.name); }, @@ -43,7 +46,7 @@ var Module = Class.extend({ * * return Array - An array with filenames. */ - getScripts: function() { + getScripts: function () { return []; }, @@ -52,7 +55,7 @@ var Module = Class.extend({ * * return Array - An array with filenames. */ - getStyles: function() { + getStyles: function () { return []; }, @@ -61,7 +64,7 @@ var Module = Class.extend({ * * return Map - A map with langKeys and filenames. */ - getTranslations: function() { + getTranslations: function () { return false; }, @@ -71,7 +74,7 @@ var Module = Class.extend({ * * return domobject - The dom to display. */ - getDom: function() { + getDom: function () { var nameWrapper = document.createElement("div"); var name = document.createTextNode(this.name); nameWrapper.appendChild(name); @@ -95,7 +98,7 @@ var Module = Class.extend({ * * return string - The header to display above the header. */ - getHeader: function() { + getHeader: function () { return this.data.header; }, @@ -107,7 +110,7 @@ var Module = Class.extend({ * argument payload mixed - The payload of the notification. * argument sender Module - The module that sent the notification. */ - notificationReceived: function(notification, payload, sender) { + notificationReceived: function (notification, payload, sender) { if (sender) { Log.log(this.name + " received a module notification: " + notification + " from sender: " + sender.name); } else { @@ -121,21 +124,21 @@ var Module = Class.extend({ * argument notification string - The identifier of the noitication. * argument payload mixed - The payload of the notification. */ - socketNotificationReceived: function(notification, payload) { + socketNotificationReceived: function (notification, payload) { Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload); }, /* suspend() * This method is called when a module is hidden. */ - suspend: function() { + suspend: function () { Log.log(this.name + " is suspended."); }, /* resume() * This method is called when a module is shown. */ - resume: function() { + resume: function () { Log.log(this.name + " is resumed."); }, @@ -148,7 +151,7 @@ var Module = Class.extend({ * * argument data obejct - Module data. */ - setData: function(data) { + setData: function (data) { this.data = data; this.name = data.name; this.identifier = data.identifier; @@ -162,7 +165,7 @@ var Module = Class.extend({ * * argument config obejct - Module config. */ - setConfig: function(config) { + setConfig: function (config) { this.config = Object.assign(this.defaults, config); }, @@ -170,13 +173,13 @@ var Module = Class.extend({ * Returns a socket object. If it doesn"t exist, it"s created. * It also registers the notification callback. */ - socket: function() { + socket: function () { if (typeof this._socket === "undefined") { this._socket = this._socket = new MMSocket(this.name); } var self = this; - this._socket.setNotificationCallback(function(notification, payload) { + this._socket.setNotificationCallback(function (notification, payload) { self.socketNotificationReceived(notification, payload); }); @@ -190,7 +193,7 @@ var Module = Class.extend({ * * return string - File path. */ - file: function(file) { + file: function (file) { return this.data.path + "/" + file; }, @@ -199,14 +202,14 @@ var Module = Class.extend({ * * argument callback function - Function called when done. */ - loadStyles: function(callback) { + loadStyles: function (callback) { var self = this; var styles = this.getStyles(); - var loadNextStyle = function() { + var loadNextStyle = function () { if (styles.length > 0) { var nextStyle = styles[0]; - Loader.loadFile(nextStyle, self, function() { + Loader.loadFile(nextStyle, self, function () { styles = styles.slice(1); loadNextStyle(); }); @@ -223,14 +226,14 @@ var Module = Class.extend({ * * argument callback function - Function called when done. */ - loadScripts: function(callback) { + loadScripts: function (callback) { var self = this; var scripts = this.getScripts(); - var loadNextScript = function() { + var loadNextScript = function () { if (scripts.length > 0) { var nextScript = scripts[0]; - Loader.loadFile(nextScript, self, function() { + Loader.loadFile(nextScript, self, function () { scripts = scripts.slice(1); loadNextScript(); }); @@ -247,14 +250,14 @@ var Module = Class.extend({ * * argument callback function - Function called when done. */ - loadTranslations: function(callback) { + loadTranslations: function (callback) { var self = this; var translations = this.getTranslations(); var lang = config.language.toLowerCase(); // The variable `first` will contain the first // defined translation after the following line. - for (var first in translations) {break;} + for (var first in translations) { break; } if (translations) { var translationFile = translations[lang] || undefined; @@ -263,7 +266,7 @@ var Module = Class.extend({ // If a translation file is set, load it and then also load the fallback translation file. // Otherwise only load the fallback translation file. if (translationFile !== undefined && translationFile !== translationsFallbackFile) { - Translator.load(self, translationFile, false, function() { + Translator.load(self, translationFile, false, function () { Translator.load(self, translationsFallbackFile, true, callback); }); } else { @@ -274,13 +277,13 @@ var Module = Class.extend({ } }, - /* translate(key, defaultValue) - * Request the translation for a given key. - * - * argument key string - The key of the string to translage - * argument defaultValue string - The default value if no translation was found. (Optional) - */ - translate: function(key, defaultValue) { + /* translate(key, defaultValue) + * Request the translation for a given key. + * + * argument key string - The key of the string to translage + * argument defaultValue string - The default value if no translation was found. (Optional) + */ + translate: function (key, defaultValue) { return Translator.translate(this, key) || defaultValue || ""; }, @@ -289,7 +292,7 @@ var Module = Class.extend({ * * argument speed Number - The speed of the animation. (Optional) */ - updateDom: function(speed) { + updateDom: function (speed) { MM.updateDom(this, speed); }, @@ -299,7 +302,7 @@ var Module = Class.extend({ * argument notification string - The identifier of the noitication. * argument payload mixed - The payload of the notification. */ - sendNotification: function(notification, payload) { + sendNotification: function (notification, payload) { MM.sendNotification(notification, payload, this); }, @@ -309,7 +312,7 @@ var Module = Class.extend({ * argument notification string - The identifier of the noitication. * argument payload mixed - The payload of the notification. */ - sendSocketNotification: function(notification, payload) { + sendSocketNotification: function (notification, payload) { this.socket().sendNotification(notification, payload); }, @@ -320,17 +323,17 @@ var Module = Class.extend({ * argument callback function - Called when the animation is done. * argument options object - Optional settings for the hide method. */ - hide: function(speed, callback, options) { + hide: function (speed, callback, options) { if (typeof callback === "object") { options = callback; - callback = function() {}; + callback = function () { }; } - callback = callback || function() {}; + callback = callback || function () { }; options = options || {}; var self = this; - MM.hideModule(self, speed, function() { + MM.hideModule(self, speed, function () { self.suspend(); callback(); }, options); @@ -345,13 +348,13 @@ var Module = Class.extend({ * argument callback function - Called when the animation is done. * argument options object - Optional settings for the hide method. */ - show: function(speed, callback, options) { + show: function (speed, callback, options) { if (typeof callback === "object") { options = callback; - callback = function() {}; + callback = function () { }; } - callback = callback || function() {}; + callback = callback || function () { }; options = options || {}; this.resume(); @@ -361,7 +364,12 @@ var Module = Class.extend({ Module.definitions = {}; -Module.create = function(name) { +Module.create = function (name) { + + // Make sure module definition is available. + if (!Module.definitions[name]) { + return; + } //Define the clone method for later use. function cloneObject(obj) { @@ -387,7 +395,39 @@ Module.create = function(name) { }; -Module.register = function(name, moduleDefinition) { +/* cmpVersions(a,b) +* Compare two symantic version numbers and return the difference. +* +* argument a string - Version number a. +* argument a string - Version number b. +*/ +function cmpVersions(a, b) { + var i, diff; + var regExStrip0 = /(\.0+)+$/; + var segmentsA = a.replace(regExStrip0, "").split("."); + var segmentsB = b.replace(regExStrip0, "").split("."); + var l = Math.min(segmentsA.length, segmentsB.length); + + for (i = 0; i < l; i++) { + diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10); + if (diff) { + return diff; + } + } + return segmentsA.length - segmentsB.length; +} + +Module.register = function (name, moduleDefinition) { + + if (moduleDefinition.requiresVersion) { + Log.log("Check MagicMirror version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + version); + if (cmpVersions(version, moduleDefinition.requiresVersion) >= 0) { + Log.log("Version is ok!"); + } else { + Log.log("Version is incorrect. Skip module: '" + name + "'"); + return; + } + } Log.log("Module registered: " + name); Module.definitions[name] = moduleDefinition; }; diff --git a/js/server.js b/js/server.js index e1a90946..9ab47a7d 100644 --- a/js/server.js +++ b/js/server.js @@ -11,6 +11,7 @@ var server = require("http").Server(app); var io = require("socket.io")(server); var path = require("path"); var ipfilter = require("express-ipfilter").IpFilter; +var fs = require("fs"); var Server = function(config, callback) { console.log("Starting server op port " + config.port + " ... "); @@ -35,8 +36,15 @@ var Server = function(config, callback) { app.use("/vendor", express.static(path.resolve(__dirname + "/../vendor"))); app.use("/translations", express.static(path.resolve(__dirname + "/../translations"))); + app.get("/version", function(req,res) { + res.send(global.version); + }); + app.get("/", function(req, res) { - res.sendFile(path.resolve(__dirname + "/../index.html")); + var html = fs.readFileSync(path.resolve(__dirname + "/../index.html"), {encoding: "utf8"}); + html = html.replace("#VERSION#", global.version); + + res.send(html); }); if (typeof callback === "function") { diff --git a/modules/README.md b/modules/README.md index 52456016..9332d009 100644 --- a/modules/README.md +++ b/modules/README.md @@ -78,6 +78,16 @@ The data object contains additional metadata about the module instance: ####`defaults: {}` Any properties defined in the defaults object, will be merged with the module config as defined in the user's config.js file. This is the best place to set your modules's configuration defaults. Any of the module configuration properties can be accessed using `this.config.propertyName`, but more about that later. +####'requiresVersion:' + +*Introduced in version: 2.1.0.* + +A string that defines the minimum version of the MagicMirror framework. If it is set, the system compares the required version with the users version. If the version of the user is out of date, it won't run the module. Make sure to also set this value in the Node helper. + +**Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module. + +Example: `"2.1.0"` + ### Subclassable module methods ####`init()` @@ -286,7 +296,7 @@ this.sendSocketNotification('SET_CONFIG', this.config); ####`this.hide(speed, callback, options)` ***speed* Number** - Optional (Required when setting callback or options), The speed of the hide animation in milliseconds. ***callback* Function** - Optional, The callback after the hide animation is finished. -***options* Function** - Optional, Object with additional options for the hide action (see below). +***options* Function** - Optional, Object with additional options for the hide action (see below). (*Introduced in version: 2.1.0.*) To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itself using `this.hide()`, but of course you can also hide another module using `anOtherModule.hide()`. @@ -303,7 +313,7 @@ Possible configurable options: ####`this.show(speed, callback, options)` ***speed* Number** - Optional (Required when setting callback or options), The speed of the show animation in milliseconds. ***callback* Function** - Optional, The callback after the show animation is finished. -***options* Function** - Optional, Object with additional options for the show action (see below). +***options* Function** - Optional, Object with additional options for the show action (see below). (*Introduced in version: 2.1.0.*) To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itself using `this.show()`, but of course you can also show another module using `anOtherModule.show()`. @@ -317,6 +327,9 @@ Possible configurable options: **Note 3:** If the dom is not yet created, the show method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender). ####Visibility locking + +(*Introduced in version: 2.1.0.*) + Visiblity locking helps the module system to prevent unwanted hide/show actions. The following scenario explains the concept: **Module B asks module A to hide:** @@ -450,6 +463,16 @@ this.expressApp.use("/" + this.name, express.static(this.path + "/public")); This is a link to the IO instance. It will allow you to do some Socket.IO magic. In most cases you won't need this, since the Node Helper has a few convenience methods to make this simple. + +####'requiresVersion:' +*Introduced in version: 2.1.0.* + +A string that defines the minimum version of the MagicMirror framework. If it is set, the system compares the required version with the users version. If the version of the user is out of date, it won't run the module. + +**Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module. + +Example: `"2.1.0"` + ### Subclassable module methods ####`init()` diff --git a/package.json b/package.json index cfef5f85..202c3e59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.0.0", + "version": "2.1.0", "description": "A modular interface for smart mirrors.", "main": "js/electron.js", "scripts": { From 0d45eb91db6928f27edfaa0a42440232248301a8 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 16:43:43 +0200 Subject: [PATCH 102/120] Fix typo. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09c8e0a6..5e407d8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Add VSCode IntelliSense support. - Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. - Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information. -- Module API: Option to define the minimumn MagicMirror verion to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresVersion) for more information. +- Module API: Option to define the minimumn MagicMirror version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information. ### Updated - Modified translations for Frysk. From a75ff0c061986aade69bf2a9b59d5437c4dc34a9 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 16:45:23 +0200 Subject: [PATCH 103/120] Improve documentation. --- modules/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/README.md b/modules/README.md index 9332d009..313c8880 100644 --- a/modules/README.md +++ b/modules/README.md @@ -86,7 +86,10 @@ A string that defines the minimum version of the MagicMirror framework. If it is **Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module. -Example: `"2.1.0"` +Example: +```` +requiresVersion: "2.1.0", +```` ### Subclassable module methods @@ -471,7 +474,10 @@ A string that defines the minimum version of the MagicMirror framework. If it is **Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module. -Example: `"2.1.0"` +Example: +```` +requiresVersion: "2.1.0", +```` ### Subclassable module methods From a6191320a100dc9c0017ef24dc47634e405b514e Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 16:47:00 +0200 Subject: [PATCH 104/120] Improve documentation. --- modules/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/README.md b/modules/README.md index 313c8880..54043b69 100644 --- a/modules/README.md +++ b/modules/README.md @@ -87,7 +87,7 @@ A string that defines the minimum version of the MagicMirror framework. If it is **Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module. Example: -```` +````javascript requiresVersion: "2.1.0", ```` @@ -336,48 +336,48 @@ Possible configurable options: Visiblity locking helps the module system to prevent unwanted hide/show actions. The following scenario explains the concept: **Module B asks module A to hide:** -```` +````javascript moduleA.hide(0, {lockString: "module_b_identifier"}); ```` Module A is now hidden, and has an lock array with the following strings: -```` +````javascript moduleA.lockStrings == ["module_b_identifier"] moduleA.hidden == true ```` **Module C asks module A to hide:** -```` +````javascript moduleA.hide(0, {lockString: "module_c_identifier"}); ```` Module A is now hidden, and has an lock array with the following strings: -```` +````javascript moduleA.lockStrings == ["module_b_identifier", "module_c_identifier"] moduleA.hidden == true ```` **Module B asks module A to show:** -```` +````javascript moduleA.show(0, {lockString: "module_b_identifier"}); ```` The lockString will be removed from moduleA’s locks array, but since there still is an other lock string available, the module remains hidden: -```` +````javascript moduleA.lockStrings == ["module_c_identifier"] moduleA.hidden == true ```` **Module C asks module A to show:** -```` +````javascript moduleA.show(0, {lockString: "module_c_identifier"}); ```` The lockString will be removed from moduleA’s locks array, and since this will result in an empty lock array, the module will be visible: -```` +````javascript moduleA.lockStrings == [] moduleA.hidden == false ```` **Note:** The locking mechanism can be overwritten by using the force tag: -```` +````javascript moduleA.show(0, {force: true}); ```` This will reset the lockstring array, and will show the module. -```` +````javascript moduleA.lockStrings == [] moduleA.hidden == false ```` @@ -475,7 +475,7 @@ A string that defines the minimum version of the MagicMirror framework. If it is **Note:** Since this check is introduced in version 2.1.0, this check will not be run in older versions. Keep this in mind if you get issue reports on your module. Example: -```` +````javascript requiresVersion: "2.1.0", ```` From 6510de5d299253434b612a86eb747a47bb4c5f28 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 20:22:30 +0200 Subject: [PATCH 105/120] Fix logger issue on electron. --- js/logger.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/js/logger.js b/js/logger.js index 6c073720..280103ab 100644 --- a/js/logger.js +++ b/js/logger.js @@ -14,34 +14,34 @@ var Log = (function() { return { info: function() { - console.info.apply(this, arguments); + console.info.apply(console, arguments); }, log: function() { - console.log.apply(this, arguments); + console.log.apply(console, arguments); }, error: function() { - console.error.apply(this, arguments); + console.error.apply(console, arguments); }, warn: function() { - console.warn.apply(this, arguments); + console.warn.apply(console, arguments); }, group: function() { - console.group.apply(this, arguments); + console.group.apply(console, arguments); }, groupCollapsed: function() { - console.groupCollapsed.apply(this, arguments); + console.groupCollapsed.apply(console, arguments); }, groupEnd: function() { console.groupEnd(); }, time: function() { - console.time.apply(this, arguments); + console.time.apply(console, arguments); }, timeEnd: function() { - console.timeEnd.apply(this, arguments); + console.timeEnd.apply(console, arguments); }, timeStamp: function() { - console.timeStamp.apply(this, arguments); + console.timeStamp.apply(console, arguments); } }; })(); From 4a53e4207c125d784fc2c81b868525e88616d856 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Thu, 13 Oct 2016 21:05:48 +0200 Subject: [PATCH 106/120] Small visual change. --- modules/default/currentweather/currentweather.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index 587080db..0662ef62 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -140,11 +140,15 @@ Module.register("currentweather",{ var humidity = document.createElement("span"); humidity.innerHTML = this.humidity; + var spacer = document.createElement("sup"); + spacer.innerHTML = " "; + var humidityIcon = document.createElement("sup"); humidityIcon.className = "wi wi-humidity humidityIcon"; humidityIcon.innerHTML = " "; small.appendChild(humidity); + small.appendChild(spacer); small.appendChild(humidityIcon); } From 8b004a549aba125e8ef88171f936b267382677d3 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Fri, 14 Oct 2016 14:19:03 +0200 Subject: [PATCH 107/120] Change Newsfeed logging. --- CHANGELOG.md | 3 +-- modules/default/newsfeed/fetcher.js | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e407d8c..5e3413bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Updated package.json as a result of Snyk security update. - Improve object instantiation to prevent reference errors. - Improve logger. `Log.log()` now accepts multiple arguments. - -### Changed +- Remove extensive logging in newsfeed node helper. - Calendar times are now uniformly capitalized. ## [2.0.5] - 2016-09-20 diff --git a/modules/default/newsfeed/fetcher.js b/modules/default/newsfeed/fetcher.js index ff0a9980..665c5e15 100644 --- a/modules/default/newsfeed/fetcher.js +++ b/modules/default/newsfeed/fetcher.js @@ -60,11 +60,11 @@ var Fetcher = function(url, reloadInterval, encoding) { } else { - console.log("Can't parse feed item:"); - console.log(item); - console.log('Title: ' + title); - console.log('Description: ' + description); - console.log('Pubdate: ' + pubdate); + // console.log("Can't parse feed item:"); + // console.log(item); + // console.log('Title: ' + title); + // console.log('Description: ' + description); + // console.log('Pubdate: ' + pubdate); } }); From 5858e862d95b8b1b4b248615d41559c338229dd8 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Fri, 14 Oct 2016 15:23:03 +0200 Subject: [PATCH 108/120] Broadcast calendar eventlist to other modules. --- CHANGELOG.md | 1 + js/class.js | 37 +++---- js/module.js | 14 --- modules/default/calendar/README.md | 8 +- modules/default/calendar/calendar.js | 112 ++++++++++++-------- modules/default/calendar/calendarfetcher.js | 17 ++- 6 files changed, 109 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e3413bb..efdd1aac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. - Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information. - Module API: Option to define the minimumn MagicMirror version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information. +- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/master/modules/default/calendar) for more information. ### Updated - Modified translations for Frysk. diff --git a/js/class.js b/js/class.js index 2b011b29..01a92603 100644 --- a/js/class.js +++ b/js/class.js @@ -11,24 +11,6 @@ // The base Class implementation (does nothing) this.Class = function() {}; - //Define the clone method for later use. - function cloneObject(obj) { - if (obj === null || typeof obj !== "object") { - return obj; - } - - var temp = obj.constructor(); // give temp the original obj's constructor - for (var key in obj) { - temp[key] = cloneObject(obj[key]); - - if (key === "lockStrings") { - Log.log(key); - } - } - - return temp; - } - // Create a new Class that inherits from this class Class.extend = function(prop) { var _super = this.prototype; @@ -87,5 +69,24 @@ }; })(); +//Define the clone method for later use. +//Helper Method +function cloneObject(obj) { + if (obj === null || typeof obj !== "object") { + return obj; + } + + var temp = obj.constructor(); // give temp the original obj's constructor + for (var key in obj) { + temp[key] = cloneObject(obj[key]); + + if (key === "lockStrings") { + Log.log(key); + } + } + + return temp; +} + /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") {module.exports = Class;} diff --git a/js/module.js b/js/module.js index 17ca9595..397d4799 100644 --- a/js/module.js +++ b/js/module.js @@ -371,20 +371,6 @@ Module.create = function (name) { return; } - //Define the clone method for later use. - function cloneObject(obj) { - if (obj === null || typeof obj !== "object") { - return obj; - } - - var temp = obj.constructor(); // give temp the original obj's constructor - for (var key in obj) { - temp[key] = cloneObject(obj[key]); - } - - return temp; - } - var moduleDefinition = Module.definitions[name]; var clonedDefinition = cloneObject(moduleDefinition); diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index fc553095..54d318ce 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -106,7 +106,6 @@ The following properties can be configured: titleReplace An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title.

Example:
- titleReplace: {'Birthday of ' : '', 'foo':'bar'} @@ -141,6 +140,13 @@ The following properties can be configured:
Default value: 0 (disabled) + + broadcastEvents + If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: CALENDAR_EVENTS. The event objects are stored in an array and contain the following fields: title, startDate, endDate, fullDayEvent, location and geo.
+
Possible values: true, false
+
Default value: true + + diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index c2a2c851..39ea6b58 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -7,7 +7,7 @@ * MIT Licensed. */ -Module.register("calendar",{ +Module.register("calendar", { // Define module defaults defaults: { @@ -16,7 +16,7 @@ Module.register("calendar",{ displaySymbol: true, defaultSymbol: "calendar", // Fontawesome Symbol see http://fontawesome.io/cheatsheet/ displayRepeatingCountTitle: false, - defaultRepeatingCountTitle: '', + defaultRepeatingCountTitle: "", maxTitleLength: 25, fetchInterval: 5 * 60 * 1000, // Update every 5 minutes. animationSpeed: 2000, @@ -35,20 +35,21 @@ Module.register("calendar",{ "De verjaardag van ": "", "'s birthday": "" }, + broadcastEvents: true }, // Define required scripts. - getStyles: function() { + getStyles: function () { return ["calendar.css", "font-awesome.css"]; }, // Define required scripts. - getScripts: function() { + getScripts: function () { return ["moment.js"]; }, // Define required translations. - getTranslations: function() { + getTranslations: function () { // The translations for the defaut modules are defined in the core translation files. // Therefor we can just return false. Otherwise we should have returned a dictionairy. // If you're trying to build your own module including translations, check out the documentation. @@ -56,7 +57,7 @@ Module.register("calendar",{ }, // Override start method. - start: function() { + start: function () { Log.log("Starting module: " + this.name); // Set locale. @@ -73,11 +74,15 @@ Module.register("calendar",{ }, // Override socket notification handler. - socketNotificationReceived: function(notification, payload) { + socketNotificationReceived: function (notification, payload) { if (notification === "CALENDAR_EVENTS") { if (this.hasCalendarURL(payload.url)) { this.calendarData[payload.url] = payload.events; this.loaded = true; + + if (this.config.broadcastEvents) { + this.broadcastEvents(); + } } } else if (notification === "FETCH_ERROR") { Log.error("Calendar Error. Could not fetch calendar: " + payload.url); @@ -91,7 +96,7 @@ Module.register("calendar",{ }, // Override dom generator. - getDom: function() { + getDom: function () { var events = this.createEventList(); var wrapper = document.createElement("table"); @@ -110,27 +115,27 @@ Module.register("calendar",{ eventWrapper.className = "normal"; if (this.config.displaySymbol) { - var symbolWrapper = document.createElement("td"); + var symbolWrapper = document.createElement("td"); symbolWrapper.className = "symbol"; - var symbol = document.createElement("span"); + var symbol = document.createElement("span"); symbol.className = "fa fa-" + this.symbolForUrl(event.url); symbolWrapper.appendChild(symbol); eventWrapper.appendChild(symbolWrapper); } var titleWrapper = document.createElement("td"), - repeatingCountTitle = ''; + repeatingCountTitle = ""; if (this.config.displayRepeatingCountTitle) { repeatingCountTitle = this.countTitleForUrl(event.url); - if(repeatingCountTitle !== '') { + if (repeatingCountTitle !== "") { var thisYear = new Date().getFullYear(), yearDiff = thisYear - event.firstYear; - repeatingCountTitle = ', '+ yearDiff + '. ' + repeatingCountTitle; + repeatingCountTitle = ", " + yearDiff + ". " + repeatingCountTitle; } } @@ -138,24 +143,24 @@ Module.register("calendar",{ titleWrapper.className = "title bright"; eventWrapper.appendChild(titleWrapper); - var timeWrapper = document.createElement("td"); + var timeWrapper = document.createElement("td"); //console.log(event.today); var now = new Date(); // Define second, minute, hour, and day variables - var one_second = 1000; // 1,000 milliseconds - var one_minute = one_second * 60; - var one_hour = one_minute * 60; - var one_day = one_hour * 24; + var oneSecond = 1000; // 1,000 milliseconds + var oneMinute = oneSecond * 60; + var oneHour = oneMinute * 60; + var oneDay = oneHour * 24; if (event.fullDayEvent) { if (event.today) { timeWrapper.innerHTML = this.capFirst(this.translate("TODAY")); - } else if (event.startDate - now < one_day && event.startDate - now > 0) { + } else if (event.startDate - now < oneDay && event.startDate - now > 0) { timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW")); - } else if (event.startDate - now < 2*one_day && event.startDate - now > 0) { - if (this.translate('DAYAFTERTOMORROW') !== 'DAYAFTERTOMORROW') { - timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); + } else if (event.startDate - now < 2 * oneDay && event.startDate - now > 0) { + if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { + timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } else { /* Check to see if the user displays absolute or relative dates with their events @@ -166,21 +171,21 @@ Module.register("calendar",{ * Note: this needs to be put in its own function, as the whole thing repeats again verbatim */ if (this.config.timeFormat === "absolute") { - if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * one_day))) { + if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) { // This event falls within the config.urgency period that the user has set timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format("MMM Do")); } } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } } else { if (event.startDate >= new Date()) { - if (event.startDate - now < 2 * one_day) { + if (event.startDate - now < 2 * oneDay) { // This event is within the next 48 hours (2 days) - if (event.startDate - now < this.config.getRelative * one_hour) { + if (event.startDate - now < this.config.getRelative * oneHour) { // If event is within 6 hour, display 'in xxx' time format or moment.fromNow() timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { @@ -196,7 +201,7 @@ Module.register("calendar",{ * Note: this needs to be put in its own function, as the whole thing repeats again verbatim */ if (this.config.timeFormat === "absolute") { - if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * one_day))) { + if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) { // This event falls within the config.urgency period that the user has set timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { @@ -207,7 +212,7 @@ Module.register("calendar",{ } } } else { - timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + ' ' + moment(event.endDate,"x").fromNow(true); + timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + " " + moment(event.endDate, "x").fromNow(true); } } //timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll'); @@ -241,7 +246,7 @@ Module.register("calendar",{ * * return bool - Has calendar url */ - hasCalendarURL: function(url) { + hasCalendarURL: function (url) { for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; if (calendar.url === url) { @@ -257,7 +262,7 @@ Module.register("calendar",{ * * return array - Array with events. */ - createEventList: function() { + createEventList: function () { var events = []; var today = moment().startOf("day"); for (var c in this.calendarData) { @@ -270,7 +275,7 @@ Module.register("calendar",{ } } - events.sort(function(a, b) { + events.sort(function (a, b) { return a.startDate - b.startDate; }); @@ -282,7 +287,7 @@ Module.register("calendar",{ * * argument url sting - Url to add. */ - addCalendar: function(url, user, pass) { + addCalendar: function (url, user, pass) { this.sendSocketNotification("ADD_CALENDAR", { url: url, maximumEntries: this.config.maximumEntries, @@ -300,10 +305,10 @@ Module.register("calendar",{ * * return string - The Symbol */ - symbolForUrl: function(url) { + symbolForUrl: function (url) { for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; - if (calendar.url === url && typeof calendar.symbol === "string") { + if (calendar.url === url && typeof calendar.symbol === "string") { return calendar.symbol; } } @@ -317,10 +322,10 @@ Module.register("calendar",{ * * return string - The Symbol */ - countTitleForUrl: function(url) { + countTitleForUrl: function (url) { for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; - if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") { + if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") { return calendar.repeatingCountTitle; } } @@ -337,9 +342,9 @@ Module.register("calendar",{ * * return string - The shortened string. */ - shorten: function(string, maxLength) { + shorten: function (string, maxLength) { if (string.length > maxLength) { - return string.slice(0,maxLength) + "…"; + return string.slice(0, maxLength) + "…"; } return string; @@ -349,8 +354,8 @@ Module.register("calendar",{ * Capitalize the first letter of a string * Eeturn capitalized string */ - - capFirst: function(string) { + + capFirst: function (string) { return string.charAt(0).toUpperCase() + string.slice(1); }, @@ -363,7 +368,7 @@ Module.register("calendar",{ * * return string - The transformed title. */ - titleTransform: function(title) { + titleTransform: function (title) { for (var needle in this.config.titleReplace) { var replacement = this.config.titleReplace[needle]; title = title.replace(needle, replacement); @@ -371,5 +376,28 @@ Module.register("calendar",{ title = this.shorten(title, this.config.maxTitleLength); return title; + }, + + /* broadcastEvents() + * Broadcasts the events to all other modules for reuse. + * The all events available in one array, sorted on startdate. + */ + broadcastEvents: function () { + var eventList = []; + for (url in this.calendarData) { + var calendar = this.calendarData[url]; + for (e in calendar) { + var event = cloneObject(calendar[e]); + delete event.url; + eventList.push(event); + } + } + + eventList.sort(function(a,b) { + return a.startDate - b.startDate; + }); + + this.sendNotification("CALENDAR_EVENTS", eventList); + } }); diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 214e2e5a..7f142546 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -27,7 +27,7 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe var opts = { headers: { - 'User-Agent': 'Mozilla/5.0 (Node.js 6.0.0) MagicMirror/v2 (https://github.com/MichMich/MagicMirror/)' + "User-Agent": "Mozilla/5.0 (Node.js 6.0.0) MagicMirror/v2 (https://github.com/MichMich/MagicMirror/)" } }; @@ -77,7 +77,7 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe if (!isFacebookBirthday) { endDate = startDate; } else { - endDate = moment(startDate).add(1, 'days'); + endDate = moment(startDate).add(1, "days"); } } @@ -101,7 +101,7 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe for (var d in dates) { startDate = moment(new Date(dates[d])); - endDate = moment(parseInt(startDate.format("x")) + duration, 'x'); + endDate = moment(parseInt(startDate.format("x")) + duration, "x"); if (endDate.format("x") > now) { newEvents.push({ title: title, @@ -132,12 +132,19 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe continue; } - // Every thing is good. Add it to the list. + + var location = event.location || false; + var geo = event.geo || false; + + // Every thing is good. Add it to the list. + newEvents.push({ title: title, startDate: startDate.format("x"), endDate: endDate.format("x"), - fullDayEvent: fullDayEvent + fullDayEvent: fullDayEvent, + location: location, + geo: geo }); } From 84dc1fa15194a0921925837b2b4229b7c6e1043c Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Fri, 14 Oct 2016 17:42:07 +0200 Subject: [PATCH 109/120] Possibility to use the the calendar feed as the source for the weather. --- CHANGELOG.md | 3 +- js/main.js | 2 +- js/module.js | 2 - modules/default/currentweather/README.md | 21 ++++- .../default/currentweather/currentweather.js | 75 ++++++++++++++---- modules/default/weatherforecast/README.md | 23 ++++-- .../weatherforecast/weatherforecast.js | 76 +++++++++++++++---- 7 files changed, 162 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efdd1aac..bcb7b9b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. - Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information. - Module API: Option to define the minimumn MagicMirror version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information. -- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/master/modules/default/calendar) for more information. +- 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. ### Updated - Modified translations for Frysk. diff --git a/js/main.js b/js/main.js index a8572c6a..e97f3e10 100644 --- a/js/main.js +++ b/js/main.js @@ -179,7 +179,7 @@ var MM = (function() { // set lockString if set in options. if (options.lockString) { - Log.log("Has lockstring: " + options.lockString); + // Log.log("Has lockstring: " + options.lockString); if (module.lockStrings.indexOf(options.lockString) === -1) { module.lockStrings.push(options.lockString); } diff --git a/js/module.js b/js/module.js index 397d4799..4815895e 100644 --- a/js/module.js +++ b/js/module.js @@ -337,8 +337,6 @@ var Module = Class.extend({ self.suspend(); callback(); }, options); - - Log.log(options); }, /* showModule(module, speed, callback) diff --git a/modules/default/currentweather/README.md b/modules/default/currentweather/README.md index 3df88173..067dce54 100644 --- a/modules/default/currentweather/README.md +++ b/modules/default/currentweather/README.md @@ -35,19 +35,20 @@ The following properties can be configured: - location The location used for weather information.
-
Example: Amsterdam,Netherlands -
Default value: New York +
Example: 'Amsterdam,Netherlands' +
Default value: New York

+ Note: When the location and locationID are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. locationID Location ID from OpenWeather This will override anything you put in location.
Leave blank if you want to use location.
Example: 1234567 -
Default value: +
Default value:

+ Note: When the location and locationID are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. @@ -158,6 +159,18 @@ The following properties can be configured:
Default value: 'weather' + + appendLocationNameToHeader + If set to true, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather.
+
Default value: true + + + + calendarClass + The class for the calender module to base the event based weather information on.
+
Default value: 'calendar' + + iconTable The conversion table to convert the weather conditions to weather-icons.
diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index 0662ef62..39db3f09 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -11,8 +11,8 @@ Module.register("currentweather",{ // Default module config. defaults: { - location: "", - locationID: "", + location: false, + locationID: false, appid: "", units: config.units, updateInterval: 10 * 60 * 1000, // every 10 minutes @@ -32,6 +32,9 @@ Module.register("currentweather",{ apiBase: "http://api.openweathermap.org/data/", weatherEndpoint: "weather", + appendLocationNameToHeader: true, + calendarClass: "calendar", + iconTable: { "01d": "wi-day-sunny", "02d": "wi-day-cloudy", @@ -54,6 +57,12 @@ Module.register("currentweather",{ }, }, + // create a variable for the first upcoming calendaar event. Used if no location is specified. + firstEvent: false, + + // create a variable to hold the location name based on the API result. + fetchedLocatioName: "", + // Define required scripts. getScripts: function() { return ["moment.js"]; @@ -103,12 +112,6 @@ Module.register("currentweather",{ return wrapper; } - if (this.config.location === "") { - wrapper.innerHTML = "Please set the openweather location in the config for module: " + this.name + "."; - wrapper.className = "dimmed light small"; - return wrapper; - } - if (!this.loaded) { wrapper.innerHTML = this.translate('LOADING'); wrapper.className = "dimmed light small"; @@ -178,11 +181,50 @@ Module.register("currentweather",{ return wrapper; }, + // Override getHeader method. + getHeader: function() { + if (this.config.appendLocationNameToHeader) { + return this.data.header + " " + this.fetchedLocatioName; + } + + return this.data.header; + }, + + // Override notification handler. + notificationReceived: function(notification, payload, sender) { + if (notification === "DOM_OBJECTS_CREATED") { + if (this.config.appendLocationNameToHeader) { + this.hide(0, {lockString: this.identifier}); + } + } + if (notification === "CALENDAR_EVENTS") { + var senderClasses = sender.data.classes.toLowerCase().split(" "); + if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) { + var lastEvent = this.firstEvent; + this.firstEvent = false; + + for (e in payload) { + var event = payload[e]; + if (event.location || event.geo) { + this.firstEvent = event; + //Log.log("First upcoming event with location: ", event); + break; + } + } + } + } + }, + /* updateWeather(compliments) * Requests new data from openweather.org. * Calls processWeather on succesfull response. */ updateWeather: function() { + if (this.config.appid === "") { + Log.error("CurrentWeather: APPID not set!"); + return; + } + var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.weatherEndpoint + this.getParams(); var self = this; var retry = true; @@ -194,11 +236,10 @@ Module.register("currentweather",{ if (this.status === 200) { self.processWeather(JSON.parse(this.response)); } else if (this.status === 401) { - self.config.appid = ""; self.updateDom(self.config.animationSpeed); Log.error(self.name + ": Incorrect APPID."); - retry = false; + retry = true; } else { Log.error(self.name + ": Could not load weather."); } @@ -218,11 +259,19 @@ Module.register("currentweather",{ */ getParams: function() { var params = "?"; - if(this.config.locationID !== "") { + if(this.config.locationID !== false) { params += "id=" + this.config.locationID; - } else { + } else if(this.config.location !== false) { params += "q=" + this.config.location; + } else if (this.firstEvent && this.firstEvent.geo) { + params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon + } else if (this.firstEvent && this.firstEvent.location) { + params += "q=" + this.firstEvent.location; + } else { + this.hide(this.config.animationSpeed, {lockString:this.identifier}); + return; } + params += "&units=" + this.config.units; params += "&lang=" + this.config.lang; params += "&APPID=" + this.config.appid; @@ -285,7 +334,7 @@ Module.register("currentweather",{ this.sunriseSunsetIcon = (sunrise < now && sunset > now) ? "wi-sunset" : "wi-sunrise"; - + this.show(this.config.animationSpeed, {lockString:this.identifier}); this.loaded = true; this.updateDom(this.config.animationSpeed); }, diff --git a/modules/default/weatherforecast/README.md b/modules/default/weatherforecast/README.md index aba03a41..a1df57c1 100644 --- a/modules/default/weatherforecast/README.md +++ b/modules/default/weatherforecast/README.md @@ -35,19 +35,20 @@ The following properties can be configured: - location The location used for weather information.
-
Example: Amsterdam,Netherlands -
Default value: New York +
Example: 'Amsterdam,Netherlands' +
Default value: New York

+ Note: When the location and locationID are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. locationID Location ID from OpenWeather This will override anything you put in location.
Leave blank if you want to use location.
Example: 1234567 -
Default value: +
Default value:

+ Note: When the location and locationID are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. @@ -85,7 +86,6 @@ The following properties can be configured:
Default value: 2000 (2 seconds) - lang The language of the days.
@@ -139,6 +139,18 @@ The following properties can be configured:
Default value: 'forecast/daily' + + appendLocationNameToHeader + If set to true, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather.
+
Default value: true + + + + calendarClass + The class for the calender module to base the event based weather information on.
+
Default value: 'calendar' + + iconTable The conversion table to convert the weather conditions to weather-icons.
@@ -164,6 +176,5 @@ The following properties can be configured: } - diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js index a8a8ca6c..7119f79e 100644 --- a/modules/default/weatherforecast/weatherforecast.js +++ b/modules/default/weatherforecast/weatherforecast.js @@ -11,8 +11,8 @@ Module.register("weatherforecast",{ // Default module config. defaults: { - location: "", - locationID: "", + location: false, + locationID: false, appid: "", units: config.units, maxNumberOfDays: 7, @@ -30,6 +30,9 @@ Module.register("weatherforecast",{ apiBase: "http://api.openweathermap.org/data/", forecastEndpoint: "forecast/daily", + appendLocationNameToHeader: true, + calendarClass: "calendar", + iconTable: { "01d": "wi-day-sunny", "02d": "wi-day-cloudy", @@ -52,6 +55,12 @@ Module.register("weatherforecast",{ }, }, + // create a variable for the first upcoming calendaar event. Used if no location is specified. + firstEvent: false, + + // create a variable to hold the location name based on the API result. + fetchedLocatioName: "", + // Define required scripts. getScripts: function() { return ["moment.js"]; @@ -95,12 +104,6 @@ Module.register("weatherforecast",{ return wrapper; } - if (this.config.location === "") { - wrapper.innerHTML = "Please set the openweather location in the config for module: " + this.name + "."; - wrapper.className = "dimmed light small"; - return wrapper; - } - if (!this.loaded) { wrapper.innerHTML = this.translate("LOADING"); wrapper.className = "dimmed light small"; @@ -156,11 +159,50 @@ Module.register("weatherforecast",{ return table; }, + // Override getHeader method. + getHeader: function() { + if (this.config.appendLocationNameToHeader) { + return this.data.header + " " + this.fetchedLocatioName; + } + + return this.data.header; + }, + + // Override notification handler. + notificationReceived: function(notification, payload, sender) { + if (notification === "DOM_OBJECTS_CREATED") { + if (this.config.appendLocationNameToHeader) { + this.hide(0, {lockString: this.identifier}); + } + } + if (notification === "CALENDAR_EVENTS") { + var senderClasses = sender.data.classes.toLowerCase().split(" "); + if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) { + var lastEvent = this.firstEvent; + this.firstEvent = false; + + for (e in payload) { + var event = payload[e]; + if (event.location || event.geo) { + this.firstEvent = event; + //Log.log("First upcoming event with location: ", event); + break; + } + } + } + } + }, + /* updateWeather(compliments) * Requests new data from openweather.org. * Calls processWeather on succesfull response. */ updateWeather: function() { + if (this.config.appid === "") { + Log.error("WeatherForecast: APPID not set!"); + return; + } + var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.forecastEndpoint + this.getParams(); var self = this; var retry = true; @@ -172,11 +214,10 @@ Module.register("weatherforecast",{ if (this.status === 200) { self.processWeather(JSON.parse(this.response)); } else if (this.status === 401) { - self.config.appid = ""; self.updateDom(self.config.animationSpeed); Log.error(self.name + ": Incorrect APPID."); - retry = false; + retry = true; } else { Log.error(self.name + ": Could not load weather."); } @@ -196,11 +237,19 @@ Module.register("weatherforecast",{ */ getParams: function() { var params = "?"; - if(this.config.locationID !== "") { + if(this.config.locationID !== false) { params += "id=" + this.config.locationID; - } else { + } else if(this.config.location !== false) { params += "q=" + this.config.location; + } else if (this.firstEvent && this.firstEvent.geo) { + params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon + } else if (this.firstEvent && this.firstEvent.location) { + params += "q=" + this.firstEvent.location; + } else { + this.hide(this.config.animationSpeed, {lockString:this.identifier}); + return; } + params += "&units=" + this.config.units; params += "&lang=" + this.config.lang; /* @@ -220,6 +269,7 @@ Module.register("weatherforecast",{ * argument data object - Weather information received form openweather.org. */ processWeather: function(data) { + this.fetchedLocatioName = data.city.name + ", " + data.city.country; this.forecast = []; for (var i = 0, count = data.list.length; i < count; i++) { @@ -236,7 +286,7 @@ Module.register("weatherforecast",{ } //Log.log(this.forecast); - + this.show(this.config.animationSpeed, {lockString:this.identifier}); this.loaded = true; this.updateDom(this.config.animationSpeed); }, From bd49bd6e33e2da6e6cd3c3dc05c6728813a642e3 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Fri, 14 Oct 2016 23:07:13 +0200 Subject: [PATCH 110/120] option to show rain amount --- modules/default/weatherforecast/README.md | 8 ++++++++ .../default/weatherforecast/weatherforecast.css | 5 +++++ .../default/weatherforecast/weatherforecast.js | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/modules/default/weatherforecast/README.md b/modules/default/weatherforecast/README.md index a1df57c1..0d321aa3 100644 --- a/modules/default/weatherforecast/README.md +++ b/modules/default/weatherforecast/README.md @@ -72,6 +72,14 @@ The following properties can be configured:
This value is optional. By default the weatherforecast module will return 7 days. + + showRainAmount + Should the predicted rain amount be displayed?
+
Possible values: true or false +
Default value: false +
This value is optional. By default the weatherforecast module will not display the predicted amount of rain. + + updateInterval How often does the content needs to be fetched? (Milliseconds)
diff --git a/modules/default/weatherforecast/weatherforecast.css b/modules/default/weatherforecast/weatherforecast.css index 7b12c42d..62c9767f 100644 --- a/modules/default/weatherforecast/weatherforecast.css +++ b/modules/default/weatherforecast/weatherforecast.css @@ -12,3 +12,8 @@ padding-left: 20px; padding-right: 0; } + +.weatherforecast .rain { + padding-left: 20px; + padding-right: 0; +} diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js index 7119f79e..7f3ef71d 100644 --- a/modules/default/weatherforecast/weatherforecast.js +++ b/modules/default/weatherforecast/weatherforecast.js @@ -16,6 +16,7 @@ Module.register("weatherforecast",{ appid: "", units: config.units, maxNumberOfDays: 7, + showRainAmount: false, updateInterval: 10 * 60 * 1000, // every 10 minutes animationSpeed: 1000, timeFormat: config.timeFormat, @@ -142,6 +143,17 @@ Module.register("weatherforecast",{ minTempCell.className = "align-right min-temp"; row.appendChild(minTempCell); + if (this.config.showRainAmount) { + var rainCell = document.createElement("td"); + if (isNaN(forecast.rain)) { + rainCell.innerHTML = ""; + } else { + rainCell.innerHTML = forecast.rain + " mm"; + } + rainCell.className = "align-right bright rain"; + row.appendChild(rainCell); + } + if (this.config.fade && this.config.fadePoint < 1) { if (this.config.fadePoint < 0) { this.config.fadePoint = 0; @@ -280,7 +292,8 @@ Module.register("weatherforecast",{ day: moment(forecast.dt, "X").format("ddd"), icon: this.config.iconTable[forecast.weather[0].icon], maxTemp: this.roundValue(forecast.temp.max), - minTemp: this.roundValue(forecast.temp.min) + minTemp: this.roundValue(forecast.temp.min), + rain: this.roundValue(forecast.rain) }); } From 0cde1d496923329604f4a8a88b84a606409b916b Mon Sep 17 00:00:00 2001 From: Jopyth Date: Fri, 14 Oct 2016 23:13:13 +0200 Subject: [PATCH 111/120] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcb7b9b7..39902b38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Module API: Option to define the minimumn MagicMirror version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information. - 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 ### Updated - Modified translations for Frysk. From e721d2204bb409951e8f0d9186acdf1bd7304136 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 15 Oct 2016 11:27:34 +0200 Subject: [PATCH 112/120] Fix typo. --- modules/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/README.md b/modules/README.md index 54043b69..5f2713a6 100644 --- a/modules/README.md +++ b/modules/README.md @@ -456,7 +456,7 @@ start: function() { } ```` -**Note: ** By default, a public path to your module's public folder will be created: +**Note:** By default, a public path to your module's public folder will be created: ````javascript this.expressApp.use("/" + this.name, express.static(this.path + "/public")); ```` From a66a4f62bda6a967b016ce94f84c0693dae47f22 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 15 Oct 2016 13:08:46 +0200 Subject: [PATCH 113/120] Add module 'updatenotification'. --- CHANGELOG.md | 1 + config/config.js.sample | 4 ++ js/defaults.js | 4 ++ modules/default/defaultmodules.js | 3 +- modules/default/updatenotification/README.md | 42 ++++++++++++++ .../default/updatenotification/node_helper.js | 45 ++++++++++++++ .../updatenotification/updatenotification.js | 58 +++++++++++++++++++ package.json | 1 + translations/en.json | 6 +- translations/nl.json | 6 +- 10 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 modules/default/updatenotification/README.md create mode 100644 modules/default/updatenotification/node_helper.js create mode 100644 modules/default/updatenotification/updatenotification.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 39902b38..2d68cd34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - 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. ### Updated - Modified translations for Frysk. diff --git a/config/config.js.sample b/config/config.js.sample index e611f872..c2607dbf 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -16,6 +16,10 @@ var config = { { module: 'alert', }, + { + module: "updatenotification", + position: "top_center" + }, { module: 'clock', position: 'top_left' diff --git a/js/defaults.js b/js/defaults.js index 0ec033c3..0f27e817 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -17,6 +17,10 @@ var defaults = { units: "metric", modules: [ + { + module: "updatenotification", + position: "top_center" + }, { module: "helloworld", position: "upper_third", diff --git a/modules/default/defaultmodules.js b/modules/default/defaultmodules.js index 42e89ee0..fccf3c52 100644 --- a/modules/default/defaultmodules.js +++ b/modules/default/defaultmodules.js @@ -15,7 +15,8 @@ var defaultModules = [ "currentweather", "helloworld", "newsfeed", - "weatherforecast" + "weatherforecast", + "updatenotification" ]; /*************** DO NOT EDIT THE LINE BELOW ***************/ diff --git a/modules/default/updatenotification/README.md b/modules/default/updatenotification/README.md new file mode 100644 index 00000000..7d839087 --- /dev/null +++ b/modules/default/updatenotification/README.md @@ -0,0 +1,42 @@ +# Module: Update Notification +The `updatenotification` module is one of the default modules of the MagicMirror. +This will display a message whenever a new version of the MagicMirror application is available. + +## Using the module + +To use this module, add it to the modules array in the `config/config.js` file: +````javascript +modules: [ + { + module: 'updatenotification', + position: 'top_center', // This can be any of the regions. + config: { + // The config property is optional. + // See 'Configuration options' for more information. + } + } +] +```` + +## Configuration options + +The following properties can be configured: + + + + + + + + + + + + + + + +
OptionDescription
updateIntervalHow often do you want to check for a new version? This value represents the interval in milliseconds.
+
Possible values: Any value above 60000 (1 minute); +
Default value: 600000 (10 minutes); +
\ No newline at end of file diff --git a/modules/default/updatenotification/node_helper.js b/modules/default/updatenotification/node_helper.js new file mode 100644 index 00000000..d049e34b --- /dev/null +++ b/modules/default/updatenotification/node_helper.js @@ -0,0 +1,45 @@ +var simpleGit = require("simple-git")(__dirname + "/../.."); +var NodeHelper = require("node_helper"); + +module.exports = NodeHelper.create({ + + config: {}, + + updateTimer: null, + + start: function () { + + }, + + socketNotificationReceived: function (notification, payload) { + if (notification === "CONFIG") { + this.config = payload; + this.preformFetch(); + } + }, + + preformFetch() { + var self = this; + simpleGit.fetch().status(function(err, data) { + if (!err) { + self.sendSocketNotification("STATUS", data); + } + }); + + this.scheduleNextFetch(this.config.updateInterval); + }, + + scheduleNextFetch: function(delay) { + if (delay < 60 * 1000) { + delay = 60 * 1000 + } + + console.log(delay); + var self = this; + clearTimeout(this.updateTimer); + this.updateTimer = setTimeout(function() { + self.preformFetch(); + }, delay); + } + +}); \ No newline at end of file diff --git a/modules/default/updatenotification/updatenotification.js b/modules/default/updatenotification/updatenotification.js new file mode 100644 index 00000000..6b79e862 --- /dev/null +++ b/modules/default/updatenotification/updatenotification.js @@ -0,0 +1,58 @@ +Module.register("updatenotification", { + + + + defaults: { + updateInterval: 10 * 60 * 1000, // every 10 minutes + }, + + status: false, + + start: function () { + Log.log("Start updatenotification"); + var self = this; + }, + + notificationReceived: function(notification, payload, sender) { + if (notification === "DOM_OBJECTS_CREATED") { + this.sendSocketNotification("CONFIG", this.config); + } + }, + + socketNotificationReceived: function (notification, payload) { + if (notification === "STATUS") { + this.status = payload; + this.updateDom(1000); + } + }, + + // Override dom generator. + getDom: function () { + var wrapper = document.createElement("div"); + + if (this.status && this.status.behind > 0) { + var message = document.createElement("div"); + message.className = "small bright"; + + var icon = document.createElement("i"); + icon.className = "fa fa-exclamation-circle"; + icon.innerHTML = " "; + message.appendChild(icon); + + var text = document.createElement("span"); + text.innerHTML = this.translate("UPDATE_NOTIFICATION"); + message.appendChild(text); + + wrapper.appendChild(message); + + var subtext = document.createElement("div"); + subtext.innerHTML = this.translate("UPDATE_INFO") + .replace("COMMIT_COUNT", this.status.behind + " " + ((this.status.behind == 1)? 'commit' : 'commits')) + .replace("BRANCH_NAME", this.status.current); + subtext.className = "xsmall dimmed"; + wrapper.appendChild(subtext); + } + + return wrapper; + } +}); diff --git a/package.json b/package.json index 202c3e59..4d7944e6 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "moment": "latest", "request": "^2.74.0", "rrule": "latest", + "simple-git": "^1.54.0", "snyk": "^1.14.1", "socket.io": "^1.4.6", "valid-url": "latest", diff --git a/translations/en.json b/translations/en.json index a2d5933a..e169ba1b 100644 --- a/translations/en.json +++ b/translations/en.json @@ -24,5 +24,9 @@ "W": "W", "WNW": "WNW", "NW": "NW", - "NNW": "NNW" + "NNW": "NNW", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "MagicMirror² update available.", + "UPDATE_INFO": "The current installation is COMMIT_COUNT behind on the BRANCH_NAME branch." } diff --git a/translations/nl.json b/translations/nl.json index e4e882ea..582b62e6 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -25,5 +25,9 @@ "W": "W", "WNW": "WNW", "NW": "NW", - "NNW": "NNW" + "NNW": "NNW", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "MagicMirror² update beschikbaar.", + "UPDATE_INFO": "De huidige installatie loopt COMMIT_COUNT achter op de BRANCH_NAME branch." } From a419ad201dcb3c731aea814e05db9bf72bb85929 Mon Sep 17 00:00:00 2001 From: fewieden Date: Sat, 15 Oct 2016 13:39:42 +0200 Subject: [PATCH 114/120] added german translation for updatenotification --- translations/de.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/translations/de.json b/translations/de.json index d8a254a9..58a4ca14 100644 --- a/translations/de.json +++ b/translations/de.json @@ -25,5 +25,9 @@ "W": "W", "WNW": "WNW", "NW": "NW", - "NNW": "NNW" + "NNW": "NNW", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "Aktualisierung für MagicMirror² verfügbar.", + "UPDATE_INFO": "Die aktuelle Installation ist COMMIT_COUNT hinter dem BRANCH_NAME branch." } From 6816bd8badfb68037efbede88299d62214c76192 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 15 Oct 2016 17:06:52 +0200 Subject: [PATCH 115/120] Solve margin issue. --- CHANGELOG.md | 3 +++ css/main.css | 8 +++++--- .../updatenotification/updatenotification.js | 13 +++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d68cd34..b1b1c8a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Remove extensive logging in newsfeed node helper. - Calendar times are now uniformly capitalized. +### Fixed +- Solve an issue where module margins would appear when the first module of a section was hidden. + ## [2.0.5] - 2016-09-20 ### Added diff --git a/css/main.css b/css/main.css index 7ae902d6..f2188c66 100644 --- a/css/main.css +++ b/css/main.css @@ -113,13 +113,15 @@ sup { */ .module { - margin-top: 30px; + margin-bottom: 30px; } -.module:first-child { - margin-top: 0; +.region.bottom .module { + margin-top: 30px; + margin-bottom: 0px; } + /** * Region Definitions. */ diff --git a/modules/default/updatenotification/updatenotification.js b/modules/default/updatenotification/updatenotification.js index 6b79e862..cd2ba42c 100644 --- a/modules/default/updatenotification/updatenotification.js +++ b/modules/default/updatenotification/updatenotification.js @@ -10,19 +10,28 @@ Module.register("updatenotification", { start: function () { Log.log("Start updatenotification"); - var self = this; + }, notificationReceived: function(notification, payload, sender) { if (notification === "DOM_OBJECTS_CREATED") { this.sendSocketNotification("CONFIG", this.config); + this.hide(0,{lockString: self.identifier}); } }, socketNotificationReceived: function (notification, payload) { if (notification === "STATUS") { this.status = payload; - this.updateDom(1000); + this.updateUI(); + } + }, + + updateUI: function() { + var self = this; + if (this.status && this.status.behind > 0) { + self.updateDom(0); + self.show(1000, {lockString: self.identifier}); } }, From b9f308c8327b0f0ea659cfad23db1fcacd8bbce2 Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Sat, 15 Oct 2016 17:11:03 +0200 Subject: [PATCH 116/120] Stylelint fixes --- css/main.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/css/main.css b/css/main.css index f2188c66..5e63e596 100644 --- a/css/main.css +++ b/css/main.css @@ -118,10 +118,9 @@ sup { .region.bottom .module { margin-top: 30px; - margin-bottom: 0px; + margin-bottom: 0; } - /** * Region Definitions. */ From cc10cd88d34e834607dd991d6995809b34c011ea Mon Sep 17 00:00:00 2001 From: Jopyth Date: Sun, 16 Oct 2016 17:24:21 +0200 Subject: [PATCH 117/120] change position from absolute to fixed --- js/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/main.js b/js/main.js index e97f3e10..9c489ee0 100644 --- a/js/main.js +++ b/js/main.js @@ -196,7 +196,7 @@ var MM = (function() { // since it's fade out anyway, we can see it lay above or // below other modules. This works way better than adjusting // the .display property. - moduleWrapper.style.position = "absolute"; + moduleWrapper.style.position = "fixed"; if (typeof callback === "function") { callback(); } }, speed); From ece0d9301f01518aace892d5797e599a307150db Mon Sep 17 00:00:00 2001 From: Jopyth Date: Sun, 16 Oct 2016 17:32:05 +0200 Subject: [PATCH 118/120] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b1c8a1..8d51f39b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Solve an issue where module margins would appear when the first module of a section was hidden. +- Solve visual display errors on chrome, if all modules in one of the right sections are hidden ## [2.0.5] - 2016-09-20 From 4d2eedc56bb3da61ccec2e6c292b87b966ba8df0 Mon Sep 17 00:00:00 2001 From: Jopyth Date: Sun, 16 Oct 2016 17:32:17 +0200 Subject: [PATCH 119/120] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d51f39b..5c9e649a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Solve an issue where module margins would appear when the first module of a section was hidden. -- Solve visual display errors on chrome, if all modules in one of the right sections are hidden +- Solved visual display errors on chrome, if all modules in one of the right sections are hidden ## [2.0.5] - 2016-09-20 From 1b7fe286a657f4dc7f16fe56e48516e24df6793a Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Mon, 17 Oct 2016 17:03:10 +0200 Subject: [PATCH 120/120] remove logging --- modules/default/updatenotification/node_helper.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/default/updatenotification/node_helper.js b/modules/default/updatenotification/node_helper.js index d049e34b..862087d8 100644 --- a/modules/default/updatenotification/node_helper.js +++ b/modules/default/updatenotification/node_helper.js @@ -34,7 +34,6 @@ module.exports = NodeHelper.create({ delay = 60 * 1000 } - console.log(delay); var self = this; clearTimeout(this.updateTimer); this.updateTimer = setTimeout(function() { @@ -42,4 +41,4 @@ module.exports = NodeHelper.create({ }, delay); } -}); \ No newline at end of file +});