Compare commits

..

398 Commits

Author SHA1 Message Date
Michael Teeuw
fb0cc61e09 Merge pull request #1241 from MichMich/develop
Release 2.3.0
2018-04-01 14:16:36 +02:00
Michael Teeuw
be29b5daf8 Prepare for release 2.3.0 2018-04-01 14:08:38 +02:00
Michael Teeuw
f010adabd0 Merge pull request #1232 from Kiina/develop
Update electron to 1.7.13
2018-03-28 12:27:05 +02:00
Dominic Dey-Marckmann
c93b263b1f Update electron to 1.7.13 2018-03-27 21:09:08 +02:00
Michael Teeuw
15f34d6b54 Update CHANGELOG.md 2018-03-25 14:56:20 +02:00
Michael Teeuw
d0eeb55999 Merge pull request #1186 from BonySimon/patch-1
Fix exception on translation of objects
2018-03-25 14:55:52 +02:00
Michael Teeuw
08c0d39b23 Update translator.js 2018-03-25 14:55:42 +02:00
Michael Teeuw
d0ecde3277 Merge pull request #1176 from relm923/forecast_max_days
Forecast - Max Days
2018-03-25 14:53:30 +02:00
Michael Teeuw
45ec57afd7 Merge branch 'develop' into forecast_max_days 2018-03-25 14:52:42 +02:00
Michael Teeuw
b0cd053083 Merge pull request #1202 from iampranavsethi/currentweather-module-updates
Currentweather module updates
2018-03-25 14:52:05 +02:00
Michael Teeuw
698a11be58 Merge branch 'develop' into currentweather-module-updates 2018-03-25 14:51:47 +02:00
Michael Teeuw
efb08fb1e1 Update CHANGELOG.md 2018-03-25 14:51:18 +02:00
Michael Teeuw
f89bc8422e Merge pull request #1224 from bacongobbler/clearer-install-question
capitalize "y/n" for clearer intent
2018-03-25 14:47:35 +02:00
Michael Teeuw
4bf4889a08 Merge pull request #1225 from moham96/patch-1
use shallow clone
2018-03-25 14:47:09 +02:00
Michael Teeuw
01ab8ba38e Merge pull request #1227 from E3V3A/patch-4
removed known issues as they are closed
2018-03-25 14:46:44 +02:00
E:V:A
ae6d15e812 removed known issues as they are closed 2018-03-25 12:07:29 +03:00
MOHAMMAD RASIM
1abfbe1d34 use shallow clone
not need to download the whole repo history
2018-03-24 16:11:57 +03:00
Matthew Fisher
d3095297c2 capitalize "y/n" for clearer intent
If you press enter, `choice` is an empty string and will default to "no". The convention is to capitalize the default answer so users know what happens when they auto-accept prompts.
2018-03-23 16:29:37 -07:00
Michael Teeuw
79d40d5644 Merge pull request #1199 from ThomasMirlacher/develop
Add dc:date to parsing in newsfeed module, which allows parsing of mo…
2018-03-21 12:17:23 +01:00
Thomas Mirlacher
008e305a84 use doublequotes. 2018-03-21 11:58:09 +01:00
Michael Teeuw
0379611edd Merge pull request #1218 from kjb085/kb/calendar-adv-filter
Add advanced filtering to excludedEvents
2018-03-21 11:34:41 +01:00
Kenn Breece
96d883c1c7 Merge branch 'develop' into kb/calendar-adv-filter 2018-03-20 15:38:16 -04:00
Kenn Breece
be0f262e37 Add advanced filtering to excludedEvents 2018-03-18 23:54:23 -04:00
Michael Teeuw
1676adf071 Merge pull request #1209 from E3V3A/patch-3
update node stable to 9.x
2018-03-14 10:26:25 +01:00
E:V:A
a5d5630067 update node stable to 9.x 2018-03-14 11:24:41 +02:00
Pranav Sethi
275956caba Fixed typos in README.md for currentweather. 2018-03-12 22:22:45 -04:00
Michael Teeuw
bf8ed87fc9 Merge pull request #1197 from ptz0n/patch-1
Update README.md
2018-03-12 18:34:21 +01:00
Michael Teeuw
fb3afac097 Merge pull request #1200 from djgalloway/wip-apt-y
Assume yes when installing deps on Raspberry Pi via apt-get
2018-03-12 18:33:36 +01:00
Michael Teeuw
eda8b037a9 Merge pull request #1205 from Tajnymag/develop
Added yarn support
2018-03-12 18:32:31 +01:00
Marek Lukáš
8ef14f7a54 Added changes from [9974e35] to CHANGELOG 2018-03-12 15:33:30 +01:00
Marek Lukáš
9974e35656 Added yarn support 2018-03-12 15:28:43 +01:00
Pranav Sethi
15bc5431b6 Fixed Trailling Spaces 2018-03-12 05:25:33 -04:00
Pranav Sethi
f767531d89 Fixed Trailling Spaces 2018-03-12 05:25:01 -04:00
Pranav Sethi
7285ada9dd Added feels like and kmph wind for currentweather module 2018-03-12 05:06:16 -04:00
Pranav Sethi
b9b9773df9 Merge branch 'develop' into currentweather-module-updates 2018-03-12 03:56:44 -04:00
David Galloway
c29a83b259 Assume yes when installing deps on Raspberry Pi via apt-get
Signed-off-by: David Galloway <dgallowa@redhat.com>
2018-03-11 13:17:33 -04:00
Thomas Mirlacher
fa45e66da6 Add dc:date to parsing in newsfeed module, which allows parsing of more rss feeds. 2018-03-10 00:30:45 +01:00
Erik Eng
7cbcdddac9 Merge branch 'develop' into patch-1 2018-03-07 09:18:07 +01:00
Erik Eng
a2f17900da Update README.md
Correct manual installation step.
2018-03-07 09:13:33 +01:00
Michael Teeuw
fb7e97b8ad Merge pull request #1190 from E3V3A/patch-1
made the module "this" instances into a table
2018-03-06 09:36:04 +01:00
Michael Teeuw
0c92a8a8e9 Merge pull request #1191 from E3V3A/patch-2
fix md header
2018-03-06 09:35:34 +01:00
Michael Teeuw
dcc59380e5 Merge pull request #1194 from bastilimbach/develop
Remove old docker config and link to docker repository
2018-03-06 09:33:50 +01:00
Sebastian Limbach
f9bf25f96d Add changes 2018-03-04 14:07:44 +01:00
Sebastian Limbach
cbcbea8b08 Remove old docker config 2018-03-04 13:59:45 +01:00
Pranav Sethi
62eb4f20da Fixed Trailling Spaces to Pass checks 2018-03-03 05:08:12 -05:00
Pranav Sethi
43d5311e5e Fixed Trailling Spaces 2018-03-03 05:00:26 -05:00
Pranav Sethi
a6f08a09d5 Added Feels Like and Windspeed in KMPH 2018-03-03 04:52:22 -05:00
Pranav Sethi
d93f5d7785 Added Feels Like and Windspeed in KMPH 2018-03-03 04:21:24 -05:00
E:V:A
c7170e6dc2 fix md header 2018-03-01 11:53:10 +02:00
E:V:A
bcf3ca7339 made the module "this" instances into a table 2018-03-01 09:44:57 +02:00
Steelskin3
0388f5787a Fix exception on translation of objects
Sometimes, the content of translations[module.name][key] is not a string but an entire object. It cause a crash on template.replace(...) of createStringFromTemplate(...). It is currently the case of MMM-Voice-Control and the previous commit have broked this module (10 month ago... I am surprised to be the first founded it)
2018-02-23 11:51:59 +01:00
Michael Teeuw
6514df9d96 Merge pull request #1184 from patoberli/patch-1
Update README.md
2018-02-20 11:29:27 +01:00
Michael Teeuw
8f5b9869dc Merge branch 'develop' into patch-1 2018-02-20 11:28:58 +01:00
patoberli
580c5fe23f Update README.md
Added a hint to use the full and not lite version of Raspbian, as the GUI is missing and thus ndm (electron) can't start after the installation.
2018-02-17 21:54:31 +01:00
Michael Teeuw
b0af5b26ba Merge pull request #1183 from fewieden/feature/translations-update
translations update
2018-02-17 10:30:30 +01:00
Michael Teeuw
9e898932f6 Merge pull request #1182 from fewieden/feature/automated-tests
Automated tests
2018-02-17 10:29:23 +01:00
fewieden
1f873b93f6 changelog, linting 2018-02-17 10:17:59 +01:00
fewieden
f414707f11 update translations for updatenotifications 2018-02-17 10:14:37 +01:00
fewieden
505825056c use translation template for updatenotifications 2018-02-17 10:10:57 +01:00
fewieden
38f7716738 linting 2018-02-17 09:20:34 +01:00
fewieden
a69d08b554 changelog 2018-02-17 09:18:12 +01:00
fewieden
3ccdb64833 deprecated unit tests 2018-02-16 22:09:15 +01:00
fewieden
78d8bff599 clone array, clone nested object, add safe checks for objects (memory address) 2018-02-16 19:58:28 +01:00
fewieden
a756fed70b fixed and reenabled lockstring test 2018-02-16 08:43:27 +01:00
fewieden
3e2a1e3548 linting 2018-02-16 00:08:11 +01:00
fewieden
96b2f2b3a4 clone object unit test 2018-02-16 00:01:02 +01:00
fewieden
d81d7d4f68 compare version unit test 2018-02-15 23:53:57 +01:00
fewieden
20244c4fb5 translations integration test 2018-02-15 23:22:52 +01:00
Michael Teeuw
b50d31ffe2 Merge pull request #1178 from E3V3A/develop
Added ToC
2018-02-13 09:24:36 +01:00
fewieden
d709a44960 strip comments unit test 2018-02-13 07:17:46 +01:00
E:V:A
4e4d07ced6 Added ToC
ToDo: Fix ToC links to headers
2018-02-11 18:24:31 +02:00
fewieden
d775bc9d7e loadCoreTranslationsFallback unit test 2018-02-11 09:08:09 +01:00
fewieden
85528761eb only load core callback if there is one available 2018-02-11 09:07:41 +01:00
fewieden
ad3eac9ddb loadcoretransations unit test 2018-02-11 08:58:02 +01:00
Reagan Elm
613f9fccd2 Update changelog 2018-02-10 20:56:10 -05:00
Reagan Elm
3d1741c904 Respect maxNumberOfDays regardless of endpoint 2018-02-10 20:53:38 -05:00
fewieden
26be14ba67 load unit test 2018-02-10 20:33:22 +01:00
fewieden
daa0755920 add missing parameter in documentation 2018-02-10 12:38:55 +01:00
fewieden
305d60e09b translator unit tests 2018-02-10 12:32:43 +01:00
fewieden
d0029efd02 utils unit tests 2018-02-10 12:30:33 +01:00
fewieden
fb4d42bf5b moved test 2018-02-10 12:28:30 +01:00
Michael Teeuw
20eec53b14 Add Manifesto. 2018-02-07 13:04:10 +01:00
Michael Teeuw
8343db44db Merge pull request #1173 from vvzvlad/vvzvlad_local
add variable morning afternoon times
2018-02-07 12:32:42 +01:00
vvzvlad
649652e373 Merge branch 'develop' into vvzvlad_local 2018-02-07 14:10:43 +03:00
vvzvlad
e37ed7c32d add variable morning afternoon times 2018-02-07 14:06:26 +03:00
vvzvlad
f9a525068b add variable morning afternoon times 2018-02-05 18:15:02 +03:00
Michael Teeuw
aa11e6d62e Merge pull request #1166 from henrysun18/develop
Show remote compliments on boot
2018-02-01 08:20:22 +01:00
henrysun18
6802d152da Show remote compliments at boot instead of after one updateInterval 2018-01-31 23:19:47 -05:00
Michael Teeuw
3b40f393d8 Merge pull request #1163 from pinsdorf/patch-1
corrected link to 3rd party modules wiki page
2018-01-30 13:49:37 +01:00
pinsdorf
020443ae8a corrected link to 3rd party modules wiki page
The link to the 3rd Party Modules still directs to the old wiki page, where use has to follow another link to the right page. Updated the link in README.md to navigate to the right wiki page instantly.
2018-01-30 10:59:18 +01:00
Michael Teeuw
1d0baccffc Merge pull request #1161 from thobach/master
Allow to scroll in full page article view of default newsfeed module
2018-01-30 09:47:33 +01:00
Thomas Bachmann
5426f0f329 Updated documentation for scroll mode in newsfeed module 2018-01-29 21:41:43 +01:00
Thomas Bachmann
790249dd1a Merge branch 'MichMich/develop' 2018-01-29 21:37:25 +01:00
Thomas Bachmann
446a201d25 Allow to scroll articles with gesture events 2018-01-29 21:26:34 +01:00
Thomas Bachmann
b6538d5e18 Merge remote-tracking branch 'MichMich/master' 2018-01-29 18:54:32 +01:00
Michael Teeuw
edd6043059 Fail PRs that are sent to the master branch. 2018-01-26 12:12:44 +01:00
Michael Teeuw
fe4ffeb7f1 Text cleanup. 2018-01-25 20:45:25 +01:00
Michael Teeuw
27b3875bfb Changed missing Changlog text. 2018-01-25 20:38:42 +01:00
Michael Teeuw
e2dbe8a0a2 Minor fixes. 2018-01-25 20:07:51 +01:00
Michael Teeuw
29fc7910b7 Remove Jest. Update dangerfile.js. 2018-01-25 19:51:23 +01:00
Michael Teeuw
22e2fdc707 Jest implementation to get danger.js to work. 2018-01-25 19:43:09 +01:00
Michael Teeuw
584786eb9f Temp disable danger. 2018-01-25 17:00:51 +01:00
Michael Teeuw
d803d9eaf9 Import 'includes' from lodash. 2018-01-25 16:39:49 +01:00
Michael Teeuw
bad6575d83 Add Danger.js 2018-01-25 16:24:05 +01:00
Michael Teeuw
fbcb7ae836 Update README.md 2018-01-23 19:10:37 +01:00
Michael Teeuw
2c1a1b10c8 Merge pull request #1147 from E3V3A/patch-2
Update README.md
2018-01-23 09:51:15 +01:00
E:V:A
155fb16a8a Update README.md
Updated README by reformatting and restructuring.
- Added, Clarified and corrected grammatics and wrong info 
- Moved/Removed some redundant parts
2018-01-23 10:44:55 +02:00
Michael Teeuw
b1ab2ce96a Merge pull request #1146 from cederstrom/put-article-in-front-of-modules
Put article iframe in front of modules
2018-01-21 11:33:22 +01:00
Andreas Cederström
f299ba6218 Put article ifram in front of modules
Before this change the article was brought up in its ifram in fullscreen and you could still see the other modules in front of it
2018-01-20 23:46:58 +01:00
Michael Teeuw
d167ad1923 Merge pull request #1136 from E3V3A/patch-2
Update README
2018-01-19 09:15:54 +01:00
E:V:A
93626e8154 Fixed bullet points markup for lint 2018-01-19 09:13:59 +02:00
Michael Teeuw
d5040c091a Merge pull request #1143 from shbatm/bug-fix
Fix for #1140 - sendNotification module errors after #1116
2018-01-18 13:35:47 +01:00
shbatm
868daef0f0 Fix for #1140 - sendNotification module errors after #1116 2018-01-17 09:49:17 -06:00
Michael Teeuw
dc8e85e7f2 Merge pull request #1139 from amcolash/patch-1
Change English translation to "In 2 days"
2018-01-16 09:20:57 +01:00
Michael Teeuw
22d32d7ca3 Merge pull request #1141 from ConnorChristie/old-dom-event-fix
Fix to emit DOM_OBJECTS_CREATED event after module DOMs have actually loaded
2018-01-16 09:20:39 +01:00
Connor Christie
2d500f8074 Fix to emit DOM_OBJECTS_CREATED event after module DOMs have actually loaded 2018-01-14 22:03:09 -06:00
Andrew McOlash
452cdc17c6 Change English translation to "In 2 days" 2018-01-14 15:52:15 -06:00
E:V:A
bcbfee0321 Update README
Updated README to warn about long installation time as discussed in #1124.
2018-01-12 10:00:35 +02:00
Michael Teeuw
dab2e7ede3 Merge pull request #1127 from roramirez/set-version-test-7-node
Set only 7 version of node to run tests in Travis CI
2018-01-08 11:26:25 +01:00
Michael Teeuw
d91acb8352 Merge pull request #1126 from d-Rickyy-b/patch-1
Fix typo in newsfeed documentation
2018-01-08 11:23:49 +01:00
Rodrigo Ramírez Norambuena
373dd8058e Set only 7 version of node to run tests in Travis CI 2018-01-07 01:03:00 -03:00
Rico
de6310e52a Fix typo
A little typo which lead to poor formatting
2018-01-07 03:30:01 +01:00
Michael Teeuw
8c297a4a4c Merge pull request #1123 from E3V3A/patch-1
Added general advice
2018-01-06 19:49:44 +01:00
E:V:A
4eb5c817bc fixed typos 2018-01-06 20:19:43 +02:00
E:V:A
07e4b26b9e Added general advice 2018-01-06 19:57:46 +02:00
Michael Teeuw
b63aa62985 Merge pull request #1121 from henrikra/master
Add basic typescript types for module
2018-01-06 14:29:52 +01:00
Henrik Raitasola
ca701c0580 Merge branch 'master' of github.com:henrikra/MagicMirror 2018-01-06 15:26:51 +02:00
Henrik Raitasola
e37043a6a8 Solve conflict 2018-01-06 15:26:38 +02:00
Michael Teeuw
7c26975d14 Merge branch 'develop' into master 2018-01-06 14:16:21 +01:00
Henrik Raitasola
47f8a43637 Add changelog 2018-01-06 15:10:10 +02:00
Henrik Raitasola
1238c0cefe Rename file to be more explicit 2018-01-06 15:06:58 +02:00
Henrik Raitasola
4c35fda045 Add most used module properties 2018-01-06 15:04:54 +02:00
Henrik Raitasola
780124c2f5 Add basic types to get started 2018-01-06 14:51:32 +02:00
Michael Teeuw
38e0af41ce Merge pull request #1116 from ConnorChristie/async-dom
DOM creation notifications in cases of async template rendering
2018-01-04 21:51:13 +01:00
Connor Christie
601e99eec0 Merge branch 'develop' into async-dom 2018-01-02 18:10:07 -06:00
Connor Christie
745a2adee7 Merge branch 'develop' into async-dom 2018-01-02 18:08:55 -06:00
Connor Christie
9e83234df1 Update changelog 2018-01-02 18:06:21 -06:00
Connor Christie
e45eeadf7d Merge remote-tracking branch 'origin/master' into async-dom 2018-01-02 18:04:03 -06:00
Michael Teeuw
9a778cea6b Merge v2.2.2 changes. 2018-01-02 18:46:41 +01:00
Michael Teeuw
20823bfc87 Add missing package-lock.json. 2018-01-02 18:41:33 +01:00
Connor Christie
be3d703692 Fix linter errors 2018-01-01 10:55:39 -06:00
Connor Christie
e2df5739f0 Update module docs 2018-01-01 10:40:52 -06:00
Connor Christie
7bb11d6436 Add documentation regarding updates 2018-01-01 10:38:00 -06:00
Connor Christie
80b84212cc Add notification for module dom creation with async support 2018-01-01 10:23:15 -06:00
Connor Christie
4a1bee769b Add true module dom creation events 2018-01-01 09:42:34 -06:00
Michael Teeuw
de99a7aeaf Merge 2.2.1 changes. 2018-01-01 14:23:38 +01:00
Michael Teeuw
a0a02701b0 Update version number. 2018-01-01 13:42:39 +01:00
Michael Teeuw
1314ae1555 Add info about v2.2.1 2018-01-01 13:40:39 +01:00
Michael Teeuw
67cf0e745c Fix linting errors. 2018-01-01 13:39:05 +01:00
Michael Teeuw
538a2acbf5 Fix linting errors. 2018-01-01 13:38:07 +01:00
Michael Teeuw
8d0e453666 Preparation for v2.3.0 release. 2018-01-01 12:59:28 +01:00
Michael Teeuw
ace04f0b30 Merge pull request #1115 from MichMich/develop
Cleanup.
2018-01-01 12:48:22 +01:00
Michael Teeuw
f8e25d6c4a Cleanup. 2018-01-01 12:47:54 +01:00
Michael Teeuw
b2bc43da4f Merge pull request #1113 from MichMich/develop
Release v2.2.0.
2018-01-01 12:44:24 +01:00
Michael Teeuw
cb12e540d2 Add package lock. 2018-01-01 12:40:37 +01:00
Michael Teeuw
39955af2fa Upgrade packages. 2018-01-01 12:36:53 +01:00
Michael Teeuw
86e1f0615d Prepare for release v2.2.0 2018-01-01 12:33:00 +01:00
Michael Teeuw
dc81ab6dee Merge pull request #1111 from TTigges/weather_decimal_marks
added option of decimal comma for temp values for default weather modules
2017-12-31 12:25:24 +01:00
Michael Teeuw
f8cf6a65ae Merge branch 'develop' into weather_decimal_marks 2017-12-31 12:25:06 +01:00
Michael Teeuw
ba909c696d Merge branch 'develop' into weather_decimal_marks 2017-12-31 12:24:25 +01:00
Torben Tigges
df0515cebf currentweather, weatherforecast, changed option of decimal comma to any decimal symbol 2017-12-31 01:15:59 +01:00
Torben Tigges
46c0e14d67 currentweather, weatherforecast, added option of decimal comma for temperature values to config 2017-12-30 22:03:26 +01:00
Michael Teeuw
97d7733464 Remove trailing spaces. 2017-12-30 21:46:34 +01:00
Michael Teeuw
afda84ef09 Electron reverted. 2017-12-30 21:39:56 +01:00
Michael Teeuw
61d6e74102 Use an old electron version ...
Hopefully Electron will be fixed soon.
2017-12-30 21:33:56 +01:00
Michael Teeuw
8d74258ce2 Merge pull request #1102 from EricWarnke/patch-1
Spelling/grammar fix
2017-12-13 09:22:38 +01:00
Eric Warnke
5dfba0b834 Spelling/gramar fix 2017-12-12 15:54:33 -07:00
Michael Teeuw
056370ec08 Merge pull request #1092 from sebcaps/develop
Fix #1091 : handle empty description
2017-11-26 20:54:13 +01:00
unknown
4e2c254558 Fix #1091 : handle empty description 2017-11-26 11:52:01 +01:00
Michael Teeuw
38c2bdb447 Merge pull request #1090 from rejas/patch-1
Fix typo
2017-11-26 10:42:20 +01:00
Veeck
0cee4717e2 Fix typo 2017-11-26 10:02:31 +01:00
Michael Teeuw
221b04c466 Merge pull request #1089 from MichMich/patch-1
Update CHANGELOG.md
2017-11-25 12:15:54 +01:00
Michael Teeuw
237e9b7191 Merge pull request #1088 from reeno/patch-2
fixed width Font Awesome symbols
2017-11-25 12:15:27 +01:00
Michael Teeuw
9457e44a88 Update CHANGELOG.md 2017-11-25 12:14:54 +01:00
reeno
80a9d40a44 fixed width Font Awesome symbols
See http://fontawesome.io/examples/#fixed-width
2017-11-25 12:08:40 +01:00
Michael Teeuw
0715325a63 Merge pull request #1081 from ChytilTomas/develop
Develop
2017-11-17 09:06:06 +01:00
Michael Teeuw
0a026fef0f Update CHANGELOG.md 2017-11-17 09:05:33 +01:00
Tomáš Chytil
5fbf650d2d Czech translation 2017-11-16 23:06:52 +01:00
Tomáš Chytil
dabdde0c3f Czech translation 2017-11-16 23:01:00 +01:00
Michael Teeuw
b6ca92a7ef Merge pull request #1080 from slametps/develop
some new features (resubmission)
2017-11-15 08:26:25 +01:00
slametps
62f7339170 add some new options
add some new options
2017-11-15 12:21:45 +07:00
slametps
eaec682ea7 per feed reloadInterval support
per feed reloadInterval support
2017-11-15 12:21:22 +07:00
slametps
12110a4442 new options
* truncated description support
* specific reloadInterval for particular feed
2017-11-15 12:21:02 +07:00
slametps
df597f53b2 add no-cache entries in HTTP header
add no-cache entries in HTTP header
2017-11-15 12:19:53 +07:00
slametps
d7d40254d4 updated
updated
2017-11-15 12:19:19 +07:00
Michael Teeuw
e7c4a2cce6 Merge pull request #1072 from morozgrafix/newsfeed_filter
Added ability to set a list of prohibited words that will be filtered…
2017-11-01 11:53:00 +01:00
Sergey Morozov
0eb1c0cea6 Added ability to set a list of prohibited words that will be filtered out of newsfeed
Resolves #1071

`prohibitedWords` config parameter is an array of words. If set and case insensitive greedy match is found anywhere in the title then that newsfeed item will not be displayed. Readme updated with instructions.

Users should be careful on the words selection as careless setting may remove many or all items from the newsfeed. Some obvious mistakes like `space, comma, dot` etc. can be prevented programatically, but I left it out of this PR

Example:

with `prohibitedWords: ['dodgers']`

Original `newsItems`:
```
0:{title: "New York City, Russia, Los Angeles Dodgers: Your Wednesday Briefing", description: "Here’s what you need to know to start your day.", pubdate: "Wed, 01 Nov 2017 09:37:36 GMT", url: "https://www.nytimes.com/2017/11/01/briefing/new-yo…ssia-los-angeles-dodgers.html?partner=rss&emc=rss", sourceTitle: "New York Times"}
1:{title: "A Mangled School Bus, Bodies Everywhere; ‘It Was Surreal’", description: "A truck ramming bicyclists. The driver emerging wi…e attack, it was as confusing as it was gruesome.", pubdate: "Wed, 01 Nov 2017 09:27:41 GMT", url: "https://www.nytimes.com/2017/10/31/nyregion/nyc-sc…r-attack-truck-witnesses.html?partner=rss&emc=rss", sourceTitle: "New York Times"}
2:{title: "Dodgers 3, Astros 1 | Series tied, 3-3: With a Rally and a Romp, Dodgers Top Astros and Force Game 7", description: "Down by a run with just four innings left in Game …nst a dominating Justin Verlander. Game 7 awaits.", pubdate: "Wed, 01 Nov 2017 07:21:07 GMT", url: "https://www.nytimes.com/2017/11/01/sports/dodgers-win-game-6.html?partner=rss&emc=rss", sourceTitle: "New York Times"}
3:{title: "José Andrés Fed Puerto Rico, and May Change How Aid Is Given", description: "The chef’s huge effort is just the latest led by c…ocally based way to feed people after a disaster.", pubdate: "Wed, 01 Nov 2017 06:40:09 GMT", url: "https://www.nytimes.com/2017/10/30/dining/jose-andres-puerto-rico.html?partner=rss&emc=rss", sourceTitle: "New York Times"}
```

Filtered `newsItems`:
```
0:{title: "A Mangled School Bus, Bodies Everywhere; ‘It Was Surreal’", description: "A truck ramming bicyclists. The driver emerging wi…e attack, it was as confusing as it was gruesome.", pubdate: "Wed, 01 Nov 2017 09:27:41 GMT", url: "https://www.nytimes.com/2017/10/31/nyregion/nyc-sc…r-attack-truck-witnesses.html?partner=rss&emc=rss", sourceTitle: "New York Times"}
1:{title: "José Andrés Fed Puerto Rico, and May Change How Aid Is Given", description: "The chef’s huge effort is just the latest led by c…ocally based way to feed people after a disaster.", pubdate: "Wed, 01 Nov 2017 06:40:09 GMT", url: "https://www.nytimes.com/2017/10/30/dining/jose
```
2017-11-01 03:50:34 -07:00
Michael Teeuw
f4d5996a88 Allow use of .njk extension for template files. 2017-10-18 13:49:03 +02:00
Michael Teeuw
c75662e720 Remove trailing spaces. 2017-10-18 12:01:06 +02:00
Michael Teeuw
79a662fb93 Log nunjucks parsing errors for debugging. 2017-10-18 11:55:02 +02:00
Michael Teeuw
8b009b7ee9 Add Catalan translation. 2017-10-18 10:15:47 +02:00
Michael Teeuw
c4face30cc Update CHANGELOG.md 2017-10-18 10:14:54 +02:00
sergibarca
d4dbb5cb51 Translation to Catalan. 2017-10-17 22:24:13 +02:00
Michael Teeuw
1e27187652 Merge pull request #1060 from nhubbard/revert-1053-remove-package-lock.json
Revert "Delete large package-lock.json files"
2017-10-16 14:46:39 +02:00
Michael Teeuw
3ff278291f Merge pull request #1061 from qistoph/difflink
Add Github diff link to update info
2017-10-16 14:43:55 +02:00
Chris van Marle
4e8bf216df Update CHANGELOG 2017-10-16 14:26:15 +02:00
Chris van Marle
e7b9100f1c Add Github link to update info 2017-10-16 14:24:29 +02:00
Michael Teeuw
08aa9790f3 Fix lint issues. 2017-10-16 14:17:12 +02:00
Michael Teeuw
5f13fd2dca Merge pull request #1058 from shbatm/develop_1056
Gracefully Shutdown Module node_helpers on exit/SIGINT (Fixes #1056)
2017-10-16 13:59:40 +02:00
shbatm
f4c6f42c38 Added default implementation of stop() function. 2017-10-15 18:44:11 -05:00
Nicholas Hubbard
6a10d08189 Revert "Delete large package-lock.json files" 2017-10-13 19:59:39 -04:00
shbatm
f646360af6 Gracefully shutdown node_helpers (Fixes #1056)
Updated documentation


Corrected Typo in Documentation


Style correction
2017-10-13 16:43:11 -05:00
Michael Teeuw
95f265ebbf Merge pull request #1057 from Stromwerk/develop
Add Bulgarian translations for MagicMirror² and Alert module
2017-10-13 21:05:16 +02:00
Kalin Koychev
39d0142993 - Add Bulgarian translations for MagicMirror² and Alert module 2017-10-13 21:51:21 +03:00
Michael Teeuw
da16172244 Merge pull request #1055 from qistoph/commentscheck
Check trailing white space in comments too
2017-10-13 20:39:44 +02:00
Michael Teeuw
71aded0fae Merge pull request #1054 from qistoph/gruntfix
Fix some white space grunt errors
2017-10-13 20:39:04 +02:00
Michael Teeuw
e173b3ea41 Merge pull request #1053 from roramirez/remove-package-lock.json
Delete large package-lock.json files
2017-10-13 20:38:18 +02:00
Chris van Marle
6c4f9466b9 Don't ignore comments in trailing whitespace check 2017-10-12 11:06:57 +02:00
Chris van Marle
664196c5ef Fix some trailing whitespace grunt errors 2017-10-12 10:23:40 +02:00
Michael Teeuw
c8d5044e7a Merge pull request #1051 from egin10/patch-1
correcting translation for indonesian language
2017-10-10 17:20:28 +02:00
Michael Teeuw
d8c31fe560 Merge pull request #1049 from egin10/patch-2
Updating and Correcting Translation
2017-10-10 17:19:50 +02:00
Rodrigo Ramírez Norambuena
516db855f5 Delete large package-lock.json files 2017-10-08 23:41:51 -03:00
Ginanjar S.B
9cdcf08ab1 correcting translation for indonesian language 2017-10-09 08:05:11 +07:00
Ginanjar
326fa73b22 Updating and Correcting Translation 2017-10-08 03:03:29 +07:00
Michael Teeuw
79cacefd07 Merge pull request #1047 from jannickfahlbusch/useHTTPSOpenWeatherMap
Weather (Current/Forecast): Use HTTPS instead of HTTP
2017-10-06 21:32:49 +02:00
Jannick Fahlbusch
07e28bfee6 Use HTTPS instead of HTTP
Chrome blocks insecure requests (HTTP) when MagicMirror is loaded
via HTTPS. This commit changes the protocol used for OpenWeatherMap.
2017-10-06 21:31:06 +02:00
Michael Teeuw
980b017fbe Merge pull request #1046 from wbleek/master
moved weekNumber into field and adjusted language handling accordingly [issue #910]
2017-10-03 22:13:21 +02:00
Wolf-Gideon Bleek
4567fd1eb0 Merge branch 'develop' into master 2017-10-03 21:29:10 +02:00
Wolf-Gideon Bleek
8c150c23f3 moved weekNumber into field and adjusted language handling accordingly [issue #910] 2017-10-03 21:25:30 +02:00
Wolf-Gideon Bleek
b4fd570269 moved weekNumber into field and adjusted language handling accordingly [issue #910] 2017-10-03 21:18:25 +02:00
Michael Teeuw
6e051d73c1 Merge pull request #1044 from cederstrom/honor-calendar-maximum-entries
Slice the list of all calendar events to honor config.maximumEntries
2017-10-01 21:51:33 +02:00
Michael Teeuw
e381e1a313 Merge pull request #1042 from roramirez/readme-localhost-bind
Updated readme about default value for `address` configuration
2017-10-01 21:49:47 +02:00
Andreas Cederström
2d03ff63cf Slice the list of all events to honor config.maximumEntries
Scenario:
* Specify more than one calendar in `config.calendars`
* Specify a maximum number of entries in `config.maximumEntries`

Result:
The module will show as many as maximumEntries for EACH calendar

Expected:
The module shall not show more than a total of maximumEntries, regardless of how many calendars I specify

Fixes #1043
2017-10-01 21:47:10 +02:00
Rodrigo Ramírez Norambuena
309de631ed Updated readme about default value for address configuration changed it
in https://github.com/MichMich/MagicMirror/commit/2f05228d
2017-10-01 15:01:34 -03:00
Michael Teeuw
bad7316b80 Allow html tags in text string. 2017-10-01 13:22:29 +02:00
Michael Teeuw
4757c36233 Updated changelog and minor fix example 2017-10-01 13:16:07 +02:00
Michael Teeuw
9ca6180207 Merge branch 'templates' into develop 2017-10-01 13:10:25 +02:00
Michael Teeuw
30179ad977 Setup of new dev release. 2017-10-01 12:39:48 +02:00
Michael Teeuw
b799609749 Merge pull request #1039 from MichMich/develop
Release 2.1.3
2017-10-01 12:36:53 +02:00
Michael Teeuw
efb6994ae7 Changes in preparation of 2.1.3 2017-10-01 12:34:54 +02:00
Michael Teeuw
880a977dd6 Merge pull request #1038 from roramirez/templates-fixes
This fix the follow things:
2017-09-30 13:39:00 +02:00
Michael Teeuw
6eceffb403 Merge pull request #1037 from roramirez/lint-fix
Little lint fix
2017-09-30 13:36:38 +02:00
Rodrigo Ramírez Norambuena
795e33881c This fix the follow things:
* The default screen on missing configuration file and syntax error.
    * Tests
2017-09-29 19:10:03 -03:00
Rodrigo Ramírez Norambuena
d310c3857f Little lint fix 2017-09-29 18:33:17 -03:00
Michael Teeuw
8c53908cc4 Update CHANGELOG.md 2017-09-29 13:37:24 +02:00
Michael Teeuw
589b54984a Add slack badge. 2017-09-29 13:36:44 +02:00
Michael Teeuw
3f30ed5251 Add info about weather forecast. 2017-09-29 13:01:08 +02:00
Michael Teeuw
3f9181905a Fix typo's. 2017-09-29 11:05:59 +02:00
Michael Teeuw
29f3a81666 Fix weather forecast. 2017-09-29 10:04:42 +02:00
Michael Teeuw
5efc43260e Switch to async rendering. 2017-09-28 16:43:38 +02:00
Michael Teeuw
e01794a07f First Nunchucks Implementation. 2017-09-28 16:11:25 +02:00
Michael Teeuw
5fde095a6f Merge pull request #1024 from roramirez/openweathermap-forescast
Hack fix issue #1017
2017-09-28 14:44:13 +02:00
Michael Teeuw
3237af2d85 Add translation: Welsh (Cymraeg) 2017-09-28 14:42:21 +02:00
Michael Teeuw
953b666ebd Update translations.js 2017-09-28 14:41:30 +02:00
Michael Teeuw
417bb4bf37 Merge pull request #1022 from meigwilym/meigwilym-welsh-lang
Welsh (Cymraeg) language file
2017-09-28 14:39:26 +02:00
Michael Teeuw
a55213d88a Merge pull request #1019 from EdgardosReis/develop
Updated pt.json translation
2017-09-28 14:38:55 +02:00
Michael Teeuw
ec84d190f4 Remove newline. 2017-09-28 14:38:39 +02:00
Michael Teeuw
1b0bad72de Remove newline. 2017-09-28 14:38:08 +02:00
Michael Teeuw
931055708d Merge pull request #1033 from roramirez/one-instance-all-module-position-spec
Refactor modules_position_spec use one instance for all it statements
2017-09-26 08:56:06 +02:00
Rodrigo Ramírez Norambuena
15fd570b49 Refactor modules_position_spec use one instance for all it statements 2017-09-25 20:52:27 -03:00
Michael Teeuw
5e51a438a7 Merge pull request #1025 from ryck/feature/indoorHumidity
Feature/indoor humidity
2017-09-20 15:19:53 +02:00
Ricardo Gonzalez
7f768059e6 Update README 2017-09-17 16:33:23 +01:00
Ricardo Gonzalez
ea70175a17 Merge branch 'develop' into feature/indoorHumidity
* develop: (71 commits)
  Update sample address
  set version of express-ipfilter:
  Describe default in comment of sample config
  More secure defaults.
  Fix grunt errors
  Weather forecast settings match current weather
  Fix JavaScript error in weatherforecast
  Update fr.json
  TestSuite: Show the missing strings for translations files.
  Update fr.json with added translations
  Added e2e test for font files
  Fix issue #986
  Fix extra tab file translations/zh_cn.json
  Add Changelog entry for new e2e test for helloworld module
  Small change for re-running Travis CI
  Change Two Conditionals to UpperCase-If
  Fix linting?
  Show Scale of Temperature if config flag is set
  Change to install Roboto fonts by npm
  Update stylelint package
  ...

# Conflicts:
#	CHANGELOG.md
2017-09-17 16:32:37 +01:00
Ricardo Gonzalez
74a736691a Merge remote-tracking branch 'upstream/develop' into develop
* upstream/develop: (71 commits)
  Update sample address
  set version of express-ipfilter:
  Describe default in comment of sample config
  More secure defaults.
  Fix grunt errors
  Weather forecast settings match current weather
  Fix JavaScript error in weatherforecast
  Update fr.json
  TestSuite: Show the missing strings for translations files.
  Update fr.json with added translations
  Added e2e test for font files
  Fix issue #986
  Fix extra tab file translations/zh_cn.json
  Add Changelog entry for new e2e test for helloworld module
  Small change for re-running Travis CI
  Change Two Conditionals to UpperCase-If
  Fix linting?
  Show Scale of Temperature if config flag is set
  Change to install Roboto fonts by npm
  Update stylelint package
  ...
2017-09-17 16:31:27 +01:00
Mei Gwilym
86ff44adfc Welsh (Cymraeg) language file 2017-09-13 22:17:07 +01:00
Rodrigo Ramírez Norambuena
58b763e935 Hack fix issue #1017 2017-09-12 10:31:49 -03:00
EdgardosReis
5c90cc59aa Updated pt.json translation 2017-09-10 21:42:01 +01:00
Michael Teeuw
710ab44073 Merge pull request #1014 from roramirez/tests/unit/weatherforecast
Add roundValue unit test function weatherforecast module:
2017-09-07 10:07:28 +02:00
Michael Teeuw
b28c5e6807 Merge pull request #1015 from roramirez/show-missing-string-test-translations
TestSuite: Show the missing strings for translations files.
2017-09-07 10:07:09 +02:00
Michael Teeuw
e5ead9ed44 Merge pull request #1004 from qistoph/issue950
More secure defaults.
2017-09-06 15:25:04 +02:00
Chris van Marle
d99897cf9d Update sample address
As proposed in review
2017-09-06 15:22:17 +02:00
Michael Teeuw
701a7cae02 Merge pull request #1011 from qistoph/fix_on_991
Fix on 991
2017-09-06 14:40:32 +02:00
Michael Teeuw
068b6a5470 Merge pull request #1012 from roramirez/set-version-express-ipfilter
set version of express-ipfilter:
2017-09-06 14:19:30 +02:00
Rodrigo Ramírez Norambuena
45d597ac49 set version of express-ipfilter:
Prevent problems with ipWhitelist using []

Information in https://forum.magicmirror.builders/topic/4716/issue-with-white-list-ip-s-not-working/14
4adc5dc33e
2017-09-05 23:56:32 -03:00
Chris van Marle
a518d3f33f Describe default in comment of sample config 2017-09-01 14:46:25 +02:00
Chris van Marle
2f05228d91 More secure defaults.
Without config, listen only on looback interface. In sample config
listen on any interface, but use an IP whitelist.

Related to #950
2017-09-01 14:46:25 +02:00
Chris van Marle
335ae0105f Fix grunt errors 2017-09-01 11:17:01 +02:00
Chris van Marle
62ce7a0e37 Weather forecast settings match current weather
This change makes the config of weather forecast more in line with
current weather. It uses the configured units (metric, imperial,
default) to determine the sign.
2017-09-01 10:58:21 +02:00
Chris van Marle
afa0fb8da1 Fix JavaScript error in weatherforecast
Change 5568e0c2ad introduces JavaScript
errors, because it's calling toUpperCase() on a boolean value.
2017-09-01 10:38:25 +02:00
Michael Teeuw
763d835f4e Merge pull request #1006 from gcarret/patch-1
Added translations for french language
2017-08-29 14:17:43 +02:00
Michael Teeuw
0289872dcd Merge pull request #1000 from QNimbus/fix-issue-986
Fix for issue 986 (font file paths)
2017-08-29 14:15:27 +02:00
Michael Teeuw
2810141bd6 Merge pull request #997 from roramirez/extra-tab-translations/zh_cn.json
Fix extra tab file translations/zh_cn.json
2017-08-29 14:14:32 +02:00
Michael Teeuw
93ea22c69d Merge pull request #996 from roramirez/default-hello-world
Default hello world
2017-08-29 14:14:12 +02:00
Michael Teeuw
daf76a311c Merge pull request #991 from DanielWeeber/temperature-scale-show
Temperature scale show
2017-08-29 14:13:43 +02:00
gcarret
b94271a725 Update fr.json 2017-08-29 07:21:10 +02:00
Rodrigo Ramírez Norambuena
1456aeedf2 TestSuite: Show the missing strings for translations files.
In the translations test now when are missing some translations for
determinated language will be show the missing string.

This can help to identified and improved the translations files.

/me listening STP: Silvergun superman
2017-08-28 21:31:01 -03:00
gcarret
4c6589a57e Update fr.json with added translations 2017-08-27 14:30:58 +02:00
Bas van Wetten
5b9a61b7db Added e2e test for font files 2017-08-21 15:33:17 +02:00
Bas van Wetten
96e71695c5 Fix issue #986
Fixed some font file paths
2017-08-21 11:51:57 +02:00
Rodrigo Ramírez Norambuena
2e7dd1bde3 Fix extra tab file translations/zh_cn.json 2017-08-20 22:50:29 -03:00
Rodrigo Ramírez Norambuena
2de543f5f9 Add Changelog entry for new e2e test for helloworld module 2017-08-20 22:49:23 -03:00
Rodrigo Ramírez Norambuena
a6ee20fca4 Merge remote-tracking branch 'roramirez_github/develop' into default-hello-world 2017-08-20 22:49:13 -03:00
DanielWeeber
2d2f159e04 Small change for re-running Travis CI 2017-08-16 12:11:57 +02:00
DanielWeeber
5568e0c2ad Change Two Conditionals to UpperCase-If 2017-08-16 10:00:38 +02:00
DanielWeeber
cb2cc0cb9e Fix linting? 2017-08-15 20:57:18 +02:00
DanielWeeber
5e573ca980 Show Scale of Temperature if config flag is set 2017-08-15 19:54:35 +02:00
Michael Teeuw
dcb4a315a6 Merge pull request #990 from roramirez/deprecation-warning
Added deprecation warning for authentication of the calendar module.
2017-08-13 19:21:17 +02:00
Rodrigo Ramírez Norambuena
4bd36fc29e Merge branch 'develop' into deprecation-warning 2017-08-13 04:28:06 -03:00
Michael Teeuw
1a7971ec82 Merge pull request #987 from roramirez/update-stylelint
Update stylelint package
2017-08-12 16:52:13 +02:00
Michael Teeuw
c1eda034b3 Merge pull request #989 from roramirez/add-log-deprecated-function
Add log deprecated function in test
2017-08-12 13:50:52 +02:00
Michael Teeuw
2294d722c7 Merge pull request #986 from roramirez/roboto-fonts-as-vendor
Change to install Roboto fonts by npm
2017-08-12 13:50:23 +02:00
Michael Teeuw
7d053be6d1 Merge pull request #975 from QNimbus/unittests/calendar
Add unittest for calendar module
2017-08-12 13:50:07 +02:00
Michael Teeuw
7a508661eb Merge branch 'develop' into update-stylelint 2017-08-10 16:29:30 +02:00
Michael Teeuw
c976242ce5 Merge branch 'develop' into unittests/calendar 2017-08-10 16:27:00 +02:00
Michael Teeuw
2b77c372a3 Merge pull request #979 from CatoAntonsen/fix_filepath
Fix this.file path
2017-08-10 16:26:03 +02:00
Michael Teeuw
b61cc67997 Merge pull request #983 from roramirez/test-unit-js-class
Test unit js class
2017-08-10 12:15:31 +02:00
Michael Teeuw
de8db1a86d Merge branch 'develop' into test-unit-js-class 2017-08-10 12:15:23 +02:00
Michael Teeuw
abfdf0e1c2 Merge pull request #982 from roramirez/doc-roundValue
Fix Documentation in  roundValue function
2017-08-10 12:14:58 +02:00
Michael Teeuw
1d662e354b Merge branch 'develop' into doc-roundValue 2017-08-10 12:14:16 +02:00
Michael Teeuw
663e9a9b5e Merge pull request #973 from roramirez/add-code-error-cliente-failstart
Add log when clientonly failed on starting.
2017-08-10 12:12:24 +02:00
Michael Teeuw
8535409962 Merge branch 'develop' into add-code-error-cliente-failstart 2017-08-10 12:12:17 +02:00
Michael Teeuw
cd5623b348 Merge pull request #972 from roramirez/add-warning-color-full-ip
Add warning color when are using full ip whitelist
2017-08-10 12:11:51 +02:00
Michael Teeuw
673e051bd5 Merge pull request #969 from roramirez/showWeek-test-es-language
Show week test es language
2017-08-10 12:11:25 +02:00
Michael Teeuw
66c949057e Merge pull request #968 from roramirez/set-version-test-dependencies
Set version spectron for 3.6.x
2017-08-10 12:11:12 +02:00
Rodrigo Ramírez Norambuena
aed09f0c64 Change to install Roboto fonts by npm 2017-08-07 20:45:42 -04:00
Rodrigo Ramírez Norambuena
c05f306b0d Update stylelint package 2017-08-06 07:59:31 -04:00
Rodrigo Ramírez Norambuena
739fb99ced Resolved conflict unit tests between currentweather and newsfeed. 2017-08-06 07:53:03 -04:00
Rodrigo Ramírez Norambuena
7fc82ccead Update Changelog for unit tests for currentweather module 2017-08-07 20:42:32 -04:00
Rodrigo Ramírez Norambuena
8ae947f59c Merge remote-tracking branch 'origin/round-temp-unit' into doc-roundValue 2017-08-07 20:40:27 -04:00
Rodrigo Ramírez Norambuena
d34b493b7d Fix clock_es_spec running before the clock_spec 2017-08-05 22:30:38 -04:00
Rodrigo Ramírez Norambuena
4df6e0ee7d Merge remote-tracking branch 'upstream/develop' into showWeek-test-es-language 2017-08-05 21:12:39 -04:00
Rodrigo Ramírez Norambuena
aac4ef05e4 Merge remote-tracking branch 'upstream/develop' into test-unit-js-class 2017-08-05 19:50:34 -04:00
Rodrigo Ramírez Norambuena
ea2f53e166 Merge remote-tracking branch 'upstream/develop' into doc-roundValue 2017-08-05 18:20:22 -04:00
Rodrigo Ramírez Norambuena
f144ec67ab Add changelog entry for log in failed of clientonly 2017-08-05 17:48:20 -04:00
Rodrigo Ramírez Norambuena
7e42dcf0b5 Merge branch 'develop' into add-code-error-cliente-failstart 2017-08-05 17:47:36 -04:00
Rodrigo Ramírez Norambuena
87c4dc313a Merge branch 'develop' into set-version-test-dependencies 2017-08-05 17:44:51 -04:00
Rodrigo Ramírez Norambuena
0d29339898 Merge branch 'develop' into add-warning-color-full-ip 2017-08-05 17:44:05 -04:00
Michael Teeuw
6d83f18490 Merge pull request #981 from roramirez/disable-vendor_spec
Disabled tests of vendor_spec:
2017-08-05 21:30:44 +02:00
Rodrigo Ramírez Norambuena
0ba125c2d7 Disabled tests of vendor_spec:
Sometimes these getting failed in Travis.
2017-08-05 02:40:03 -04:00
Rodrigo Ramírez Norambuena
6abd120a5c Add CHANGELOG entry for color in warning if full ip whitelist 2017-08-04 22:39:52 -04:00
Rodrigo Ramírez Norambuena
5cf7e89ce6 Merge remote-tracking branch 'roramirez_github/develop' into add-warning-color-full-ip 2017-08-04 22:38:31 -04:00
Cato Antonsen
353786cb61 Fix this.file path 2017-08-03 21:34:23 +02:00
Michael Teeuw
586beea21e Merge pull request #977 from roramirez/use-before-after-vendors
Use before after vendors
2017-08-02 12:07:40 +02:00
Rodrigo Ramírez Norambuena
b80454a1f4 Added log text DEPRECATED for old method of authentication 2017-07-31 17:18:34 -04:00
Rodrigo Ramírez Norambuena
19f80cf506 Add entry in Changelog for change hooks in vendors_spec 2017-07-31 16:58:33 -04:00
Rodrigo Ramírez Norambuena
d01100bb15 Merge remote-tracking branch 'roramirez_github/develop' into use-before-after-vendors 2017-07-31 16:57:24 -04:00
Bas van Wetten
e0414e4eb9 Add unittest for calendar module
Add unittest for 'getLocalSpecification' function.
2017-07-31 22:36:14 +02:00
Michael Teeuw
1eb10e3c22 Merge pull request #971 from roramirez/set-title-magicmirror-2
Set title on MagicMirror² for index.html
2017-07-31 15:04:54 +02:00
Michael Teeuw
4772fbcd4a Merge pull request #970 from QNimbus/unittest-calendar
Add new unit tests
2017-07-31 15:04:25 +02:00
Michael Teeuw
18b61e35be Merge branch 'develop' into unittest-calendar 2017-07-31 15:04:16 +02:00
Michael Teeuw
bb7faf0fb3 Merge pull request #967 from roramirez/show-test-build-npm-dependencies
Debug npm list in CI
2017-07-31 15:03:25 +02:00
Michael Teeuw
1603742adc Merge branch 'develop' into show-test-build-npm-dependencies 2017-07-31 15:03:20 +02:00
Michael Teeuw
8a830e40bb Merge pull request #966 from roramirez/format-changelog
Fix litles changes of format in the Changelog
2017-07-31 15:02:43 +02:00
Michael Teeuw
d8adcf5a84 Merge branch 'develop' into format-changelog 2017-07-31 15:02:36 +02:00
Michael Teeuw
1d9a404f77 Merge pull request #965 from roramirez/newfeed-unit
Newfeed unit
2017-07-31 15:00:37 +02:00
Michael Teeuw
26dcaf6078 Merge pull request #962 from QNimbus/fix-issue-961
Fix calendar.js bug
2017-07-31 15:00:15 +02:00
Michael Teeuw
a91e4014bf Merge pull request #959 from roramirez/include-node-8
Include node 8 testsuite and CI
2017-07-31 14:59:34 +02:00
Rodrigo Ramírez Norambuena
06af327e5e Added deprecation warning for authentication of the calendar module.
Discussed in Review
9848f80630 (r105531731)
2017-07-30 22:56:27 -04:00
Bas van Wetten
35e3b889c3 Add new unit tests
Add new unit tests for 'shorten' function in calendar module
2017-07-29 16:02:53 +02:00
Bas van Wetten
5ef6ba0258 Small edit of CHANGELOG
Added a period at the end of the CHANGELOG entries
2017-07-29 11:44:43 +02:00
Bas van Wetten
12754ff135 Updated changelog for calendar fix
Updated changelog for calendar fix
2017-07-28 22:19:25 +02:00
Bas van Wetten
d09a1e254f Merge branch 'fix-issue-963' into fix-issue-961 2017-07-28 21:34:58 +02:00
Bas van Wetten
b89ee67daf Merge branch 'fix-issue-961' into fix-issue-963 2017-07-28 21:33:10 +02:00
Bas van Wetten
7bd256c311 Fix calendar.js bug issue #963
Fixed calendar specific configuration settings maximumEntries and maximumNumberOfDays not overriding global setting
2017-07-28 21:07:38 +02:00
Bas van Wetten
4add7cd0b3 Fix calendar.js bug
Fix bug where excludedEvents count towards maximumEntries displayed
2017-07-28 17:47:22 +02:00
Rodrigo Ramírez Norambuena
5ac20cc4cf SuiteTest: Added unit tests for js/class.js 2017-07-25 21:42:51 -04:00
Rodrigo Ramírez Norambuena
9d7b0487d5 Change hooks for vendor_spec:
Use the hooks before and after in the vendor_spec instead of use beforeAll and
afterAll in the e2e test to prevent failure in CI.
2017-07-25 20:24:04 -04:00
Rodrigo Ramírez Norambuena
59aa84f6c8 Add log when clientonly failed on starting. 2017-07-25 17:52:44 -04:00
Rodrigo Ramírez Norambuena
765b03c868 Add warning color when are using full ip whitelist 2017-07-25 11:26:01 -04:00
Rodrigo Ramírez Norambuena
41ce3db8f9 Set title on MagicMirror² for index.html 2017-07-25 11:00:38 -04:00
Rodrigo Ramírez Norambuena
00e3ef757c Merge remote-tracking branch 'roramirez_github/develop' into showWeek-test-es-language 2017-07-25 10:53:50 -04:00
Rodrigo Ramírez Norambuena
84dc0b2959 Set version spectron for 3.6.x 2017-07-25 10:28:45 -04:00
Rodrigo Ramírez Norambuena
2e48099070 Debug npm list in CI
Execute npm list after the tests in Travis
2017-07-25 10:07:32 -04:00
Rodrigo Ramírez Norambuena
77779bbcd9 Fix litles changes of format in the Changelog 2017-07-25 09:50:51 -04:00
Rodrigo Ramírez Norambuena
e08bc01c33 Fix conflict with test function newsfeed 2017-07-25 09:32:32 -04:00
Michael Teeuw
bf24ee369f Merge pull request #957 from QNimbus/develop
Addition to .gitignore to ignore VS Code folder
2017-07-25 14:50:00 +02:00
Michael Teeuw
876f12db89 Merge pull request #955 from roramirez/close-code-tag-README-modules
Close code tag and fix format for Modules Readme
2017-07-25 14:49:42 +02:00
Michael Teeuw
8b84459e13 Merge pull request #953 from roramirez/activate-test-e2e
Activate e2e test in Travis and desactivate failed test in CI:
2017-07-25 14:49:25 +02:00
Rodrigo Ramírez Norambuena
dccfcc9663 Merge pull request #2 from QNimbus/activate-test-e2e
Change suggestion for e2e testing
2017-07-24 22:38:32 -04:00
Bas van Wetten
203e1cc9b9 Implemented requested change PR #2
Moved tests/e2e_new to tests/e2e folder
2017-07-24 22:08:12 +02:00
Bas van Wetten
b612f0cdec PR for issue #956
Changed .gitignore to ignore Visual Studio Code project folder with custom launch configuration. (See issue #956)
2017-07-24 21:56:53 +02:00
Rodrigo Ramírez Norambuena
961301fbec Merge remote-tracking branch 'roramirez_github/develop' into newfeed-unit 2017-07-24 11:36:16 -04:00
Rodrigo Ramírez Norambuena
2a38d99cf1 Merge remote-tracking branch 'roramirez_github/develop' into include-node-8 2017-07-24 11:34:47 -04:00
Rodrigo Ramírez Norambuena
7903328c2d Add Node 8 for testing 2017-07-23 20:49:52 -04:00
Rodrigo Ramírez Norambuena
56d2b4a80c Close code tag and fix format for Modules Readme 2017-07-23 20:31:26 -04:00
Ricardo Gonzalez
2c6ecaab5b Add ability for currentweather module to display indoor humidity via INDOOR_HUMIDITY notification 2017-07-23 23:55:32 +01:00
Ricardo Gonzalez
45d289a65e Merge branch 'develop' of github.com:ryck/MagicMirror into develop
* 'develop' of github.com:ryck/MagicMirror:
  Add template for v2.1.3
  Set dev version.
2017-07-23 23:52:10 +01:00
Bas van Wetten
318c8c68b0 Change suggestion for e2e testing
- Changed global-setup.js to allow for easier test creation
- Changed each e2e test suite to work with new global-setup.js
- All tests (except for dev_console.js) now work with Travis CI
2017-07-23 23:06:27 +02:00
Michael Teeuw
fbd47a7f3b Merge pull request #951 from QNimbus/fix-issue-950
Fix for issue #950
2017-07-20 10:12:45 +02:00
Rodrigo Ramírez Norambuena
07533f5658 Activate e2e test in Travis and desactivate failed test in CI:
- dev_console
 - vendor_spec
2017-07-20 00:34:20 -04:00
Rodrigo Ramírez Norambuena
66b7e3e1f5 Fix lint newsfeed_spec 2017-07-20 00:27:57 -04:00
Rodrigo Ramírez Norambuena
4fee4d1903 Add Changelog Unit test for capitalizeFirstLetter newfeed module 2017-07-20 00:10:01 -04:00
Rodrigo Ramírez Norambuena
90d70beea2 Merge remote-tracking branch 'roramirez_github/develop' into newfeed-unit 2017-07-20 00:09:05 -04:00
Unknown
a7297d2685 Fix for issue #950
Changed 'server.js' to allow an empty ipwhitelist to allow any and all hosts instead of none as mentioned in the documentation
2017-07-18 14:07:18 +02:00
Michael Teeuw
86ae704e86 Merge pull request #924 from QNimbus/client-only-pr
Added clientonly script
2017-07-12 11:08:04 +02:00
Michael Teeuw
2d1e993fe1 Merge branch 'develop' into client-only-pr 2017-07-12 11:07:49 +02:00
Michael Teeuw
04b550e435 Update correct version. 2017-07-12 10:58:28 +02:00
Michael Teeuw
c492ea77f1 Merge pull request #943 from QNimbus/fix-issue-940
Fix issue #940
2017-07-12 10:55:43 +02:00
Michael Teeuw
61d9112ba7 Merge pull request #941 from QNimbus/fix-issue-933
Fix issue #933
2017-07-12 10:55:23 +02:00
Michael Teeuw
d7fe36de71 Merge pull request #934 from eouia/develop
add symbol and color on broadcasted events
2017-07-12 10:54:59 +02:00
Unknown
db0bd3fa2d Fix issue #940
Fix for issue 940 - time was incorrectly displayed in a 12-hour fashion regardless of the 24 hour clock preference in config.js
2017-07-09 11:46:59 +02:00
Unknown
551619e772 Fix issue #933
This is a fix for issue 933 which restores the original alligment of the analog clock; the analog clock still does not properly align to the left of the left sidebar when content of other left sidebar modules is too wide.
2017-07-08 21:31:05 +02:00
eouia
29bae230a4 Update CHANGELOG.md 2017-07-06 16:09:49 +02:00
eouia
83be49156f symbol and color for broadcasted events (calendar)
- Add symbol and color properties of event when `CALENDAR_EVENTS` notification is broadcasted from `defaultcalendar` module.
2017-07-06 16:09:16 +02:00
eouia
561ae102fb add symbol and color on broadcasted events 2017-07-06 11:57:16 +02:00
Unknown
a05e69b855 Removed cookie dependencies
Removed module import and dependency on the 'cookie' library; it's not used anymore
2017-07-02 12:10:16 +02:00
Unknown
8eb772d80b Allow use of env variables
Made some changes that allows the use of environment variables when starting the standalone client.
2017-07-02 12:10:16 +02:00
Unknown
1590693547 New server route to fetch config
Added a new route to the Express server to supply client with config. Removed the original 'cookie' hack
2017-07-02 12:10:16 +02:00
Unknown
66f93ee541 Added clientonly script
Added clientonly script to have server and client run at different locations
2017-07-02 12:10:16 +02:00
Michael Teeuw
8893df118e Add template for v2.1.3 2017-07-01 20:36:17 +02:00
Michael Teeuw
2c77cb5ca5 Set dev version. 2017-07-01 20:35:11 +02:00
Rodrigo Ramírez Norambuena
947c2e556d Add test e2e showWeek feature in spanish language. 2017-04-09 15:32:15 -03:00
Rodrigo Ramírez Norambuena
f974fd0660 Add roundValue unit test function weatherforecast module:
- tests for this.config.roundTemp is false
    - tests for this.config.roundTemp is true
2017-03-29 00:29:47 -03:00
Rodrigo Ramírez Norambuena
af9fdfa224 Add roundValue unit test function currentweather module:
- tests for this.config.roundTemp is false
2017-03-28 22:15:48 -03:00
Rodrigo Ramírez Norambuena
181cb235df Unit test currentweather module:
Add roundValue unit test function currentweather module
	tests for this.config.roundTemp is true
2017-03-28 10:05:08 -03:00
Rodrigo Ramírez Norambuena
60c5d96037 fix documentation currentweather and weatherforecast function
roundValue:

This function toFixed return a string type not a number value.
2017-03-27 12:18:36 -03:00
Rodrigo Ramírez Norambuena
daad8bca69 Add test e2e helloworld module with default config text. 2017-03-26 17:36:45 -03:00
Rodrigo Ramírez Norambuena
0117cd478b Unit test for capitalizeFirstLetter newfeed module 2017-03-26 16:19:45 -03:00
169 changed files with 16217 additions and 1215 deletions

View File

@@ -5,12 +5,18 @@
"max-len": ["error", 250],
"curly": "error",
"camelcase": ["error", {"properties": "never"}],
"no-trailing-spaces": ["error"],
"no-trailing-spaces": ["error", {"ignoreComments": false }],
"no-irregular-whitespace": ["error"]
},
"env": {
"browser": true,
"node": true,
"es6": true
}
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"globalReturn": true
}
}
}

3
.gitignore vendored
View File

@@ -16,6 +16,9 @@ jspm_modules
.npm
.node_repl_history
# Visual Studio Code ignoramuses.
.vscode/
# Various Windows ignoramuses.
Thumbs.db
ehthumbs.db

View File

@@ -1,9 +1,8 @@
language: node_js
node_js:
- "7"
- "6"
- "5.1"
before_script:
- yarn danger ci
- npm install grunt-cli -g
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
@@ -11,6 +10,9 @@ before_script:
script:
- grunt
- npm run test:unit
- npm run test:e2e
after_script:
- npm list
cache:
directories:
- node_modules

View File

@@ -2,6 +2,116 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [2.3.0] - 2018-04-01
### Added
- Add new settings in compliments module: setting time intervals for morning and afternoon
- Add system notification `MODULE_DOM_CREATED` for notifying each module when their Dom has been fully loaded.
- Add types for module.
- Implement Danger.js to notify contributors when CHANGELOG.md is missing in PR.
- Allow to scroll in full page article view of default newsfeed module with gesture events from [MMM-Gestures](https://github.com/thobach/MMM-Gestures)
- Changed 'compliments.js' - update DOM if remote compliments are loaded instead of waiting one updateInterval to show custom compliments
- Automated unit tests utils, deprecated, translator, cloneObject(lockstrings)
- Automated integration tests translations
- Add advanced filtering to the excludedEvents configuration of the default calendar module
- New currentweather module config option: `showFeelsLike`: Shows how it actually feels like. (wind chill or heat index)
- New currentweather module config option: `useKMPHwind`: adds an option to see wind speed in Kmph instead of just m/s or Beaufort.
- Add dc:date to parsing in newsfeed module, which allows parsing of more rss feeds.
### Changed
- Add link to GitHub repository which contains the respective Dockerfile.
- Optimized automated unit tests cloneObject, cmpVersions
- Update notifications use now translation templates instead of normal strings.
- Yarn can be used now as an installation tool
- Changed Electron dependency to v1.7.13.
### Fixed
- News article in fullscreen (iframe) is now shown in front of modules.
- Forecast respects maxNumberOfDays regardless of endpoint.
- Fix exception on translation of objects.
## [2.2.2] - 2018-01-02
### Added
- Add missing `package-lock.json`.
### Changed
- Changed Electron dependency to v1.7.10.
## [2.2.1] - 2018-01-01
### Fixed
- Fixed linting errors.
## [2.2.0] - 2018-01-01
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
### Changed
- Calender week is now handled with a variable translation in order to move number language specific.
- Reverted the Electron dependency back to 1.4.15 since newer version don't seem to work on the Raspberry Pi very well.
### Added
- Add option to use [Nunjucks](https://mozilla.github.io/nunjucks/) templates in modules. (See `helloworld` module as an example.)
- Add Bulgarian translations for MagicMirror² and Alert module.
- Add graceful shutdown of modules by calling `stop` function of each `node_helper` on SIGINT before exiting.
- Link update subtext to Github diff of current version versus tracking branch.
- Add Catalan translation.
- Add ability to filter out newsfeed items based on prohibited words found in title (resolves #1071)
- Add options to truncate description support of a feed in newsfeed module
- Add reloadInterval option for particular feed in newsfeed module
- Add no-cache entries of HTTP headers in newsfeed module (fetcher)
- Add Czech translation.
- Add option for decimal symbols other than the decimal point for temperature values in both default weather modules: WeatherForecast and CurrentWeather.
### Fixed
- Fixed issue with calendar module showing more than `maximumEntries` allows
- WeatherForecast and CurrentWeather are now using HTTPS instead of HTTP
- Correcting translation for Indonesian language
- Fix issue where calendar icons wouldn't align correctly
## [2.1.3] - 2017-10-01
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
### Changed
- Remove Roboto fonts files inside `fonts` and these are installed by npm install command.
### Added
- Add `clientonly` script to start only the electron client for a remote server.
- Add symbol and color properties of event when `CALENDAR_EVENTS` notification is broadcasted from `default/calendar` module.
- Add `.vscode/` folder to `.gitignore` to keep custom Visual Studio Code config out of git.
- Add unit test the capitalizeFirstLetter function of newfeed module.
- Add new unit tests for function `shorten` in calendar module.
- Add new unit tests for function `getLocaleSpecification` in calendar module.
- Add unit test for js/class.js.
- Add unit tests for function `roundValue` in currentweather module.
- Add test e2e showWeek feature in spanish language.
- Add warning Log when is used old authentication method in the calendar module.
- Add test e2e for helloworld module with default config text.
- Add ability for `currentweather` module to display indoor humidity via INDOOR_HUMIDITY notification.
- Add Welsh (Cymraeg) translation.
- Add Slack badge to Readme.
### Updated
- Changed 'default.js' - listen on all attached interfaces by default.
- Add execution of `npm list` after the test are ran in Travis CI.
- Change hooks for the vendors e2e tests.
- Add log when clientonly failed on starting.
- Add warning color when are using full ip whitelist.
- Set version of the `express-ipfilter` on 0.3.1.
### Fixed
- Fixed issue with incorrect allignment of analog clock when displayed in the center column of the MM.
- Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM.
- Fixed issue with calendar module where 'excludedEvents' count towards 'maximumEntries'.
- Fixed issue with calendar module where global configuration of maximumEntries was not overridden by calendar specific config (see module doc).
- Fixed issue where `this.file(filename)` returns a path with two hashes.
- Workaround for the WeatherForecast API limitation.
## [2.1.2] - 2017-07-01
### Changed
@@ -30,7 +140,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Updated
- Added missing keys to Polish translation.
- Added missing key to German translation.
- Added better translation with flexible word order to Finnish translation
- Added better translation with flexible word order to Finnish translation.
### Fixed
- Fix instruction in README for using automatically installer script.
@@ -38,8 +148,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix double message about port when server is starting
- Corrected Swedish translations for TODAY/TOMORROW/DAYAFTERTOMORROW.
- Removed unused import from js/electron.js
- Made calendar.js respect config.timeFormat irrespecive of locale setting
- Fixed alignment of analog clock when a large calendar is displayed in the same side bar
- Made calendar.js respect config.timeFormat irrespecive of locale setting.
- Fixed alignment of analog clock when a large calendar is displayed in the same side bar.
## [2.1.1] - 2017-04-01
@@ -47,18 +157,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Changed
- Add `anytime` group for Compliments module.
- Compliments module can use remoteFile without default daytime arrays defined
- Compliments module can use remoteFile without default daytime arrays defined.
- Installer: Use init config.js from config.js.sample.
- Switched out `rrule` package for `rrule-alt` and fixes in `ical.js` in order to fix calendar issues. ([#565](https://github.com/MichMich/MagicMirror/issues/565))
- Make mouse events pass through the region fullscreen_above to modules below.
- Scaled the splash screen down to make it a bit more subtle.
- Replace HTML tables with markdown tables in README files.
- Added `DAYAFTERTOMORROW`, `UPDATE_NOTIFICATION` and `UPDATE_NOTIFICATION_MODULE` to Finnish translations.
- Run `npm test` on Travis automatically
- Run `npm test` on Travis automatically.
- Show the splash screen image even when is reboot or halted.
- Added some missing translaton strings in the sv.json file.
- Run task jsonlint to check translation files.
- Restructured Test Suite
- Restructured Test Suite.
### Added
- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)).

179
README.md
View File

@@ -7,6 +7,7 @@
<a href="http://choosealicense.com/licenses/mit"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
<a href="https://travis-ci.org/MichMich/MagicMirror"><img src="https://travis-ci.org/MichMich/MagicMirror.svg" alt="Travis"></a>
<a href="https://snyk.io/test/github/MichMich/MagicMirror"><img src="https://snyk.io/test/github/MichMich/MagicMirror/badge.svg" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/github/MichMich/MagicMirror" style="max-width:100%;"></a>
<a href="http://slack.magicmirror.builders"><img src="http://slack.magicmirror.builders:3000/badge.svg" alt="Slack Status"></a>
</p>
**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](http://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MichMich/MagicMirror/graphs/contributors).
@@ -15,109 +16,123 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](http://elec
## Table Of Contents
- [Usage](#usage)
- [Installation](#installation)
- [Raspberry Pi](#raspberrypi)
- [General](#general)
- [Server Only](#server-only)
- [Client Only](#client-only)
- [Docker](#docker)
- [Configuration](#configuration)
- [Modules](#modules)
- [Updating](#updating)
- [Known Issues](#known-issues)
- [Community](#community)
- [Contributing Guidelines](#contributing-guidelines)
- [Manifesto](#manifesto)
## Usage
## Installation
### 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.
### Raspberry Pi
### Automatic Installer (Raspberry Pi Only!)
#### Automatic Installation (Raspberry Pi only!)
*Electron*, the app wrapper around MagicMirror², only supports the Raspberry Pi 2/3. The Raspberry Pi 0/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. (Yes, people have managed to run MM² also on a Pi0, so if you insist, search in the forums.)
Note that you will need to install the lastest full version of Raspbian, **don't use the Lite version**.
Execute the following command on your Raspberry Pi to install MagicMirror²:
````
```bash
bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/raspberry.sh)"
````
```
### Manual Installation
#### Manual Installation
1. Download and install the latest Node.js version.
1. Download and install the latest *Node.js* version.
2. Clone the repository and check out the master branch: `git clone https://github.com/MichMich/MagicMirror`
3. Enter the repository: `cd ~/MagicMirror`
4. Install and run the app: `npm install && npm start`
3. Enter the repository: `cd MagicMirror/`
4. Install and run the app with: `npm install && npm start` \
For **Server Only** use: `npm install && node serveronly` .
**Important:** `npm start` does **not** work via SSH, use `DISPLAY=:0 nohup npm start &` instead. This starts the mirror on the remote display.
**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.
**:warning: Important!**
- **The installation step for `npm install` will take a very long time**, often with little or no terminal response! \
For the RPi3 this is **~10** minutes and for the Rpi2 **~25** minutes. \
Do not interrupt or you risk getting a :broken_heart: by Raspberry Jam.
Also note that:
- `npm start` does **not** work via SSH. But you can use `DISPLAY=:0 nohup npm start &` instead. \
This starts the mirror on the remote display.
- If you want to debug on Raspberry Pi you can use `npm start dev` which will start MM with *Dev Tools* enabled.
- To access toolbar menu when in mirror mode, hit `ALT` key.
- To toggle the (web) `Developer Tools` from mirror mode, use `CTRL-SHIFT-I` or `ALT` and select `View`.
### Server Only
In some cases, you want to start the application without an actual app window. In this case, you can start MagicMirror² in server only mode by manually running `node serveronly` or using Docker. This will start the server, after which you can open the application in your browser of choice. Detailed description below.
#### Docker
**Important:** Make sure that you whitelist the interface/ip (`ipWhitelist`) in the server config where you want the client to connect to, otherwise it will not be allowed to connect to the server. You also need to set the local host `address` field to `0.0.0.0` in order for the RPi to listen on all interfaces and not only `localhost` (default).
```javascript
var config = {
address: "0.0.0.0", // default is "localhost"
port: 8080, // default
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:172.17.0.1"], // default -- need to add your IP here
...
};
```
### Client Only
This is when you already have a server running remotely and want your RPi to connect as a standalone client to this instance, to show the MM from the server. Then from your RPi, you run it with: `node clientonly --address 192.168.1.5 --port 8080`. (Specify the ip address and port number of the server)
### Docker
MagicMirror² in server only mode can be deployed using [Docker](https://docker.com). After a successful [Docker installation](https://docs.docker.com/engine/installation/) you just need to execute the following command in the shell:
```bash
docker run -d \
--publish 80:8080 \
--restart always \
--volume ~/magic_mirror/config:/opt/magic_mirror/config \
--volume ~/magic_mirror/modules:/opt/magic_mirror/modules \
--name magic_mirror \
bastilimbach/docker-magicmirror
--publish 80:8080 \
--restart always \
--volume ~/magic_mirror/config:/opt/magic_mirror/config \
--volume ~/magic_mirror/modules:/opt/magic_mirror/modules \
--name magic_mirror \
bastilimbach/docker-magicmirror
```
To get more information about the available Dockerfile versions and configurations head over to the respective [GitHub repository](https://github.com/bastilimbach/docker-MagicMirror).
| **Volumes** | **Description** |
| --- | --- |
| `/opt/magic_mirror/config` | Mount this volume to insert your own config into the docker container. |
| `/opt/magic_mirror/modules` | Mount this volume to add your own custom modules into the docker container. |
You may need to add your Docker Host IP to your `ipWhitelist` option. If you have some issues setting up this configuration, check [this forum post](https://forum.magicmirror.builders/topic/1326/ipwhitelist-howto).
```javascript
var config = {
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:172.17.0.1"]
};
```
If you want to run the server on a raspberry pi, use the `raspberry` tag. (bastilimbach/docker-magicmirror:raspberry)
#### Manual
1. Download and install the latest Node.js version.
2. Clone the repository and check out the master branch: `git clone https://github.com/MichMich/MagicMirror`
3. Enter the repository: `cd ~/MagicMirror`
4. Install and run the app: `npm install && node serveronly`
### 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 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 && npm install
```
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.
## Configuration
1. Duplicate `config/config.js.sample` to `config/config.js`. **Note:** If you used the installer script. This step is already done for you.
2. Modify your required settings.
### Raspberry Specific
The following wiki links are helpful for the initial 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)
### General
1. Copy `config/config.js.sample` to `config/config.js`. \
**Note:** If you used the installer script. This step is already done for you.
2. Modify your required settings. \
Note: You'll can check your configuration running `npm run config:check`.
Note: You'll can check your configuration running the follow command:
```bash
npm run config:check
```
The following properties can be configured:
| **Option** | **Description** |
| --- | --- |
| `port` | The port on which the MagicMirror² server will run on. The default value is `8080`. |
| `address` | The ip address the accept connections. The default open bind `::` is IPv6 is available or `0.0.0.0` IPv4 run on. Example config: `192.168.10.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"]]`). Set `[]` to allow all IP addresses. For more information about how configure this directive see the [follow post ipWhitelist HowTo](https://forum.magicmirror.builders/topic/1326/ipwhitelist-howto) |
| `address` | The *interface* ip address on which to accept connections. The default is `localhost`, which would prevent exposing the built-in webserver to machines on the local network. To expose it to other machines, use: `0.0.0.0`. |
| `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"]`, which is from `localhost` only. Add your IP when needed. You can also specify IP ranges with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or directly with (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`). Set `[]` to allow all IP addresses. For more information see: [follow post ipWhitelist HowTo](https://forum.magicmirror.builders/topic/1326/ipwhitelist-howto) |
| `zoom` | This allows to scale the mirror contents with a given zoom factor. The default value is `1.0`|
| `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`. |
@@ -150,12 +165,20 @@ The following modules are installed by default.
- [**Hello World**](modules/default/helloworld)
- [**Alert**](modules/default/alert)
For more available modules, check out out the wiki page: [MagicMirror² Modules](https://github.com/MichMich/MagicMirror/wiki/MagicMirror²-Modules). If you want to build your own modules, check out the [MagicMirror² Module Development Documentation](modules) and don't forget to add it to the wiki and the [forum](https://forum.magicmirror.builders/category/7/showcase)!
For more available modules, check out out the wiki page [MagicMirror² 3rd Party Modules](https://github.com/MichMich/MagicMirror/wiki/3rd-party-modules). If you want to build your own modules, check out the [MagicMirror² Module Development Documentation](modules) and don't forget to add it to the wiki and the [forum](https://forum.magicmirror.builders/category/7/showcase)!
## Known issues
- Electron seems to have some issues on certain Raspberry Pi 2's. See [#145](https://github.com/MichMich/MagicMirror/issues/145).
- MagicMirror² (Electron) sometimes quits without an error after an extended period of use. See [#150](https://github.com/MichMich/MagicMirror/issues/150).
## Updating
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 && npm install
```
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.
## Community
@@ -174,6 +197,22 @@ Please keep the following in mind:
Thanks for your help in making MagicMirror² better!
## Manifesto
A real Manifesto is still to be written. Till then, Michael's response on [one of the repository issues](https://github.com/MichMich/MagicMirror/issues/1174) gives a great summary:
> "... I started this project as an ultimate starter project for Raspberry Pi enthusiasts. As a matter of fact, for most of the contributors, the MagicMirror project is the first open source project they ever contributed to. This is one of the reasons why the MagicMirror project is featured in several RasPi magazines.
>
>The project has a lot of opportunities for improvement. We could use a powerful framework like Vue to ramp up the development speed. We could use SASS for better/easier css implementations. We could make it an NPM installable package. And as you say, we could bundle it up. The big downside of of of these changes is that it over complicates things: a user no longer will be able to open just one file and make a small modification and see how it works out.
>
>Of course, a bundled version can be complimentary to the regular un-bundled version. And I'm sure a lot of (new) users will opt for the bundled version. But this means those users won't be motivated to take a peek under the hood. They will just remain 'users'. They won't become contributors, and worse: they won't be motivated to take their first steps in software development.
>
>And to be honest: motivating curious users to step out of their comfort zone and take those first steps is what drives me in this project. Therefor my ultimate goal is this project is to keep it as accessible as possible."
>
> ~ Michael Teeuw
<p align="center">
<br>
<a href="https://forum.magicmirror.builders/topic/728/magicmirror-is-voted-number-1-in-the-magpi-top-50"><img src="https://magicmirror.builders/img/magpi-best-watermark-custom.png" width="150" alt="MagPi Top 50"></a>

104
clientonly/index.js Normal file
View File

@@ -0,0 +1,104 @@
/* jshint esversion: 6 */
"use strict";
// Use seperate scope to prevent global scope pollution
(function () {
var config = {};
// Helper function to get server address/hostname from either the commandline or env
function getServerAddress() {
// Helper function to get command line parameters
// Assumes that a cmdline parameter is defined with `--key [value]`
function getCommandLineParameter(key, defaultValue = undefined) {
var index = process.argv.indexOf(`--${key}`);
var value = index > -1 ? process.argv[index + 1] : undefined;
return value !== undefined ? String(value) : defaultValue;
}
// Prefer command line arguments over environment variables
["address", "port"].forEach((key) => {
config[key] = getCommandLineParameter(key, process.env[key.toUpperCase()]);
})
}
function getServerConfig(url) {
// Return new pending promise
return new Promise((resolve, reject) => {
// Select http or https module, depending on reqested url
const lib = url.startsWith("https") ? require("https") : require("http");
const request = lib.get(url, (response) => {
var configData = "";
// Gather incomming data
response.on("data", function(chunk) {
configData += chunk;
});
// Resolve promise at the end of the HTTP/HTTPS stream
response.on("end", function() {
resolve(JSON.parse(configData));
});
});
request.on("error", function(error) {
reject(new Error(`Unable to read config from server (${url} (${error.message}`));
});
})
};
function fail(message, code = 1) {
if (message !== undefined && typeof message === "string") {
console.log(message);
} else {
console.log("Usage: 'node clientonly --address 192.168.1.10 --port 8080'");
}
process.exit(code);
}
getServerAddress();
(config.address && config.port) || fail();
// Only start the client if a non-local server was provided
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) === -1) {
getServerConfig(`http://${config.address}:${config.port}/config/`)
.then(function (config) {
// Pass along the server config via an environment variable
var env = Object.create(process.env);
var options = { env: env };
config.address = config.address;
config.port = config.port;
env.config = JSON.stringify(config);
// Spawn electron application
const electron = require("electron");
const child = require("child_process").spawn(electron, ["js/electron.js"], options);
// Pipe all child process output to current stdout
child.stdout.on("data", function (buf) {
process.stdout.write(`Client: ${buf}`);
});
// Pipe all child process errors to current stderr
child.stderr.on("data", function (buf) {
process.stderr.write(`Client: ${buf}`);
});
child.on("error", function (err) {
process.stdout.write(`Client: ${err}`);
});
child.on('close', (code) => {
if (code != 0) {
console.log(`There something wrong. The clientonly is not running code ${code}`);
}
});
})
.catch(function (reason) {
fail(`Unable to connect to server: (${reason})`);
});
} else {
fail();
}
}());

View File

@@ -9,6 +9,11 @@
*/
var config = {
address: "localhost", // Address to listen on, can be:
// - "localhost", "127.0.0.1", "::1" to listen on loopback interface
// - another specific IPv4/6 to listen on a specific interface
// - "", "0.0.0.0", "::" to listen on any interface
// Default, when address config is left out, is "localhost"
port: 8080,
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses
// or add a specific IPv4 of 192.168.1.5 :

View File

@@ -95,7 +95,7 @@ body {
header {
text-transform: uppercase;
font-size: 15px;
font-family: "Roboto Condensed";
font-family: "Roboto Condensed", Arial, Helvetica, sans-serif;
font-weight: 400;
border-bottom: 1px solid #666;
line-height: 15px;
@@ -151,6 +151,7 @@ sup {
.region.right {
right: 0;
text-align: right;
}
.region.top {
@@ -161,6 +162,10 @@ sup {
margin-bottom: 25px;
}
.region.bottom .container {
margin-top: 25px;
}
.region.top .container:empty {
margin-bottom: 0;
}
@@ -185,10 +190,6 @@ sup {
bottom: 0;
}
.region.bottom .container {
margin-top: 25px;
}
.region.bottom .container:empty {
margin-top: 0;
}
@@ -231,10 +232,6 @@ sup {
text-align: left;
}
.region.right {
text-align: right;
}
.region table {
width: 100%;
border-spacing: 0;

17
dangerfile.js Normal file
View File

@@ -0,0 +1,17 @@
import { danger, fail, warn } from "danger"
// Check if the CHANGELOG.md file has been edited
// Fail the build and post a comment reminding submitters to do so if it wasn't changed
if (!danger.git.modified_files.includes("CHANGELOG.md")) {
warn("Please include an updated `CHANGELOG.md` file.<br>This way we can keep track of all the contributions.")
}
// Check if the PR request is send to the master branch.
// This should only be done by MichMich.
if (danger.github.pr.base.ref === "master" && danger.github.pr.user.login !== "MichMich") {
// Check if the PR body or title includes the text: #accepted.
// If not, the PR will fail.
if ((danger.github.pr.body + danger.github.pr.title).includes("#accepted")) {
fail("Please send all your pull requests to the `develop` branch.<br>Pull requests on the `master` branch will not be accepted.")
}
}

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

12
fonts/package-lock.json generated Normal file
View File

@@ -0,0 +1,12 @@
{
"name": "magicmirror-fonts",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"roboto-fontface": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.8.0.tgz",
"integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
}
}
}

15
fonts/package.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "magicmirror-fonts",
"description": "Package for fonts use by MagicMirror Core.",
"repository": {
"type": "git",
"url": "git+https://github.com/MichMich/MagicMirror.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/MichMich/MagicMirror/issues"
},
"dependencies": {
"roboto-fontface": "^0.8.0"
}
}

View File

@@ -5,9 +5,9 @@
src:
local("Roboto Thin"),
local("Roboto-Thin"),
url("Roboto-Thin/Roboto-Thin.woff2") format("woff2"),
url("Roboto-Thin/Roboto-Thin.woff") format("woff"),
url("Roboto-Thin/Roboto-Thin.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.ttf") format("truetype");
}
@font-face {
@@ -17,9 +17,9 @@
src:
local("Roboto Condensed Light"),
local("RobotoCondensed-Light"),
url("RobotoCondensed-Light/RobotoCondensed-Light.woff2") format("woff2"),
url("RobotoCondensed-Light/RobotoCondensed-Light.woff") format("woff"),
url("RobotoCondensed-Light/RobotoCondensed-Light.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Light.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Light.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Light.ttf") format("truetype");
}
@font-face {
@@ -29,9 +29,9 @@
src:
local("Roboto Condensed"),
local("RobotoCondensed-Regular"),
url("RobotoCondensed-Regular/RobotoCondensed-Regular.woff2") format("woff2"),
url("RobotoCondensed-Regular/RobotoCondensed-Regular.woff") format("woff"),
url("RobotoCondensed-Regular/RobotoCondensed-Regular.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Regular.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Regular.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Regular.ttf") format("truetype");
}
@font-face {
@@ -41,9 +41,9 @@
src:
local("Roboto Condensed Bold"),
local("RobotoCondensed-Bold"),
url("RobotoCondensed-Bold/RobotoCondensed-Bold.woff2") format("woff2"),
url("RobotoCondensed-Bold/RobotoCondensed-Bold.woff") format("woff"),
url("RobotoCondensed-Bold/RobotoCondensed-Bold.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Bold.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Bold.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Bold.ttf") format("truetype");
}
@font-face {
@@ -53,9 +53,9 @@
src:
local("Roboto"),
local("Roboto-Regular"),
url("Roboto-Regular/Roboto-Regular.woff2") format("woff2"),
url("Roboto-Regular/Roboto-Regular.woff") format("woff"),
url("Roboto-Regular/Roboto-Regular.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.ttf") format("truetype");
}
@font-face {
@@ -65,9 +65,9 @@
src:
local("Roboto Medium"),
local("Roboto-Medium"),
url("Roboto-Medium/Roboto-Medium.woff2") format("woff2"),
url("Roboto-Medium/Roboto-Medium.woff") format("woff"),
url("Roboto-Medium/Roboto-Medium.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.ttf") format("truetype");
}
@font-face {
@@ -77,9 +77,9 @@
src:
local("Roboto Bold"),
local("Roboto-Bold"),
url("Roboto-Bold/Roboto-Bold.woff2") format("woff2"),
url("Roboto-Bold/Roboto-Bold.woff") format("woff"),
url("Roboto-Bold/Roboto-Bold.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.ttf") format("truetype");
}
@font-face {
@@ -89,7 +89,7 @@
src:
local("Roboto Light"),
local("Roboto-Light"),
url("Roboto-Light/Roboto-Light.woff2") format("woff2"),
url("Roboto-Light/Roboto-Light.woff") format("woff"),
url("Roboto-Light/Roboto-Light.ttf") format("truetype");
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff2") format("woff2"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff") format("woff"),
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.ttf") format("truetype");
}

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Magic Mirror</title>
<title>MagicMirror²</title>
<meta name="google" content="notranslate" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
@@ -38,6 +38,7 @@
</div>
<div class="region fullscreen above"><div class="container"></div></div>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="vendor/node_modules/nunjucks/browser/nunjucks.min.js"></script>
<script type="text/javascript" src="js/defaults.js"></script>
<script type="text/javascript" src="#CONFIG_FILE#"></script>
<script type="text/javascript" src="vendor/vendor.js"></script>

View File

@@ -42,7 +42,7 @@ sudo apt-get update || echo -e "\e[91mUpdate failed, carrying on installation ..
# Installing helper tools
echo -e "\e[96mInstalling helper tools ...\e[90m"
sudo apt-get install curl wget git build-essential unzip || exit
sudo apt-get --assume-yes install curl wget git build-essential unzip || exit
# Check if we need to install or upgrade Node.js.
echo -e "\e[96mCheck current Node installation ...\e[0m"
@@ -82,7 +82,7 @@ if $NODE_INSTALL; then
# The NODE_STABLE_BRANCH variable will need to be manually adjusted when a new branch is released. (e.g. 7.x)
# Only tested (stable) versions are recommended as newer versions could break MagicMirror.
NODE_STABLE_BRANCH="6.x"
NODE_STABLE_BRANCH="9.x"
curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_BRANCH | sudo -E bash -
sudo apt-get install -y nodejs
echo -e "\e[92mNode.js installation Done!\e[0m"
@@ -101,7 +101,7 @@ if [ -d "$HOME/MagicMirror" ] ; then
fi
echo -e "\e[96mCloning MagicMirror ...\e[90m"
if git clone https://github.com/MichMich/MagicMirror.git; then
if git clone --depth=1 https://github.com/MichMich/MagicMirror.git; then
echo -e "\e[92mCloning MagicMirror Done!\e[0m"
else
echo -e "\e[91mUnable to clone MagicMirror."
@@ -149,7 +149,7 @@ else
fi
# Use pm2 control like a service MagicMirror
read -p "Do you want use pm2 for auto starting of your MagicMirror (y/n)?" choice
read -p "Do you want use pm2 for auto starting of your MagicMirror (y/N)?" choice
if [[ $choice =~ ^[Yy]$ ]]; then
sudo npm install -g pm2
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup linux -u pi --hp /home/pi"

View File

@@ -236,6 +236,33 @@ var App = function() {
});
});
};
/* stop()
* This methods stops the core app.
* This calls each node_helper's STOP() function, if it exists.
* Added to fix #1056
*/
this.stop = function() {
for (var h in nodeHelpers) {
var nodeHelper = nodeHelpers[h];
if (typeof nodeHelper.stop === "function") {
nodeHelper.stop();
}
}
};
/* Listen for SIGINT signal and call stop() function.
*
* Added to fix #1056
* Note: this is only used if running `server-only`. Otherwise
* this.stop() is called by app.on("before-quit"... in `electron.js`
*/
process.on("SIGINT", () => {
console.log("[SIGINT] Received. Shutting down server...");
setTimeout(() => { process.exit(0); }, 3000); // Force quit after 3 seconds
this.stop();
process.exit(0);
});
};
module.exports = new App();

View File

@@ -4,15 +4,15 @@
*/
// Inspired by base2 and Prototype
(function() {
(function () {
var initializing = false;
var fnTest = /xyz/.test(function() {xyz;}) ? /\b_super\b/ : /.*/;
var fnTest = /xyz/.test(function () { xyz; }) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function() {};
this.Class = function () { };
// Create a new Class that inherits from this class
Class.extend = function(prop) {
Class.extend = function (prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
@@ -30,23 +30,23 @@
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
@@ -90,4 +90,6 @@ function cloneObject(obj) {
}
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {module.exports = Class;}
if (typeof module !== "undefined") {
module.exports = Class;
}

View File

@@ -8,10 +8,12 @@
*/
var port = 8080;
var address = "localhost";
if (typeof(mmPort) !== "undefined") {
port = mmPort;
}
var defaults = {
address: address,
port: port,
kioskmode: false,
electronOptions: {},

View File

@@ -6,7 +6,7 @@ const electron = require("electron");
const core = require(__dirname + "/app.js");
// Config
var config = {};
var config = process.env.config ? JSON.parse(process.env.config) : {};
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
@@ -17,7 +17,6 @@ const BrowserWindow = electron.BrowserWindow;
let mainWindow;
function createWindow() {
var electronOptionsDefaults = {
width: 800,
height: 600,
@@ -46,8 +45,9 @@ function createWindow() {
mainWindow = new BrowserWindow(electronOptions);
// and load the index.html of the app.
//mainWindow.loadURL('file://' + __dirname + '../../index.html');
mainWindow.loadURL("http://localhost:" + config.port);
// If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost
var address = (config.address === void 0) | (config.address === "") ? (config.address = "localhost") : config.address;
mainWindow.loadURL(`http://${address}:${config.port}`);
// Open the DevTools if run with "npm start dev"
if (process.argv.includes("dev")) {
@@ -96,8 +96,24 @@ app.on("activate", function() {
}
});
// Start the core application.
// This starts all node helpers and starts the webserver.
core.start(function(c) {
config = c;
/* This method will be called when SIGINT is received and will call
* each node_helper's stop function if it exists. Added to fix #1056
*
* Note: this is only used if running Electron. Otherwise
* core.stop() is called by process.on("SIGINT"... in `app.js`
*/
app.on("before-quit", (event) => {
console.log("Shutting down server...");
event.preventDefault();
setTimeout(() => { process.exit(0); }, 3000); // Force-quit after 3 seconds.
core.stop();
process.exit(0);
});
// Start the core application if server is run on localhost
// This starts all node helpers and starts the webserver.
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) > -1) {
core.start(function(c) {
config = c;
});
}

View File

@@ -1,5 +1,5 @@
/* global Log, Loader, Module, config, defaults */
/* jshint -W020 */
/* jshint -W020, esversion: 6 */
/* Magic Mirror
* Main System
@@ -19,42 +19,49 @@ var MM = (function() {
* are configured for a specific position.
*/
var createDomObjects = function() {
for (var m in modules) {
var module = modules[m];
var domCreationPromises = [];
if (typeof module.data.position === "string") {
var wrapper = selectWrapper(module.data.position);
var dom = document.createElement("div");
dom.id = module.identifier;
dom.className = module.name;
if (typeof module.data.classes === "string") {
dom.className = "module " + dom.className + " " + module.data.classes;
}
dom.opacity = 0;
wrapper.appendChild(dom);
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);
}
var moduleContent = document.createElement("div");
moduleContent.className = "module-content";
dom.appendChild(moduleContent);
updateDom(module, 0);
modules.forEach(module => {
if (typeof module.data.position !== "string") {
return;
}
}
var wrapper = selectWrapper(module.data.position);
var dom = document.createElement("div");
dom.id = module.identifier;
dom.className = module.name;
if (typeof module.data.classes === "string") {
dom.className = "module " + dom.className + " " + module.data.classes;
}
dom.opacity = 0;
wrapper.appendChild(dom);
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);
}
var moduleContent = document.createElement("div");
moduleContent.className = "module-content";
dom.appendChild(moduleContent);
var domCreationPromise = updateDom(module, 0);
domCreationPromises.push(domCreationPromise);
domCreationPromise.then(() => {
sendNotification("MODULE_DOM_CREATED", null, null, module);
}).catch(Log.error);
});
updateWrapperStates();
sendNotification("DOM_OBJECTS_CREATED");
Promise.all(domCreationPromises).then(() => {
sendNotification("DOM_OBJECTS_CREATED");
});
};
/* selectWrapper(position)
@@ -79,11 +86,12 @@ var MM = (function() {
* argument notification string - The identifier of the notification.
* argument payload mixed - The payload of the notification.
* argument sender Module - The module that sent the notification.
* argument sendTo Module - The module to send the notification to. (optional)
*/
var sendNotification = function(notification, payload, sender) {
var sendNotification = function(notification, payload, sender, sendTo) {
for (var m in modules) {
var module = modules[m];
if (module !== sender) {
if (module !== sender && (!sendTo || module === sendTo)) {
module.notificationReceived(notification, payload, sender);
}
}
@@ -94,19 +102,53 @@ var MM = (function() {
*
* argument module Module - The module that needs an update.
* argument speed Number - The number of microseconds for the animation. (optional)
*
* return Promise - Resolved when the dom is fully updated.
*/
var updateDom = function(module, speed) {
var newContent = module.getDom();
var newHeader = module.getHeader();
return new Promise((resolve) => {
var newContentPromise = module.getDom();
var newHeader = module.getHeader();
if (!module.hidden) {
if (!(newContentPromise instanceof Promise)) {
// convert to a promise if not already one to avoid if/else's everywhere
newContentPromise = Promise.resolve(newContentPromise);
}
newContentPromise.then((newContent) => {
var updatePromise = updateDomWithContent(module, speed, newHeader, newContent);
updatePromise.then(resolve).catch(Log.error);
}).catch(Log.error);
});
};
/* updateDomWithContent(module, speed, newHeader, newContent)
* Update the dom with the specified content
*
* argument module Module - The module that needs an update.
* argument speed Number - The number of microseconds for the animation. (optional)
* argument newHeader String - The new header that is generated.
* argument newContent Domobject - The new content that is generated.
*
* return Promise - Resolved when the module dom has been updated.
*/
var updateDomWithContent = function(module, speed, newHeader, newContent) {
return new Promise((resolve) => {
if (module.hidden || !speed) {
updateModuleContent(module, newHeader, newContent);
resolve();
return;
}
if (!moduleNeedsUpdate(module, newHeader, newContent)) {
resolve();
return;
}
if (!speed) {
updateModuleContent(module, newHeader, newContent);
resolve();
return;
}
@@ -115,16 +157,16 @@ var MM = (function() {
if (!module.hidden) {
showModule(module, speed / 2);
}
resolve();
});
} else {
updateModuleContent(module, newHeader, newContent);
}
});
};
/* moduleNeedsUpdate(module, newContent)
* Check if the content has changed.
*
* argument module Module - The module to check.
* argument newHeader String - The new header that is generated.
* argument newContent Domobject - The new content that is generated.
*
* return bool - Does the module need an update?
@@ -152,6 +194,7 @@ var MM = (function() {
* Update the content of a module on screen.
*
* argument module Module - The module to check.
* argument newHeader String - The new header that is generated.
* argument newContent Domobject - The new content that is generated.
*/
var updateModuleContent = function(module, newHeader, newContent) {

View File

@@ -27,6 +27,11 @@ var Module = Class.extend({
// visibility when hiding and showing module.
lockStrings: [],
// Storage of the nunjuck Environment,
// This should not be referenced directly.
// Use the nunjucksEnvironment() to get it.
_nunjucksEnvironment: null,
/* init()
* Is called when the module is instantiated.
*/
@@ -70,25 +75,36 @@ var Module = Class.extend({
/* getDom()
* This method generates the dom which needs to be displayed. This method is called by the Magic Mirror core.
* This method needs to be subclassed if the module wants to display info on the mirror.
* This method can to be subclassed if the module wants to display info on the mirror.
* Alternatively, the getTemplete method could be subclassed.
*
* return domobject - The dom to display.
* return DomObject | Promise - The dom or a promise with the dom to display.
*/
getDom: function () {
var nameWrapper = document.createElement("div");
var name = document.createTextNode(this.name);
nameWrapper.appendChild(name);
return new Promise((resolve) => {
var div = document.createElement("div");
var template = this.getTemplate();
var templateData = this.getTemplateData();
var identifierWrapper = document.createElement("div");
var identifier = document.createTextNode(this.identifier);
identifierWrapper.appendChild(identifier);
identifierWrapper.className = "small dimmed";
// Check to see if we need to render a template string or a file.
if (/^.*((\.html)|(\.njk))$/.test(template)) {
// the template is a filename
this.nunjucksEnvironment().render(template, templateData, function (err, res) {
if (err) {
Log.error(err)
}
var div = document.createElement("div");
div.appendChild(nameWrapper);
div.appendChild(identifierWrapper);
div.innerHTML = res;
return div;
resolve(div);
});
} else {
// the template is a template string.
div.innerHTML = this.nunjucksEnvironment().renderString(template, templateData);
resolve(div);
}
});
},
/* getHeader()
@@ -102,6 +118,28 @@ var Module = Class.extend({
return this.data.header;
},
/* getTemplate()
* This method returns the template for the module which is used by the default getDom implementation.
* This method needs to be subclassed if the module wants to use a tempate.
* It can either return a template sting, or a template filename.
* If the string ends with '.html' it's considered a file from within the module's folder.
*
* return string - The template string of filename.
*/
getTemplate: function () {
return "<div class=\"normal\">" + this.name + "</div><div class=\"small dimmed\">" + this.identifier + "</div>";
},
/* getTemplateData()
* This method returns the data to be used in the template.
* This method needs to be subclassed if the module wants to use a custom data.
*
* return Object
*/
getTemplateData: function () {
return {}
},
/* notificationReceived(notification, payload, sender)
* This method is called when a notification arrives.
* This method is called by the Magic Mirror core.
@@ -118,6 +156,30 @@ var Module = Class.extend({
}
},
/** nunjucksEnvironment()
* Returns the nunjucks environment for the current module.
* The environment is checked in the _nunjucksEnvironment instance variable.
* @returns Nunjucks Environment
*/
nunjucksEnvironment: function() {
if (this._nunjucksEnvironment != null) {
return this._nunjucksEnvironment;
}
var self = this;
this._nunjucksEnvironment = new nunjucks.Environment(new nunjucks.WebLoader(this.file(""), {async: true}), {
trimBlocks: true,
lstripBlocks: true
});
this._nunjucksEnvironment.addFilter("translate", function(str) {
return self.translate(str)
});
return this._nunjucksEnvironment;
},
/* socketNotificationReceived(notification, payload)
* This method is called when a socket notification arrives.
*
@@ -194,7 +256,7 @@ var Module = Class.extend({
* return string - File path.
*/
file: function (file) {
return this.data.path + "/" + file;
return (this.data.path + "/" + file).replace("//", "/");
},
/* loadStyles()
@@ -276,8 +338,8 @@ var Module = Class.extend({
* Request the translation for a given key with optional variables and default value.
*
* argument key string - The key of the string to translate
* argument defaultValueOrVariables string/object - The default value or variables for translating. (Optional)
* argument defaultValue string - The default value with variables. (Optional)
* argument defaultValueOrVariables string/object - The default value or variables for translating. (Optional)
* argument defaultValue string - The default value with variables. (Optional)
*/
translate: function (key, defaultValueOrVariables, defaultValue) {
if(typeof defaultValueOrVariables === "object") {
@@ -414,11 +476,3 @@ Module.register = function (name, moduleDefinition) {
Log.log("Module registered: " + name);
Module.definitions[name] = moduleDefinition;
};
if (typeof exports != "undefined") { // For testing purpose only
// A good a idea move the function cmpversions a helper file.
// It's used into other side.
exports._test = {
cmpVersions: cmpVersions
}
}

View File

@@ -13,6 +13,7 @@ var path = require("path");
var ipfilter = require("express-ipfilter").IpFilter;
var fs = require("fs");
var helmet = require("helmet");
var Utils = require(__dirname + "/utils.js");
var Server = function(config, callback) {
@@ -26,11 +27,11 @@ var Server = function(config, callback) {
server.listen(port, config.address ? config.address : null);
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length == 0) {
console.info("You're using a full whitelist configuration to allow for all IPs")
console.info(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs"))
}
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: config.ipWhitelist.length === 0 ? "deny" : "allow", log: false})(req, res, function(err) {
if (err === undefined) {
return next();
}
@@ -52,6 +53,10 @@ var Server = function(config, callback) {
res.send(global.version);
});
app.get("/config", function(req,res) {
res.send(config);
});
app.get("/", function(req, res) {
var html = fs.readFileSync(path.resolve(global.root_path + "/index.html"), {encoding: "utf8"});
html = html.replace("#VERSION#", global.version);

View File

@@ -126,6 +126,9 @@ var Translator = (function() {
// variables: {timeToWait: "2 hours", work: "painting"}
// to: "Please wait for 2 hours before continuing with painting."
function createStringFromTemplate(template, variables) {
if(Object.prototype.toString.call(template) !== "[object String]") {
return template;
}
if(variables.fallback && !template.match(new RegExp("\{.+\}"))) {
template = variables.fallback;
}
@@ -156,11 +159,12 @@ var Translator = (function() {
return key;
},
/* load(module, file, callback)
/* load(module, file, isFallback, callback)
* Load a translation file (json) and remember the data.
*
* argument module Module - The module to load the translation file for.
* argument file string - Path of the file we want to load.
* argument isFallback boolean - Flag to indicate fallback translations.
* argument callback function - Function called when done.
*/
load: function(module, file, isFallback, callback) {
@@ -216,10 +220,12 @@ var Translator = (function() {
// defined translation after the following line.
for (var first in translations) {break;}
Log.log("Loading core translation fallback file: " + translations[first]);
loadJSON(translations[first], function(translations) {
self.coreTranslationsFallback = translations;
});
if (first) {
Log.log("Loading core translation fallback file: " + translations[first]);
loadJSON(translations[first], function(translations) {
self.coreTranslationsFallback = translations;
});
}
},
};
})();

31
module-types.ts Normal file
View File

@@ -0,0 +1,31 @@
type ModuleProperties = {
defaults?: object,
start?(): void,
getHeader?(): string,
getTemplate?(): string,
getTemplateData?(): object,
notificationReceived?(notification: string, payload: any, sender: object): void,
socketNotificationReceived?(notification: string, payload: any): void,
suspend?(): void,
resume?(): void,
getDom?(): HTMLElement,
getStyles?(): string[],
[key: string]: any,
};
export declare const Module: {
register(moduleName: string, moduleProperties: ModuleProperties): void;
};
export declare const Log: {
info(message?: any, ...optionalParams: any[]): void,
log(message?: any, ...optionalParams: any[]): void,
error(message?: any, ...optionalParams: any[]): void,
warn(message?: any, ...optionalParams: any[]): void,
group(groupTitle?: string, ...optionalParams: any[]): void,
groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void,
groupEnd(): void,
time(timerName?: string): void,
timeEnd(timerName?: string): void,
timeStamp(timerName?: string): void,
};

View File

@@ -2,6 +2,42 @@
This document describes the way to develop your own MagicMirror² modules.
Table of Contents:
- Module structure
- Files
- The Core module file: modulename.js
- Available module instance properties
- Subclassable module methods
- Module instance methods
- Visibility locking
- The Node Helper: node_helper.js
- Available module instance properties
- Subclassable module methods
- Module instance methods
- MagicMirror Helper Methods
- Module Selection
- MagicMirror Logger
---
## General Advice
As MagicMirror has gained huge popularity, so has the number of available modules. For new users and developers alike, it is very time consuming to navigate around the various repositories in order to find out what exactly a certain modules does, how it looks and what it depends on. Unfortunately, this information is rarely available, nor easily obtained without having to install it first.
Therefore **we highly recommend you to include the following information in your README file.**
- A high quality screenshot of your working module
- A short, one sentence, clear description what it does (duh!)
- What external API's it depend on, including web links to those
- Wheteher the API/request require a key and the user limitations of those. (Is it free?)
Surely this also help you get better recognition and feedback for your work.
## Module structure
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.
@@ -14,7 +50,7 @@ A module can be placed in one single folder. Or multiple modules can be grouped
- **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.
## Core module file: modulename.js
## The Core module file: modulename.js
This is the script in which the module will be defined. This script is required in order for the module to be used. In it's most simple form, the core module file must contain:
````javascript
Module.register("modulename",{});
@@ -44,30 +80,16 @@ As you can see, the `Module.register()` method takes two arguments: the name of
### Available module instance properties
After the module is initialized, the module instance has a few available module properties:
#### `this.name`
**String**
| Instance Property | Type | Description |
|:----------------- |:---- |:----------- |
| `this.name` | String | The name of the module. |
| `this.identifier` | String | This is a unique identifier for the module instance. |
| `this.hidden` | Boolean | This represents if the module is currently hidden (faded away). |
| `this.config` | Boolean | The configuration of the module instance as set in the user's `config.js` file. This config will also contain the module's defaults if these properties are not over-written by the user config. |
| `this.data` | Object | The data object contain additional metadata about the module instance. (See below) |
The name of the module.
#### `this.identifier`
**String**
This is a unique identifier for the module instance.
#### `this.hidden`
**Boolean**
This represents if the module is currently hidden (faded away).
#### `this.config`
**Boolean**
The configuration of the module instance as set in the user's config.js file. This config will also contain the module's defaults if these properties are not over written by the user config.
#### `this.data`
**Object**
The data object contains additional metadata about the module instance:
The `this.data` data object contain the follwoing metadata:
- `data.classes` - The classes which are added to the module dom wrapper.
- `data.file` - The filename of the core module file.
- `data.path` - The path of the module folder.
@@ -230,11 +252,12 @@ notificationReceived: function(notification, payload, sender) {
}
````
**Note:** the system sends two notifications when starting up. These notifications could come in handy!
**Note:** the system sends three 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.
- `DOM_OBJECTS_CREATED` - All dom objects are created. The system is now ready to perform visual changes.
- `MODULE_DOM_CREATED` - This module's dom has been fully loaded. You can now access your module's dom objects.
#### `socketNotificationReceived: function(notification, payload)`
@@ -472,7 +495,7 @@ this.translate("RUNNING", {
{
"RUNNING": "Slutar",
}
````
In this case the `translate`-function will not find any variables in the translation, will look for `fallback` variable and use that if possible to create the translation.
## The Node Helper: node_helper.js
@@ -555,6 +578,17 @@ start: function() {
}
````
#### `stop()`
This method is called when the MagicMirror server receives a `SIGINT` command and is shutting down. This method should include any commands needed to close any open connections, stop any sub-processes and gracefully exit the module.
**Example:**
````javascript
stop: function() {
console.log("Shutting down MyModule");
this.connection.close();
}
````
#### `socketNotificationReceived: function(notification, payload)`
With this method, your node helper can receive notifications from your modules. When this method is called, it has 2 arguments:

View File

@@ -60,5 +60,5 @@ self.sendNotification("SHOW_ALERT", {});
| `timer` (optional) | How long the alert should stay visible in ms. <br> **Important:** If you do not use the `timer`, it is your duty to hide the alert by using `self.sendNotification("HIDE_ALERT");`! <br><br>**Possible values:** `int` `float` <br> **Default value:** `none`
## Open Source Licenses
###[NotificationStyles](https://github.com/codrops/NotificationStyles)
### [NotificationStyles](https://github.com/codrops/NotificationStyles)
See [ympanus.net](http://tympanus.net/codrops/licensing/) for license.

View File

@@ -0,0 +1,4 @@
{
"sysTitle": "MagicMirror нотификация",
"welcome": "Добре дошли, стартирането беше успешно"
}

View File

@@ -46,7 +46,7 @@ The following properties can be configured:
| `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates <br><br> **Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days) <br><br> **Default value:** `7`
| `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`. <br><br> **Possible values:** `true`, `false` <br><br> **Default value:** `true`
| `hidePrivate` | Hides private calendar events. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown. <br><br> **Example:** `['Birthday', 'Hide This Event']` <br> **Default value:** `[]`
| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown. <br><br>Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.<br>**Required**<br>`filterBy` - string used to determine if filter is applied.<br>**Optional**<br>`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]<br>`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity<br><br> **Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}]` <br> **Default value:** `[]`
### Calendar configuration

View File

@@ -67,30 +67,7 @@ Module.register("calendar", {
Log.log("Starting module: " + this.name);
// Set locale.
moment.locale(config.language);
switch (config.timeFormat) {
case 12: {
moment.updateLocale(config.language, {
longDateFormat: {
LT: "h:mm A"
}
});
break;
}
case 24: {
moment.updateLocale(config.language, {
longDateFormat: {
LT: "hh:mm"
}
});
break;
}
// If config.timeFormat was not given (or has invalid format) default to locale default
default: {
break;
}
}
moment.updateLocale(config.language, this.getLocaleSpecification(config.timeFormat));
for (var c in this.config.calendars) {
var calendar = this.config.calendars[c];
@@ -102,7 +79,9 @@ Module.register("calendar", {
};
// we check user and password here for backwards compatibility with old configs
if(calendar.user && calendar.pass){
if(calendar.user && calendar.pass) {
Log.warn("Deprecation warning: Please update your calendar authentication configuration.");
Log.warn("https://github.com/MichMich/MagicMirror/tree/v2.1.2/modules/default/calendar#calendar-authentication-options");
calendar.auth = {
user: calendar.user,
pass: calendar.pass
@@ -153,20 +132,6 @@ Module.register("calendar", {
for (var e in events) {
var event = events[e];
var excluded = false;
for (var f in this.config.excludedEvents) {
var filter = this.config.excludedEvents[f];
if (event.title.toLowerCase().includes(filter.toLowerCase())) {
excluded = true;
break;
}
}
if (excluded) {
continue;
}
var eventWrapper = document.createElement("tr");
if (this.config.colored) {
@@ -185,7 +150,7 @@ Module.register("calendar", {
for(var i = 0; i < symbols.length; i++) {
var symbol = document.createElement("span");
symbol.className = "fa fa-" + symbols[i];
symbol.className = "fa fa-fw fa-" + symbols[i];
if(i > 0){
symbol.style.paddingLeft = "5px";
}
@@ -320,6 +285,31 @@ Module.register("calendar", {
return wrapper;
},
/**
* This function accepts a number (either 12 or 24) and returns a moment.js LocaleSpecification with the
* corresponding timeformat to be used in the calendar display. If no number is given (or otherwise invalid input)
* it will a localeSpecification object with the system locale time format.
*
* @param {number} timeFormat Specifies either 12 or 24 hour time format
* @returns {moment.LocaleSpecification}
*/
getLocaleSpecification: function(timeFormat) {
switch (timeFormat) {
case 12: {
return { longDateFormat: {LT: "h:mm A"} };
break;
}
case 24: {
return { longDateFormat: {LT: "HH:mm"} };
break;
}
default: {
return { longDateFormat: {LT: moment.localeData().longDateFormat("LT")} };
break;
}
}
},
/* hasCalendarURL(url)
* Check if this config contains the calendar url.
*
@@ -377,6 +367,7 @@ Module.register("calendar", {
addCalendar: function (url, auth, calendarConfig) {
this.sendSocketNotification("ADD_CALENDAR", {
url: url,
excludedEvents: calendarConfig.excludedEvents || this.config.excludedEvents,
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
fetchInterval: this.config.fetchInterval,
@@ -437,25 +428,27 @@ Module.register("calendar", {
return defaultValue;
},
/* shorten(string, maxLength)
* Shortens a string if it's longer than maxLength.
* Adds an ellipsis to the end.
/**
* Shortens a string if it's longer than maxLength and add a ellipsis to the end
*
* argument string string - The string to shorten.
* argument maxLength number - The max length of the string.
* argument wrapEvents - Wrap the text after the line has reached maxLength
*
* return string - The shortened string.
* @param {string} string Text string to shorten
* @param {number} maxLength The max length of the string
* @param {boolean} wrapEvents Wrap the text after the line has reached maxLength
* @returns {string} The shortened string
*/
shorten: function (string, maxLength, wrapEvents) {
if (wrapEvents) {
if (typeof string !== "string") {
return "";
}
if (wrapEvents === true) {
var temp = "";
var currentLine = "";
var words = string.split(" ");
for (var i = 0; i < words.length; i++) {
var word = words[i];
if (currentLine.length + word.length < 25 - 1) { // max - 1 to account for a space
if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) { // max - 1 to account for a space
currentLine += (word + " ");
} else {
if (currentLine.length > 0) {
@@ -467,12 +460,12 @@ Module.register("calendar", {
}
}
return temp + currentLine;
return (temp + currentLine).trim();
} else {
if (string.length > maxLength) {
return string.slice(0, maxLength) + "&hellip;";
if (maxLength && typeof maxLength === "number" && string.length > maxLength) {
return string.trim().slice(0, maxLength) + "&hellip;";
} else {
return string;
return string.trim();
}
}
},
@@ -522,6 +515,8 @@ Module.register("calendar", {
var calendar = this.calendarData[url];
for (var e in calendar) {
var event = cloneObject(calendar[e]);
event.symbol = this.symbolsForUrl(url);
event.color = this.colorForUrl(url);
delete event.url;
eventList.push(event);
}

View File

@@ -8,7 +8,7 @@
var ical = require("./vendor/ical.js");
var moment = require("moment");
var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumberOfDays, auth) {
var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth) {
var self = this;
var reloadTimer = null;
@@ -113,6 +113,46 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
title = event.description;
}
var excluded = false,
dateFilter = null;
for (var f in excludedEvents) {
var filter = excludedEvents[f],
testTitle = title.toLowerCase(),
until = null;
if (filter instanceof Object) {
if (typeof filter.until !== "undefined") {
until = filter.until;
}
// If additional advanced filtering is added in, this section
// must remain last as we overwrite the filter object with the
// filterBy string
if (filter.caseSensitive) {
filter = filter.filterBy;
testTitle = title;
} else {
filter = filter.filterBy.toLowerCase();
}
} else {
filter = filter.toLowerCase();
}
if (testTitle.includes(filter)) {
if (until) {
dateFilter = until;
} else {
excluded = true;
}
break;
}
}
if (excluded) {
continue;
}
var location = event.location || false;
var geo = event.geo || false;
var description = event.description || false;
@@ -124,6 +164,11 @@ 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");
if (timeFilterApplies(now, endDate, dateFilter)) {
continue;
}
if (endDate.format("x") > now) {
newEvents.push({
title: title,
@@ -158,6 +203,10 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
continue;
}
if (timeFilterApplies(now, endDate, dateFilter)) {
continue;
}
// Every thing is good. Add it to the list.
newEvents.push({
@@ -223,6 +272,28 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
return false;
};
/* timeFilterApplies()
* Determines if the user defined time filter should apply
*
* argument now Date - Date object using previously created object for consistency
* argument endDate Moment - Moment object representing the event end date
* argument filter string - The time to subtract from the end date to determine if an event should be shown
*
* return bool - The event should be filtered out
*/
var timeFilterApplies = function(now, endDate, filter) {
if (filter) {
var until = filter.split(" "),
value = parseInt(until[0]),
increment = until[1].slice("-1") === "s" ? until[1] : until[1] + "s", // Massage the data for moment js
filterUntil = moment(endDate.format()).subtract(value, increment);
return now < filterUntil.format("x");
}
return false;
};
/* public methods */
/* startFetch()

View File

@@ -24,7 +24,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, payload.auth);
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth);
}
},
@@ -36,7 +36,7 @@ module.exports = NodeHelper.create({
* attribute reloadInterval number - Reload interval in milliseconds.
*/
createFetcher: function(url, fetchInterval, maximumEntries, maximumNumberOfDays, auth) {
createFetcher: function(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth) {
var self = this;
if (!validUrl.isUri(url)) {
@@ -47,7 +47,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, auth);
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth);
fetcher.onReceive(function(fetcher) {
//console.log('Broadcast events.');

View File

@@ -108,7 +108,7 @@ vows.describe('node-ical').addBatch({
assert.equal(topic.end.getFullYear(), 1998);
assert.equal(topic.end.getUTCMonth(), 2);
assert.equal(topic.end.getUTCDate(), 15);
assert.equal(topic.end.getUTCHours(), 00);
assert.equal(topic.end.getUTCHours(), 0);
assert.equal(topic.end.getUTCMinutes(), 30);
}
}
@@ -146,7 +146,7 @@ vows.describe('node-ical').addBatch({
}
, 'has a start datetime' : function(topic) {
assert.equal(topic.start.getFullYear(), 2011);
assert.equal(topic.start.getMonth(), 09);
assert.equal(topic.start.getMonth(), 9);
assert.equal(topic.start.getDate(), 11);
}
@@ -192,7 +192,7 @@ vows.describe('node-ical').addBatch({
}
, 'has a start' : function(topic){
assert.equal(topic.start.tz, 'America/Phoenix')
assert.equal(topic.start.toISOString(), new Date(2011, 10, 09, 19, 0,0).toISOString())
assert.equal(topic.start.toISOString(), new Date(2011, 10, 9, 19, 0,0).toISOString())
}
}
}
@@ -208,7 +208,7 @@ vows.describe('node-ical').addBatch({
})[0];
}
, 'has a start' : function(topic){
assert.equal(topic.start.toISOString(), new Date(2011, 07, 04, 12, 0,0).toISOString())
assert.equal(topic.start.toISOString(), new Date(2011, 7, 4, 12, 0,0).toISOString())
}
}
, 'event with rrule' :{
@@ -249,7 +249,7 @@ vows.describe('node-ical').addBatch({
},
'task completed': function(task){
assert.equal(task.completion, 100);
assert.equal(task.completed.toISOString(), new Date(2013, 06, 16, 10, 57, 45).toISOString());
assert.equal(task.completed.toISOString(), new Date(2013, 6, 16, 10, 57, 45).toISOString());
}
}
}
@@ -367,7 +367,7 @@ vows.describe('node-ical').addBatch({
assert.equal(topic.end.getFullYear(), 2014);
assert.equal(topic.end.getMonth(), 3);
assert.equal(topic.end.getUTCHours(), 19);
assert.equal(topic.end.getUTCMinutes(), 00);
assert.equal(topic.end.getUTCMinutes(), 0);
}
}
},

View File

@@ -94,7 +94,7 @@ Module.register("clock",{
dateWrapper.innerHTML = now.format(this.config.dateFormat);
}
if (this.config.showWeek) {
weekWrapper.innerHTML = this.translate("WEEK") + " " + now.week();
weekWrapper.innerHTML = this.translate("WEEK", { weekNumber: now.week() });
}
timeWrapper.innerHTML = timeString;
secondsWrapper.innerHTML = now.format("ss");

View File

@@ -1,5 +1,5 @@
.clockCircle {
margin: 0;
margin: 0 auto;
position: relative;
border-radius: 50%;
background-size: 100%;

View File

@@ -32,6 +32,12 @@ The following properties can be configured:
| `compliments` | The list of compliments. <br><br> **Possible values:** An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. See _compliment configuration_ below. <br> **Default value:** See _compliment configuration_ below.
| `remoteFile` | External file from which to load the compliments <br><br> **Possible values:** Path to a JSON file containing compliments, configured as per the value of the _compliments configuration_ (see below). An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. - `compliments.json` <br> **Default value:** `null` (Do not load from file)
| `classes` | Override the CSS classes of the div showing the compliments <br><br> **Default value:** `thin xlarge bright`
| `morningStartTime` | Time in hours (in 24 format), after which the mode of "morning" will begin <br> **Possible values:** `0` - `24` <br><br> **Default value:** `3`
| `morningEndTime` | Time in hours (in 24 format), after which the mode of "morning" will end <br> **Possible values:** `0` - `24` <br><br> **Default value:** `12`
| `afternoonStartTime` | Time in hours (in 24 format), after which the mode "afternoon" will begin <br> **Possible values:** `0` - `24` <br><br> **Default value:** `12`
| `afternoonEndTime` | Time in hours (in 24 format), after which the mode "afternoon" will end <br> **Possible values:** `0` - `24` <br><br> **Default value:** `17`
All the rest of the time that does not fall into the morningStartTime-morningEndTime and afternoonStartTime-afternoonEndTime ranges is considered "evening".
### Compliment configuration

View File

@@ -32,7 +32,11 @@ Module.register("compliments", {
},
updateInterval: 30000,
remoteFile: null,
fadeSpeed: 4000
fadeSpeed: 4000,
morningStartTime: 3,
morningEndTime: 12,
afternoonStartTime: 12,
afternoonEndTime: 17
},
// Set currentweather from module
@@ -49,14 +53,15 @@ Module.register("compliments", {
this.lastComplimentIndex = -1;
var self = this;
if (this.config.remoteFile != null) {
this.complimentFile((response) => {
this.config.compliments = JSON.parse(response);
self.updateDom();
});
}
// Schedule update timer.
var self = this;
setInterval(function() {
self.updateDom(self.config.fadeSpeed);
}, this.config.updateInterval);
@@ -98,9 +103,9 @@ Module.register("compliments", {
var hour = moment().hour();
var compliments;
if (hour >= 3 && hour < 12 && this.config.compliments.hasOwnProperty("morning")) {
if (hour >= this.config.morningStartTime && hour < this.config.morningEndTime && this.config.compliments.hasOwnProperty("morning")) {
compliments = this.config.compliments.morning.slice(0);
} else if (hour >= 12 && hour < 17 && this.config.compliments.hasOwnProperty("afternoon")) {
} else if (hour >= this.config.afternoonStartTime && hour < this.config.afternoonEndTime && this.config.compliments.hasOwnProperty("afternoon")) {
compliments = this.config.compliments.afternoon.slice(0);
} else if(this.config.compliments.hasOwnProperty("evening")) {
compliments = this.config.compliments.evening.slice(0);

View File

@@ -43,9 +43,12 @@ The following properties can be configured:
| `showWindDirectionAsArrow` | Show the wind direction as an arrow instead of abbreviation <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `showHumidity` | Show the current humidity <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `showIndoorTemperature` | If you have another module that emits the INDOOR_TEMPERATURE notification, the indoor temperature will be displayed <br> **Default value:** `false`
| `onlyTemp` | Show only current Temperature and weather icon. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `onlyTemp` | Show only current Temperature and weather icon without windspeed, sunset, sunrise time and feels like. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `showFeelsLike` | Shows the Feels like temperature weather. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `true`
| `useKMPHWind` | Uses KMPH as units for windspeed. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `false`
| `useBeaufort` | Pick between using the Beaufort scale for wind speed or using the default units. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `lang` | The language of the days. <br><br> **Possible values:** `en`, `nl`, `ru`, etc ... <br> **Default value:** uses value of _config.language_
| `decimalSymbol` | The decimal symbol to use.<br><br> **Possible values:** `.`, `,` or any other symbol.<br> **Default value:** `.`
| `initialLoadDelay` | The initial delay before loading. If you have multiple modules that use the same API key, you might want to delay one of the requests. (Milliseconds) <br><br> **Possible values:** `1000` - `5000` <br> **Default value:** `0`
| `retryDelay` | The delay before retrying after a request failure. (Milliseconds) <br><br> **Possible values:** `1000` - `60000` <br> **Default value:** `2500`
| `apiVersion` | The OpenWeatherMap API version to use. <br><br> **Default value:** `2.5`

View File

@@ -23,16 +23,20 @@ Module.register("currentweather",{
showWindDirection: true,
showWindDirectionAsArrow: false,
useBeaufort: true,
useKMPHwind: false,
lang: config.language,
decimalSymbol: ".",
showHumidity: false,
degreeLabel: false,
showIndoorTemperature: false,
showIndoorHumidity: false,
showFeelsLike: true,
initialLoadDelay: 0, // 0 seconds delay
retryDelay: 2500,
apiVersion: "2.5",
apiBase: "http://api.openweathermap.org/data/",
apiBase: "https://api.openweathermap.org/data/",
weatherEndpoint: "weather",
appendLocationNameToHeader: true,
@@ -101,8 +105,9 @@ Module.register("currentweather",{
this.sunriseSunsetIcon = null;
this.temperature = null;
this.indoorTemperature = null;
this.indoorHumidity = null;
this.weatherType = null;
this.feelsLike = null;
this.loaded = false;
this.scheduleUpdate(this.config.initialLoadDelay);
@@ -207,9 +212,13 @@ Module.register("currentweather",{
}
}
if (this.config.decimalSymbol === "") {
this.config.decimalSymbol = ".";
}
var temperature = document.createElement("span");
temperature.className = "bright";
temperature.innerHTML = " " + this.temperature + "&deg;" + degreeLabel;
temperature.innerHTML = " " + this.temperature.replace(".", this.config.decimalSymbol) + "&deg;" + degreeLabel;
large.appendChild(temperature);
if (this.config.showIndoorTemperature && this.indoorTemperature) {
@@ -219,11 +228,35 @@ Module.register("currentweather",{
var indoorTemperatureElem = document.createElement("span");
indoorTemperatureElem.className = "bright";
indoorTemperatureElem.innerHTML = " " + this.indoorTemperature + "&deg;" + degreeLabel;
indoorTemperatureElem.innerHTML = " " + this.indoorTemperature.replace(".", this.config.decimalSymbol) + "&deg;" + degreeLabel;
large.appendChild(indoorTemperatureElem);
}
if (this.config.showIndoorHumidity && this.indoorHumidity) {
var indoorHumidityIcon = document.createElement("span");
indoorHumidityIcon.className = "fa fa-tint";
large.appendChild(indoorHumidityIcon);
var indoorHumidityElem = document.createElement("span");
indoorHumidityElem.className = "bright";
indoorHumidityElem.innerHTML = " " + this.indoorHumidity + "%";
large.appendChild(indoorHumidityElem);
}
wrapper.appendChild(large);
if (this.config.showFeelsLike && this.config.onlyTemp === false){
var small = document.createElement("div");
small.className = "normal medium";
var feelsLike = document.createElement("span");
feelsLike.className = "dimmed";
feelsLike.innerHTML = "Feels " + this.feelsLike + "&deg;" + degreeLabel;
small.appendChild(feelsLike);
wrapper.appendChild(small);
}
return wrapper;
},
@@ -262,6 +295,10 @@ Module.register("currentweather",{
this.indoorTemperature = this.roundValue(payload);
this.updateDom(self.config.animationSpeed);
}
if (notification === "INDOOR_HUMIDITY") {
this.indoorHumidity = this.roundValue(payload);
this.updateDom(self.config.animationSpeed);
}
},
/* updateWeather(compliments)
@@ -343,13 +380,71 @@ Module.register("currentweather",{
this.humidity = parseFloat(data.main.humidity);
this.temperature = this.roundValue(data.main.temp);
this.feelsLike = 0;
if (this.config.useBeaufort){
this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
} else if (this.config.useKMPHwind) {
this.windSpeed = parseFloat((data.wind.speed * 60 * 60) / 1000).toFixed(0);
} else {
this.windSpeed = parseFloat(data.wind.speed).toFixed(0);
}
// ONLY WORKS IF TEMP IN C //
var windInMph = parseFloat(data.wind.speed * 2.23694);
var tempInF = 0;
switch (this.config.units){
case "metric": tempInF = 1.8 * this.temperature + 32;
break;
case "imperial": tempInF = this.temperature;
break;
case "default":
var tc = this.temperature - 273.15;
tempInF = 1.8 * tc + 32;
break;
}
if (windInMph > 3 && tempInF < 50){
// windchill
var windchillinF = Math.round(35.74+0.6215*tempInF-35.75*Math.pow(windInMph,0.16)+0.4275*tempInF*Math.pow(windInMph,0.16));
var windChillInC = (windchillinF - 32) * (5/9);
// this.feelsLike = windChillInC.toFixed(0);
switch (this.config.units){
case "metric": this.feelsLike = windChillInC.toFixed(0);
break;
case "imperial": this.feelsLike = windChillInF.toFixed(0);
break;
case "default":
var tc = windChillInC - 273.15;
this.feelsLike = tc.toFixed(0);
break;
}
} else if (tempInF > 80 && this.humidity > 40){
// heat index
var Hindex = -42.379 + 2.04901523*tempInF + 10.14333127*this.humidity
- 0.22475541*tempInF*this.humidity - 6.83783*Math.pow(10,-3)*tempInF*tempInF
- 5.481717*Math.pow(10,-2)*this.humidity*this.humidity
+ 1.22874*Math.pow(10,-3)*tempInF*tempInF*this.humidity
+ 8.5282*Math.pow(10,-4)*tempInF*this.humidity*this.humidity
- 1.99*Math.pow(10,-6)*tempInF*tempInF*this.humidity*this.humidity;
switch (this.config.units){
case "metric": this.feelsLike = Hindex.toFixed(0);
break;
case "imperial": this.feelsLike = parseFloat(Hindex * 1.8 + 32).toFixed(0);
break;
case "default":
var tc = Hindex - 273.15;
this.feelsLike = tc.toFixed(0);
break;
}
} else {
this.feelsLike = parseFloat(this.temperature).toFixed(0);
}
this.windDirection = this.deg2Cardinal(data.wind.deg);
this.windDeg = data.wind.deg;
this.weatherType = this.config.iconTable[data.weather[0].icon];
@@ -469,10 +564,11 @@ Module.register("currentweather",{
*
* argument temperature number - Temperature.
*
* return number - Rounded Temperature.
* return string - Rounded Temperature.
*/
roundValue: function(temperature) {
var decimals = this.config.roundTemp ? 0 : 1;
return parseFloat(temperature).toFixed(decimals);
}
});

View File

@@ -14,10 +14,11 @@ Module.register("helloworld",{
text: "Hello World!"
},
// Override dom generator.
getDom: function() {
var wrapper = document.createElement("div");
wrapper.innerHTML = this.config.text;
return wrapper;
getTemplate: function () {
return "helloworld.njk"
},
getTemplateData: function () {
return this.config
}
});

View File

@@ -0,0 +1,5 @@
<!--
Use ` | safe` to allow html tages within the text string.
https://mozilla.github.io/nunjucks/templating.html#autoescaping
-->
<div>{{text | safe}}</div>

View File

@@ -39,7 +39,7 @@ MagicMirror's [notification mechanism](https://github.com/MichMich/MagicMirror/t
| ----------------------- | -----------
| `ARTICLE_NEXT` | Shows the next news title (hiding the summary or previously fully displayed article)
| `ARTICLE_PREVIOUS` | Shows the previous news title (hiding the summary or previously fully displayed article)
| `ARTICLE_MORE_DETAILS` | When received the _first time_, shows the corresponding description of the currently displayed news title. <br> The module expects that the module's configuration option `showDescription` is set to `false` (default value). <br><br> When received a _second consecutive time_, shows the full news article in an IFRAME. <br> This requires that the news page can be embedded in an IFRAME, e.g. doesn't have the HTTP response header [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) set to e.g. `DENY`.
| `ARTICLE_MORE_DETAILS` | When received the _first time_, shows the corresponding description of the currently displayed news title. <br> The module expects that the module's configuration option `showDescription` is set to `false` (default value). <br><br> When received a _second consecutive time_, shows the full news article in an IFRAME. <br> This requires that the news page can be embedded in an IFRAME, e.g. doesn't have the HTTP response header [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) set to e.g. `DENY`.<br><br>When received the _next consecutive times_, reloads the page and scrolls down by `scrollLength` pixels to paginate through the article.
| `ARTICLE_LESS_DETAILS` | Hides the summary or full news article and only displays the news title of the currently viewed news item.
Note the payload of the sent notification event is ignored.
@@ -57,25 +57,29 @@ The third party [MMM-Gestures](https://github.com/thobach/MMM-Gestures) module s
The following properties can be configured:
| Option | Description
| ----------------- | -----------
| `feeds` | An array of feed urls that will be used as source. <br> More info about this object can be found below. <br> **Default value:** `[{ title: "New York Times", url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", encoding: "UTF-8" }]`
| `showSourceTitle` | Display the title of the source. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `showPublishDate` | Display the publish date of an headline. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `showDescription` | Display the description of an item. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `wrapTitle` | Wrap the title of the item to multiple lines. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `wrapDescription` | Wrap the description of the item to multiple lines. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `hideLoading` | Hide module instead of showing LOADING status. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `reloadInterval` | How often does the content needs to be fetched? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `300000` (5 minutes)
| `updateInterval` | How often do you want to display a new headline? (Milliseconds) <br><br> **Possible values:**`1000` - `60000` <br> **Default value:** `10000` (10 seconds)
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `2500` (2.5 seconds)
| `maxNewsItems` | Total amount of news items to cycle through. (0 for unlimited) <br><br> **Possible values:**`0` - `...` <br> **Default value:** `0`
| `ignoreOldItems` | Ignore news items that are outdated. <br><br> **Possible values:**`true` or `false <br> **Default value:** `false`
| `ignoreOlderThan` | How old should news items be before they are considered outdated? (Milliseconds) <br><br> **Possible values:**`1` - `...` <br> **Default value:** `86400000` (1 day)
| `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. <br><br> **Possible values:**`'title'`, `'description'`, `'both'`
| `startTags` | List the tags you would like to have removed at the beginning of the feed item <br><br> **Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
| `removeEndTags` | Remove specified tags from the **end** of an item's description and/or title. <br><br> **Possible values:**`'title'`, `'description'`, `'both'`
| `endTags` | List the tags you would like to have removed at the end of the feed item <br><br> **Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
| Option | Description
| ------------------ | -----------
| `feeds` | An array of feed urls that will be used as source. <br> More info about this object can be found below. <br> **Default value:** `[{ title: "New York Times", url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", encoding: "UTF-8" }]`<br>You can add `reloadInterval` option to set particular reloadInterval to a feed.
| `showSourceTitle` | Display the title of the source. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `showPublishDate` | Display the publish date of an headline. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `showDescription` | Display the description of an item. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `wrapTitle` | Wrap the title of the item to multiple lines. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `wrapDescription` | Wrap the description of the item to multiple lines. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `truncDescription` | Truncate description? <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `lengthDescription`| How many characters to be displayed for a truncated description? <br><br> **Possible values:** `1` - `500` <br> **Default value:** `400`
| `hideLoading` | Hide module instead of showing LOADING status. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `reloadInterval` | How often does the content needs to be fetched? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `300000` (5 minutes)
| `updateInterval` | How often do you want to display a new headline? (Milliseconds) <br><br> **Possible values:**`1000` - `60000` <br> **Default value:** `10000` (10 seconds)
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `2500` (2.5 seconds)
| `maxNewsItems` | Total amount of news items to cycle through. (0 for unlimited) <br><br> **Possible values:**`0` - `...` <br> **Default value:** `0`
| `ignoreOldItems` | Ignore news items that are outdated. <br><br> **Possible values:**`true` or `false` <br> **Default value:** `false`
| `ignoreOlderThan` | How old should news items be before they are considered outdated? (Milliseconds) <br><br> **Possible values:**`1` - `...` <br> **Default value:** `86400000` (1 day)
| `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. <br><br> **Possible values:**`'title'`, `'description'`, `'both'`
| `startTags` | List the tags you would like to have removed at the beginning of the feed item <br><br> **Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
| `removeEndTags` | Remove specified tags from the **end** of an item's description and/or title. <br><br> **Possible values:**`'title'`, `'description'`, `'both'`
| `endTags` | List the tags you would like to have removed at the end of the feed item <br><br> **Possible values:** `['TAG']` or `['TAG1','TAG2',...]`
| `prohibitedWords` | Remove news feed item if one of these words is found anywhere in the title (case insensitive and greedy matching) <br><br> **Possible values:** `['word']` or `['word1','word2',...]`
| `scrollLength` | Scrolls the full news article page by a given number of pixels when a `ARTICLE_MORE_DETAILS` notification is received and the full news article is already displayed.<br><br> **Possible values:** `1` or `10000` <br> **Default value:** `500`
The `feeds` property contains an array with multiple objects. These objects have the following properties:

View File

@@ -45,13 +45,13 @@ var Fetcher = function(url, reloadInterval, encoding) {
var title = item.title;
var description = item.description || item.summary || item.content || "";
var pubdate = item.pubdate || item.published || item.updated;
var pubdate = item.pubdate || item.published || item.updated || item["dc:date"];
var url = item.url || item.link || "";
if (title && pubdate) {
var regex = /(<([^>]+)>)/ig;
description = description.replace(regex, "");
description = description.toString().replace(regex, "");
items.push({
title: title,
@@ -61,17 +61,16 @@ 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);
}
});
parser.on("end", function() {
parser.on("end", function() {
//console.log("end parsing - " + url);
self.broadcastItems();
scheduleTimer();
});
@@ -83,7 +82,9 @@ var Fetcher = function(url, reloadInterval, encoding) {
nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
headers = {"User-Agent": "Mozilla/5.0 (Node.js "+ nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)"}
headers = {"User-Agent": "Mozilla/5.0 (Node.js "+ nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)",
"Cache-Control": "max-age=0, no-cache, no-store, must-revalidate",
"Pragma": "no-cache"}
request({uri: url, encoding: null, headers: headers})
.on("error", function(error) {

View File

@@ -23,8 +23,10 @@ Module.register("newsfeed",{
showDescription: false,
wrapTitle: true,
wrapDescription: true,
truncDescription: true,
lengthDescription: 400,
hideLoading: false,
reloadInterval: 5 * 60 * 1000, // every 5 minutes
reloadInterval: 5 * 60 * 1000, // every 5 minutes
updateInterval: 10 * 1000,
animationSpeed: 2.5 * 1000,
maxNewsItems: 0, // 0 for unlimited
@@ -33,8 +35,9 @@ Module.register("newsfeed",{
removeStartTags: "",
removeEndTags: "",
startTags: [],
endTags: []
endTags: [],
prohibitedWords: [],
scrollLength: 500
},
// Define required scripts.
@@ -60,6 +63,7 @@ Module.register("newsfeed",{
this.newsItems = [];
this.loaded = false;
this.activeItem = 0;
this.scrollPosition = 0;
this.registerFeeds();
@@ -168,7 +172,8 @@ Module.register("newsfeed",{
if (this.config.showDescription) {
var description = document.createElement("div");
description.className = "small light" + (!this.config.wrapDescription ? " no-wrap" : "");
description.innerHTML = this.newsItems[this.activeItem].description;
var txtDesc = this.newsItems[this.activeItem].description;
description.innerHTML = (this.config.truncDescription ? (txtDesc.length > this.config.lengthDescription ? txtDesc.substring(0, this.config.lengthDescription) + "..." : txtDesc) : txtDesc);
wrapper.appendChild(description);
}
@@ -176,12 +181,14 @@ Module.register("newsfeed",{
var fullArticle = document.createElement("iframe");
fullArticle.className = "";
fullArticle.style.width = "100%";
// very large height value to allow scrolling
fullArticle.height = "10000";
fullArticle.style.height = "10000";
fullArticle.style.top = "0";
fullArticle.style.left = "0";
fullArticle.style.position = "fixed";
fullArticle.height = window.innerHeight;
fullArticle.style.border = "none";
fullArticle.src = this.newsItems[this.activeItem].url;
fullArticle.src = typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href;
fullArticle.style.zIndex = 1;
wrapper.appendChild(fullArticle);
}
@@ -241,6 +248,18 @@ Module.register("newsfeed",{
if(this.config.maxNewsItems > 0) {
newsItems = newsItems.slice(0, this.config.maxNewsItems);
}
if(this.config.prohibitedWords.length > 0) {
newsItems = newsItems.filter(function(value){
for (var i=0; i < this.config.prohibitedWords.length; i++) {
if (value["title"].toLowerCase().indexOf(this.config.prohibitedWords[i].toLowerCase()) > -1) {
return false;
}
}
return true;
}, this);
}
this.newsItems = newsItems;
},
@@ -306,6 +325,10 @@ Module.register("newsfeed",{
resetDescrOrFullArticleAndTimer: function() {
this.config.showDescription = false;
this.config.showFullArticle = false;
this.scrollPosition = 0;
// reset bottom bar alignment
document.getElementsByClassName("region bottom bar")[0].style.bottom = "0";
document.getElementsByClassName("region bottom bar")[0].style.top = "inherit";
if(!timer){
this.scheduleUpdateInterval();
}
@@ -334,12 +357,27 @@ Module.register("newsfeed",{
}
// if "more details" is received the first time: show article summary, on second time show full article
else if(notification == "ARTICLE_MORE_DETAILS"){
this.config.showDescription = !this.config.showDescription;
this.config.showFullArticle = !this.config.showDescription;
clearInterval(timer);
timer = null;
Log.info(this.name + " - showing " + this.config.showDescription ? "article description" : "full article");
this.updateDom(100);
// full article is already showing, so scrolling down
if(this.config.showFullArticle == true){
this.scrollPosition += this.config.scrollLength;
window.scrollTo(0, this.scrollPosition);
Log.info(this.name + " - scrolling down");
Log.info(this.name + " - ARTICLE_MORE_DETAILS, scroll position: " + this.config.scrollLength);
}
// display full article
else {
this.config.showDescription = !this.config.showDescription;
this.config.showFullArticle = !this.config.showDescription;
// make bottom bar align to top to allow scrolling
if(this.config.showFullArticle == true){
document.getElementsByClassName("region bottom bar")[0].style.bottom = "inherit";
document.getElementsByClassName("region bottom bar")[0].style.top = "-90px";
}
clearInterval(timer);
timer = null;
Log.info(this.name + " - showing " + this.config.showDescription ? "article description" : "full article");
this.updateDom(100);
}
} else if(notification == "ARTICLE_LESS_DETAILS"){
this.resetDescrOrFullArticleAndTimer();
Log.info(this.name + " - showing only article titles again");

View File

@@ -36,7 +36,7 @@ module.exports = NodeHelper.create({
var url = feed.url || "";
var encoding = feed.encoding || "UTF-8";
var reloadInterval = config.reloadInterval || 5 * 60 * 1000;
var reloadInterval = feed.reloadInterval || config.reloadInterval || 5 * 60 * 1000;
if (!validUrl.isUri(url)) {
self.sendSocketNotification("INCORRECT_URL", url);

View File

@@ -64,7 +64,10 @@ module.exports = NodeHelper.create({
sg.git.fetch().status(function(err, data) {
data.module = sg.module;
if (!err) {
self.sendSocketNotification("STATUS", data);
sg.git.log({"-1": null}, function(err, data2) {
data.hash = data2.latest.hash;
self.sendSocketNotification("STATUS", data);
});
}
});
});

View File

@@ -11,11 +11,11 @@ Module.register("updatenotification", {
},
notificationReceived: function(notification, payload, sender) {
notificationReceived: function (notification, payload, sender) {
if (notification === "DOM_OBJECTS_CREATED") {
this.sendSocketNotification("CONFIG", this.config);
this.sendSocketNotification("MODULES", Module.definitions);
this.hide(0,{lockString: self.identifier});
this.hide(0, { lockString: self.identifier });
}
},
@@ -26,14 +26,25 @@ Module.register("updatenotification", {
}
},
updateUI: function() {
updateUI: function () {
var self = this;
if (this.status && this.status.behind > 0) {
self.updateDom(0);
self.show(1000, {lockString: self.identifier});
self.show(1000, { lockString: self.identifier });
}
},
diffLink: function(text) {
var localRef = this.status.hash;
var remoteRef = this.status.tracking.replace(/.*\//, "");
return "<a href=\"https://github.com/MichMich/MagicMirror/compare/"+localRef+"..."+remoteRef+"\" "+
"class=\"xsmall dimmed\" "+
"style=\"text-decoration: none;\" "+
"target=\"_blank\" >" +
text +
"</a>";
},
// Override dom generator.
getDom: function () {
var wrapper = document.createElement("div");
@@ -47,20 +58,26 @@ Module.register("updatenotification", {
icon.innerHTML = "&nbsp;";
message.appendChild(icon);
var subtextHtml = this.translate("UPDATE_INFO", {
COMMIT_COUNT: this.status.behind + " " + ((this.status.behind == 1) ? "commit" : "commits"),
BRANCH_NAME: this.status.current
});
var text = document.createElement("span");
if (this.status.module == "default") {
text.innerHTML = this.translate("UPDATE_NOTIFICATION");
subtextHtml = this.diffLink(subtextHtml);
} else {
text.innerHTML = this.translate("UPDATE_NOTIFICATION_MODULE").replace("MODULE_NAME", this.status.module);
text.innerHTML = this.translate("UPDATE_NOTIFICATION_MODULE", {
MODULE_NAME: this.status.module
});
}
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.innerHTML = subtextHtml;
subtext.className = "xsmall dimmed";
wrapper.appendChild(subtext);
}

Some files were not shown because too many files have changed in this diff Show More