diff --git a/.gitignore b/.gitignore index 67feae54..1e17ef8b 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ Temporary Items # Ignore all modules except the default modules. /modules/** +!/modules/default !/modules/default/** !/modules/README.md** diff --git a/.travis.yml b/.travis.yml index f2d34342..da3fb099 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,9 @@ node_js: - "5.1" before_script: - npm install grunt-cli -g -script: grunt +script: +- grunt +- npm test +cache: + directories: + - node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index b9551b79..706299cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,41 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [2.1.1] - Unreleased + +**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install` + +### Changed +- 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 + +### Added +- Add loaded function to modules, providing an async callback. +- Made default newsfeed module aware of gesture events from [MMM-Gestures](https://github.com/thobach/MMM-Gestures) +- Add use pm2 for manager process into Installer RaspberryPi script +- Russian Translation +- Afrikaans Translation +- Add postinstall script to notify user that MagicMirror installed successfully despite warnings from NPM. +- Init tests using mocha. +- Option to use RegExp in Calendar's titleReplace. +- Hungarian Translation. +- Icelandic Translation. +- Add use a script to prevent when is run by SSH session set DISPLAY enviroment. +- Enable ability to set configuration file by the enviroment variable called MM_CONFIG_FILE. + +### Fixed +- Update .gitignore to not ignore default modules folder. +- Remove white flash on boot up. +- Added `update` in Raspberry Pi installation script. +- Fix an issue where the analog clock looked scrambled. ([#611](https://github.com/MichMich/MagicMirror/issues/611)) +- If units is set to imperial, the showRainAmount option of weatherforecast will show the correct unit. +- Module currentWeather: check if temperature received from api is defined. + ## [2.1.0] - 2016-12-31 **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install` @@ -118,7 +153,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Added reference to Italian Translation. -- Added the missing NE translation to all languages. [#334](https://github.com/MichMich/MagicMirror/issues/344) +- Added the missing NE translation to all languages. [#344](https://github.com/MichMich/MagicMirror/issues/344) - Added proper User-Agent string to calendar call. ### Changed diff --git a/Gruntfile.js b/Gruntfile.js index ec3128ef..a3edb053 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -7,8 +7,9 @@ module.exports = function(grunt) { configFile: ".eslintrc.json" }, target: ["js/*.js", "modules/default/*.js", "modules/default/*/*.js", - "serveronly/*.js", "*.js", "!modules/default/alert/notificationFx.js", - "!modules/default/alert/modernizr.custom.js", "!modules/default/alert/classie.js" + "serveronly/*.js", "*.js", "tests/*/*.js", "!modules/default/alert/notificationFx.js", + "!modules/default/alert/modernizr.custom.js", "!modules/default/alert/classie.js", + "config/*", ] }, stylelint: { diff --git a/LICENSE.md b/LICENSE.md index d4765af2..09ac7e6f 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ The MIT License (MIT) ===================== -Copyright © 2016 Michael Teeuw +Copyright © 2016-2017 Michael Teeuw Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/README.md b/README.md index 7c5286dd..b13b5f54 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](http://elec - [Configuration](#configuration) - [Modules](#modules) - [Known Issues](#known-issues) -- [community](#community) +- [Community](#community) - [Contributing Guidelines](#contributing-guidelines) ## Usage @@ -37,7 +37,7 @@ curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installer ### Manual Installation 1. Download and install the latest Node.js version. -2. Clone the repository and check out the beta branch: `git clone https://github.com/MichMich/MagicMirror` +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` @@ -68,7 +68,7 @@ Type `git status` to see your changes, if there are any, you can reset them with ## Configuration -1. Duplicate `config/config.js.sample` to `config/config.js`. +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. The following properties can be configured: @@ -83,7 +83,7 @@ The following properties can be configured: | `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. | | `units` | The units that will be used in the default weather modules. Possible values are `metric` or `imperial`. The default is `metric`. | | `modules` | An array of active modules. **The array must contain objects. See the next table below for more information.** | -| `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (defaults `.width = 800` & `.height = 600`). Kiosk mode can be enabled by setting `.kiosk = true`, `.autoHideMenuBar = false`, `.fullscreen = false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). | +| `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (example: `electronOptions: { fullscreen: false, width: 800, height: 600 }`). Kiosk mode can be enabled by setting `.kiosk = true`, `.autoHideMenuBar = false`, `.fullscreen = false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). | Module configuration: diff --git a/config/config.js.sample b/config/config.js.sample index 913dbc43..eab22972 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -8,61 +8,61 @@ var config = { port: 8080, ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], - language: 'en', + language: "en", timeFormat: 24, - units: 'metric', + units: "metric", modules: [ { - module: 'alert', + module: "alert", }, { module: "updatenotification", position: "top_bar" }, { - module: 'clock', - position: 'top_left' + module: "clock", + position: "top_left" }, { - module: 'calendar', - header: 'US Holidays', - position: 'top_left', + module: "calendar", + header: "US Holidays", + position: "top_left", config: { calendars: [ { - symbol: 'calendar-check-o ', - url: 'webcal://www.calendarlabs.com/templates/ical/US-Holidays.ics' + symbol: "calendar-check-o ", + url: "webcal://www.calendarlabs.com/templates/ical/US-Holidays.ics" } ] } }, { - module: 'compliments', - position: 'lower_third' + module: "compliments", + position: "lower_third" }, { - module: 'currentweather', - position: 'top_right', + module: "currentweather", + position: "top_right", config: { - location: 'New York', - locationID: '', //ID from http://www.openweathermap.org - appid: 'YOUR_OPENWEATHER_API_KEY' + location: "New York", + locationID: "", //ID from http://www.openweathermap.org + appid: "YOUR_OPENWEATHER_API_KEY" } }, { - module: 'weatherforecast', - position: 'top_right', - header: 'Weather Forecast', + module: "weatherforecast", + position: "top_right", + header: "Weather Forecast", config: { - location: 'New York', - locationID: '5128581', //ID from http://www.openweathermap.org - appid: 'YOUR_OPENWEATHER_API_KEY' + location: "New York", + locationID: "5128581", //ID from http://www.openweathermap.org + appid: "YOUR_OPENWEATHER_API_KEY" } }, { - module: 'newsfeed', - position: 'bottom_bar', + module: "newsfeed", + position: "bottom_bar", config: { feeds: [ { @@ -79,4 +79,4 @@ var config = { }; /*************** DO NOT EDIT THE LINE BELOW ***************/ -if (typeof module !== 'undefined') {module.exports = config;} +if (typeof module !== "undefined") {module.exports = config;} diff --git a/css/main.css b/css/main.css index 5e63e596..f1c07fa0 100644 --- a/css/main.css +++ b/css/main.css @@ -135,6 +135,11 @@ sup { left: -60px; right: -60px; bottom: -60px; + pointer-events: none; +} + +.region.fullscreen * { + pointer-events: auto; } .region.right { diff --git a/installers/mm.sh b/installers/mm.sh new file mode 100755 index 00000000..cc6c4bb3 --- /dev/null +++ b/installers/mm.sh @@ -0,0 +1,2 @@ +cd ~/MagicMirror +DISPLAY=:0 npm start diff --git a/installers/pm2_MagicMirror.json b/installers/pm2_MagicMirror.json new file mode 100644 index 00000000..3f0b27bd --- /dev/null +++ b/installers/pm2_MagicMirror.json @@ -0,0 +1,7 @@ +{ + apps : [{ + name : "MagicMirror", + script : "/home/pi/MagicMirror/installers/mm.sh", + watch : ["/home/pi/MagicMirror/config/config.js"] + }] +} diff --git a/installers/postinstall/postinstall.sh b/installers/postinstall/postinstall.sh new file mode 100644 index 00000000..dc19df98 --- /dev/null +++ b/installers/postinstall/postinstall.sh @@ -0,0 +1,2 @@ +echo "\033[32mMagicMirror installation successful!" +exit 0 diff --git a/installers/raspberry.sh b/installers/raspberry.sh index cd995a1e..718f78b6 100644 --- a/installers/raspberry.sh +++ b/installers/raspberry.sh @@ -36,6 +36,10 @@ fi function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; } function command_exists () { type "$1" &> /dev/null ;} +# Update before first apt-get +echo -e "\e[96mUpdating packages ...\e[90m" +sudo apt-get update || echo -e "\e[91mUpdate failed, carrying on installation ...\e[90m" + # Installing helper tools echo -e "\e[96mInstalling helper tools ...\e[90m" sudo apt-get install curl wget git build-essential unzip || exit @@ -113,6 +117,9 @@ else exit; fi +# Use sample config for start MagicMirror +cp config/config.js.sample config/config.js + # Check if plymouth is installed (default with PIXEL desktop environment), then install custom splashscreen. echo -e "\e[96mCheck plymouth installation ...\e[0m" if command_exists plymouth; then @@ -141,6 +148,16 @@ else echo -e "\e[93mplymouth is not installed.\e[0m"; fi +# Use pm2 control like a service MagicMirror +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" + pm2 start ~/MagicMirror/installers/pm2_MagicMirror.json + pm2 save +fi + echo " " echo -e "\e[92mWe're ready! Run \e[1m\e[97mDISPLAY=:0 npm start\e[0m\e[92m from the ~/MagicMirror directory to start your MagicMirror.\e[0m" echo " " diff --git a/js/app.js b/js/app.js index ba6cd1a9..9f992b29 100644 --- a/js/app.js +++ b/js/app.js @@ -17,6 +17,10 @@ console.log("Starting MagicMirror: v" + global.version); // global absolute root path global.root_path = path.resolve(__dirname + "/../"); +if (process.env.MM_CONFIG_FILE) { + global.configuration_file = process.env.MM_CONFIG_FILE; +} + // The next part is here to prevent a major exception when there // is no internet connection. This could probable be solved better. process.on("uncaughtException", function (err) { @@ -41,7 +45,14 @@ var App = function() { var loadConfig = function(callback) { console.log("Loading config ..."); var defaults = require(__dirname + "/defaults.js"); + + // For this check proposed to TestSuite + // https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8 var configFilename = path.resolve(global.root_path + "/config/config.js"); + if (typeof(global.configuration_file) === "undefined" ) { + configFilename = path.resolve(global.configuration_file); + } + try { fs.accessSync(configFilename, fs.F_OK); var c = require(configFilename); @@ -66,7 +77,7 @@ var App = function() { * * argument module string - The name of the module (including subpath). */ - var loadModule = function(module) { + var loadModule = function(module, callback) { var elements = module.split("/"); var moduleName = elements[elements.length - 1]; @@ -103,6 +114,10 @@ var App = function() { m.setName(moduleName); m.setPath(path.resolve(moduleFolder)); nodeHelpers.push(m); + + m.loaded(callback); + } else { + callback(); } }; @@ -111,14 +126,24 @@ var App = function() { * * argument module string - The name of the module (including subpath). */ - var loadModules = function(modules) { + var loadModules = function(modules, callback) { console.log("Loading module helpers ..."); - for (var m in modules) { - loadModule(modules[m]); - } + var loadNextModule = function() { + if (modules.length > 0) { + var nextModule = modules[0]; + loadModule(nextModule, function() { + modules = modules.slice(1); + loadNextModule(); + }); + } else { + // All modules are loaded + console.log("All module helpers loaded."); + callback(); + } + }; - console.log("All module helpers loaded."); + loadNextModule(); }; /* cmpVersions(a,b) @@ -164,24 +189,24 @@ var App = function() { } } - loadModules(modules); + loadModules(modules, function() { + var server = new Server(config, function(app, io) { + console.log("Server started ..."); - var server = new Server(config, function(app, io) { - console.log("Server started ..."); + for (var h in nodeHelpers) { + var nodeHelper = nodeHelpers[h]; + nodeHelper.setExpressApp(app); + nodeHelper.setSocketIO(io); + nodeHelper.start(); + } - for (var h in nodeHelpers) { - var nodeHelper = nodeHelpers[h]; - nodeHelper.setExpressApp(app); - nodeHelper.setSocketIO(io); - nodeHelper.start(); - } + console.log("Sockets connected & modules started ..."); - console.log("Sockets connected & modules started ..."); - - if (typeof callback === "function") { - callback(config); - } + if (typeof callback === "function") { + callback(config); + } + }); }); }); }; diff --git a/js/electron.js b/js/electron.js index 173abe68..1f16092b 100644 --- a/js/electron.js +++ b/js/electron.js @@ -28,7 +28,8 @@ function createWindow() { webPreferences: { nodeIntegration: false, zoomFactor: config.zoom - } + }, + backgroundColor: "#000000" } // DEPRECATED: "kioskmode" backwards compatibility, to be removed diff --git a/js/module.js b/js/module.js index 67305a9c..dfd5f2bc 100644 --- a/js/module.js +++ b/js/module.js @@ -415,3 +415,11 @@ 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 + } +} diff --git a/modules/README.md b/modules/README.md index 42a31dfa..03664b15 100644 --- a/modules/README.md +++ b/modules/README.md @@ -96,6 +96,21 @@ requiresVersion: "2.1.0", ####`init()` This method is called when a module gets instantiated. In most cases you do not need to subclass this method. +####`loaded(callback)` + +*Introduced in version: 2.1.1.* + +This method is called when a module is loaded. Subsequent modules in the config are not yet loaded. The `callback` function MUST be called when the module is done loading. In most cases you do not need to subclass this method. + +**Example:** +````javascript +loaded: function(callback) { + this.finishLoading(); + Log.log(this.name + ' is loaded!'); + callback(); +} +```` + ####`start()` This method is called when all modules are loaded an the system is ready to boot up. Keep in mind that the dom object for the module is not yet created. The start method is a perfect place to define any additional module properties: diff --git a/modules/default/alert/README.md b/modules/default/alert/README.md index d566313d..58be0570 100644 --- a/modules/default/alert/README.md +++ b/modules/default/alert/README.md @@ -7,7 +7,7 @@ To use this module, add it to the modules array in the config/config.js file: ``` modules: [ { - module: 'alert', + module: "alert", config: { // The config property is optional. // See 'Configuration options' for more information. @@ -21,52 +21,13 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
effectThe animation effect to use for notifications.
-
Possible values: scale slide genie jelly flip exploader bouncyflip -
Default value: slide -
alert_effectThe animation effect to use for alerts.
-
Possible values: scale slide genie jelly flip exploader bouncyflip -
Default value: jelly -
display_timeTime a notification is displayed in milliseconds.
-
Possible values: int -
Default value: 3500 -
positionPosition where the notifications should be displayed.
-
Possible values: left center right -
Default value: center -
welcome_messageMessage shown at startup.
-
Possible values: string false -
Default value: false (no message at startup) -
+| Option | Description +| ----------------- | ----------- +| `effect` | The animation effect to use for notifications.

**Possible values:** `scale` `slide` `genie` `jelly` `flip` `exploader` `bouncyflip`
**Default value:** `slide` +| `alert_effect` | The animation effect to use for alerts.

**Possible values:** `scale` `slide` `genie` `jelly` `flip` `exploader` `bouncyflip`
**Default value:** `jelly` +| `display_time` | Time a notification is displayed in milliseconds.

**Possible values:** `int`
**Default value:** `3500` +| `position` | Position where the notifications should be displayed.

**Possible values:** `left` `center` `right`
**Default value:** `center` +| `welcome_message` | Message shown at startup.

**Possible values:** `string` `false`
**Default value:** `false` (no message at startup) ## Developer notes @@ -82,83 +43,21 @@ self.sendNotification("SHOW_ALERT", {}); ``` ### Notification params - - - - - - - - - - - - - - - - - - -
OptionDescription
titleThe title of the notification.
-
Possible values: text or html -
messageThe message of the notification.
-
Possible values: text or html -
+| Option | Description +| --------- | ----------- +| `title` | The title of the notification.

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

**Possible values:** `text` or `html` + ### Alert params - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
titleThe title of the alert.
-
Possible values: text or html -
messageThe message of the alert.
-
Possible values: text or html -
imageUrl (optional)Image to show in the alert
-
Possible values: url path -
Default value: none -
imageFA (optional)Font Awesome icon to show in the alert
-
Possible values: See Font Awsome website. -
Default value: none -
imageHeight (optional even with imageUrl set)Height of the image
-
Possible values: intpx -
Default value: 80px -
timer (optional)How long the alert should stay visible in ms. -
Important: If you do not use the timer, it is your duty to hide the alert by using self.sendNotification("HIDE_ALERT");!
-
Possible values: int float -
Default value: none -
+| Option | Description +| ----------------------------------------------- | ----------- +| `title` | The title of the alert.

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

**Possible values:** `text` or `html` +| `imageUrl` (optional) | Image to show in the alert

**Possible values:** `url` `path`
**Default value:** `none` +| `imageFA` (optional) | Font Awesome icon to show in the alert

**Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website.
**Default value:** `none` +| `imageHeight` (optional even with imageUrl set) | Height of the image

**Possible values:** `intpx`
**Default value:** `80px` +| `timer` (optional) | How long the alert should stay visible in ms.
**Important:** If you do not use the `timer`, it is your duty to hide the alert by using `self.sendNotification("HIDE_ALERT");`!

**Possible values:** `int` `float`
**Default value:** `none` ## Open Source Licenses ###[NotificationStyles](https://github.com/codrops/NotificationStyles) diff --git a/modules/default/alert/translations/hu.json b/modules/default/alert/translations/hu.json new file mode 100644 index 00000000..be618365 --- /dev/null +++ b/modules/default/alert/translations/hu.json @@ -0,0 +1,4 @@ +{ + "sysTitle": "MagicMirror értesítés", + "welcome": "Üdvözöljük, indulás sikeres!" +} diff --git a/modules/default/alert/translations/ru.json b/modules/default/alert/translations/ru.json new file mode 100644 index 00000000..ef7ee708 --- /dev/null +++ b/modules/default/alert/translations/ru.json @@ -0,0 +1,4 @@ +{ + "sysTitle": "MagicMirror Уведомление", + "welcome": "Добро пожаловать, старт был успешным!"" +} diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index c4c330b8..a40d78d1 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -8,8 +8,8 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'calendar', - position: 'top_left', // This can be any of the regions. Best results in left or right regions. + module: "calendar", + position: "top_left", // This can be any of the regions. Best results in left or right regions. config: { // The config property is optional. // If no config is set, an example calendar is shown. @@ -24,152 +24,26 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
maximumEntriesThe maximum number of events shown.
-
Possible values: 0 - 100 -
Default value: 10 -
maximumNumberOfDaysThe maximum number of days in the future.
-
Default value: 365 -
displaySymbolDisplay a symbol in front of an entry.
-
Possible values: true or false -
Default value: true -
defaultSymbolThe default symbol.
-
Possible values: See Font Awsome website. -
Default value: calendar -
maxTitleLengthThe maximum title length.
-
Possible values: 10 - 50 -
Default value: 25 -
fetchIntervalHow often does the content needs to be fetched? (Milliseconds)
-
Possible values: 1000 - 86400000 -
Default value: 300000 (5 minutes) -
animationSpeedSpeed of the update animation. (Milliseconds)
-
Possible values:0 - 5000 -
Default value: 2000 (2 seconds) -
fadeFade the future events to black. (Gradient)
-
Possible values: true or false -
Default value: true -
fadePointWhere to start fade?
-
Possible values: 0 (top of the list) - 1 (bottom of list) -
Default value: 0.25 -
calendarsThe list of calendars.
-
Possible values: An array, see calendar configuration below. -
Default value: An example calendar. -
titleReplaceAn object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title.
-
Example:
- - titleReplace: {'Birthday of ' : '', 'foo':'bar'} - -
Default value: - - { - "De verjaardag van ": "", - "'s birthday": "" - } - -
displayRepeatingCountTitleShow count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary")
-
Possible values: true or false -
Default value: false -
dateFormatFormat to use for the date of events (when using absolute dates)
-
Possible values: See Moment.js formats -
Default value: MMM Do (e.g. Jan 18th) -
timeFormatDisplay event times as absolute dates, or relative time
-
Possible values: absolute or relative -
Default value: relative -
getRelativeHow much time (in hours) should be left until calendar events start getting relative?
-
Possible values: 0 (events stay absolute) - 48 (48 hours before the event starts) -
Default value: 6 -
urgencyWhen 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
-
Possible values: a positive integer representing the number of days for which you want a relative date, for example 7 (for 7 days)
-
Default value: 7 -
broadcastEventsIf this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: CALENDAR_EVENTS. The event objects are stored in an array and contain the following fields: title, startDate, endDate, fullDayEvent, location and geo.
-
Possible values: true, false
-
Default value: true -
hidePrivateHides private calendar events.
-
Possible values: true or false -
Default value: false -
+| Option | Description +| ---------------------------- | ----------- +| `maximumEntries` | The maximum number of events shown. / **Possible values:** `0` - `100`
**Default value:** `10` +| `maximumNumberOfDays` | The maximum number of days in the future.

**Default value:** `365` +| `displaySymbol` | Display a symbol in front of an entry.

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

**Possible values:** See [Font Awsome](http://fontawesome.io/icons/) website.
**Default value:** `calendar` +| `maxTitleLength` | The maximum title length.

**Possible values:** `10` - `50`
**Default value:** `25` +| `fetchInterval` | How often does the content needs to be fetched? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `300000` (5 minutes) +| `animationSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `2000` (2 seconds) +| `fade` | Fade the future events to black. (Gradient)

**Possible values:** `true` or `false`
**Default value:** `true` +| `fadePoint` | Where to start fade?

**Possible values:** `0` (top of the list) - `1` (bottom of list)
**Default value:** `0.25` +| `calendars` | The list of calendars.

**Possible values:** An array, see _calendar configuration_ below.
**Default value:** _An example calendar._ +| `titleReplace` | An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title.

**Example:** `{'Birthday of ' : '', 'foo':'bar'}`
**Default value:** `{ "De verjaardag van ": "", "'s birthday": "" }` +| `displayRepeatingCountTitle` | Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary")

**Possible values:** `true` or `false`
**Default value:** `false` +| `dateFormat` | Format to use for the date of events (when using absolute dates)

**Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/)
**Default value:** `MMM Do` (e.g. Jan 18th) +| `timeFormat` | Display event times as absolute dates, or relative time

**Possible values:** `absolute` or `relative`
**Default value:** `relative` +| `getRelative` | How much time (in hours) should be left until calendar events start getting relative?

**Possible values:** `0` (events stay absolute) - `48` (48 hours before the event starts)
**Default value:** `6` +| `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

**Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days)

**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`.

**Possible values:** `true`, `false`

**Default value:** `true` +| `hidePrivate` | Hides private calendar events.

**Possible values:** `true` or `false`
**Default value:** `false` ### Calendar configuration @@ -179,7 +53,7 @@ The `colored` property gives the option for an individual color for each calenda #### Default value: ````javascript config: { - colored: false, + colored: false, calendars: [ { url: 'http://www.calendarlabs.com/templates/ical/US-Holidays.ics', @@ -212,12 +86,13 @@ config: {
Possible values: See Font Awesome website. - + color The font color of an event from this calendar. This property should be set if the config is set to colored: true.

Possible values: HEX, RGB or RGBA values (#efefef, rgb(242,242,242), rgba(242,242,242,0.5)). + repeatingCountTitle The count title for yearly repating events in this calendar.
diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index d74d1f96..1ca137ca 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -390,7 +390,7 @@ Module.register("calendar", { /* capFirst(string) * Capitalize the first letter of a string - * Eeturn capitalized string + * Return capitalized string */ capFirst: function (string) { @@ -409,6 +409,13 @@ Module.register("calendar", { titleTransform: function (title) { for (var needle in this.config.titleReplace) { var replacement = this.config.titleReplace[needle]; + + var regParts = needle.match(/^\/(.+)\/([gim]*)$/); + if (regParts) { + // the parsed pattern is a regexp. + needle = new RegExp(regParts[1], regParts[2]); + } + title = title.replace(needle, replacement); } diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index a1b8db09..cc511659 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -12,7 +12,6 @@ var CalendarFetcher = require("./calendarfetcher.js"); module.exports = NodeHelper.create({ // Override start method. start: function() { - var self = this; var events = []; this.fetchers = []; diff --git a/modules/default/calendar/vendor/ical.js/ical.js b/modules/default/calendar/vendor/ical.js/ical.js index 252e426b..f60c5357 100644 --- a/modules/default/calendar/vendor/ical.js/ical.js +++ b/modules/default/calendar/vendor/ical.js/ical.js @@ -90,7 +90,6 @@ return dt } - var dateParam = function(name){ return function(val, params, curr){ @@ -143,6 +142,16 @@ } } + var exdateParam = function(name){ + return function(val, params, curr){ + var date = dateParam(name)(val, params, curr); + if (date.exdates === undefined) { + date.exdates = []; + } + date.exdates.push(date.exdate); + return date; + } + } var geoParam = function(name){ return function(val, params, curr){ @@ -240,6 +249,7 @@ , 'LOCATION' : storeParam('location') , 'DTSTART' : dateParam('start') , 'DTEND' : dateParam('end') + , 'EXDATE' : exdateParam('exdate') ,' CLASS' : storeParam('class') , 'TRANSP' : storeParam('transparency') , 'GEO' : geoParam('geo') diff --git a/modules/default/calendar/vendor/ical.js/node-ical.js b/modules/default/calendar/vendor/ical.js/node-ical.js index 2f6ef3ef..c954e722 100644 --- a/modules/default/calendar/vendor/ical.js/node-ical.js +++ b/modules/default/calendar/vendor/ical.js/node-ical.js @@ -17,7 +17,8 @@ exports.parseFile = function(filename){ } -var rrule = require('rrule').RRule +var rrule = require('rrule-alt').RRule +var rrulestr = rrule.rrulestr ical.objectHandlers['RRULE'] = function(val, params, curr, stack, line){ curr.rrule = line; @@ -26,7 +27,7 @@ ical.objectHandlers['RRULE'] = function(val, params, curr, stack, line){ var originalEnd = ical.objectHandlers['END']; ical.objectHandlers['END'] = function(val, params, curr, stack){ if (curr.rrule) { - var rule = curr.rrule.replace('RRULE:', ''); + var rule = curr.rrule; if (rule.indexOf('DTSTART') === -1) { if (curr.start.length === 8) { @@ -36,10 +37,14 @@ ical.objectHandlers['END'] = function(val, params, curr, stack){ } } - rule += ';DTSTART=' + curr.start.toISOString().replace(/[-:]/g, ''); + rule += ' DTSTART:' + curr.start.toISOString().replace(/[-:]/g, ''); rule = rule.replace(/\.[0-9]{3}/, ''); } - curr.rrule = rrule.fromString(rule); + for (var i in curr.exdates) { + rule += ' EXDATE:' + curr.exdates[i].toISOString().replace(/[-:]/g, ''); + rule = rule.replace(/\.[0-9]{3}/, ''); + } + curr.rrule = rrulestr(rule); } return originalEnd.call(this, val, params, curr, stack); } diff --git a/modules/default/clock/README.md b/modules/default/clock/README.md index 76a979d4..5570ff5a 100644 --- a/modules/default/clock/README.md +++ b/modules/default/clock/README.md @@ -8,8 +8,8 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'clock', - position: 'top_left', // This can be any of the regions. + module: "clock", + position: "top_left", // This can be any of the regions. config: { // The config property is optional. // See 'Configuration options' for more information. @@ -22,106 +22,18 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
timeFormatUse 12 or 24 hour format.
-
Possible values: 12 or 24 -
Default value: uses value of config.timeFormat -
displaySecondsDisplay seconds.
-
Possible values: true or false -
Default value: true -
showPeriodShow the period (am/pm) with 12 hour format.
-
Possible values: true or false -
Default value: true -
showPeriodUpperShow the period (AM/PM) with 12 hour format as uppercase.
-
Possible values: true or false -
Default value: false -
clockBoldRemove the colon and bold the minutes to make a more modern look.
-
Possible values: true or false -
Default value: false -
showDateTurn off or on the Date section.
-
Possible values: true or false -
Default value: true -
displayTypeDisplay a digital clock, analog clock, or both together.
-
Possible values: digital, analog, or both -
Default value: digital -
analogSizeSpecific to the analog clock. Defines how large the analog display is.
-
Possible values: A positive number of pixels -
Default value: 200px -
analogFaceSpecific to the analog clock. Specifies which clock face to use.
-
Possible values: simple for a simple border, none for no face or border, or face-### (where ### is currently a value between 001 and 012, inclusive) -
Default value: simple -
secondsColorSpecific to the analog clock. Specifies what color to make the 'seconds' hand.
-
Possible values: any HTML RGB Color -
Default value: #888888 -
analogPlacementSpecific to the analog clock. (requires displayType set to 'both') Specifies where the analog clock is in relation to the digital clock
-
Possible values: top, right, bottom, or left -
Default value: bottom -
analogShowDateSpecific to the analog clock. If the clock is used as a separate module and set to analog only, this configures whether a date is also displayed with the clock.
-
Possible values: false, top, or bottom -
Default value: top -
timezoneSpecific a timezone to show clock.
-
Possible examples values: America/New_York, America/Santiago, Etc/GMT+10 -
Default value: none -
+| Option | Description +| ----------------- | ----------- +| `timeFormat` | Use 12 or 24 hour format.

**Possible values:** `12` or `24`
**Default value:** uses value of _config.timeFormat_ +| `displaySeconds` | Display seconds.

**Possible values:** `true` or `false`
**Default value:** `true` +| `showPeriod` | Show the period (am/pm) with 12 hour format.

**Possible values:** `true` or `false`
**Default value:** `true` +| `showPeriodUpper` | Show the period (AM/PM) with 12 hour format as uppercase.

**Possible values:** `true` or `false`
**Default value:** `false` +| `clockBold` | Remove the colon and bold the minutes to make a more modern look.

**Possible values:** `true` or `false`
**Default value:** `false` +| `showDate` | Turn off or on the Date section.

**Possible values:** `true` or `false`
**Default value:** `true` +| `displayType` | Display a digital clock, analog clock, or both together.

**Possible values:** `digital`, `analog`, or `both`
**Default value:** `digital` +| `analogSize` | **Specific to the analog clock.** Defines how large the analog display is.

**Possible values:** A positive number of pixels`
**Default value:** `200px` +| `analogFace` | **Specific to the analog clock.** Specifies which clock face to use.

**Possible values:** `simple` for a simple border, `none` for no face or border, or `face-###` (where ### is currently a value between 001 and 012, inclusive)
**Default value:** `simple` +| `secondsColor` | **Specific to the analog clock.** Specifies what color to make the 'seconds' hand.

**Possible values:** `any HTML RGB Color`
**Default value:** `#888888` +| `analogPlacement` | **Specific to the analog clock. _(requires displayType set to `'both'`)_** Specifies where the analog clock is in relation to the digital clock

**Possible values:** `top`, `right`, `bottom`, or `left`
**Default value:** `bottom` +| `analogShowDate` | **Specific to the analog clock.** If the clock is used as a separate module and set to analog only, this configures whether a date is also displayed with the clock.

**Possible values:** `false`, `top`, or `bottom`
**Default value:** `top` +| `timezone` | Specific a timezone to show clock.

**Possible examples values:** `America/New_York`, `America/Santiago`, `Etc/GMT+10`
**Default value:** `none` diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index c84c133e..1882c52e 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -134,6 +134,10 @@ Module.register("clock",{ if (this.config.analogFace != "" && this.config.analogFace != "simple" && this.config.analogFace != "none") { clockCircle.style.background = "url("+ this.data.path + "faces/" + this.config.analogFace + ".svg)"; clockCircle.style.backgroundSize = "100%"; + + // The following line solves issue: https://github.com/MichMich/MagicMirror/issues/611 + clockCircle.style.border = "1px solid black"; + } else if (this.config.analogFace != "none") { clockCircle.style.border = "2px solid white"; } diff --git a/modules/default/compliments/README.md b/modules/default/compliments/README.md index 430c4fbf..8ef9e2fb 100644 --- a/modules/default/compliments/README.md +++ b/modules/default/compliments/README.md @@ -8,8 +8,8 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'compliments', - position: 'lower_third', // This can be any of the regions. + module: "compliments", + position: "lower_third", // This can be any of the regions. // Best results in one of the middle regions like: lower_third config: { // The config property is optional. @@ -25,48 +25,12 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
updateIntervalHow often does the compliment have to change? (Milliseconds)
-
Possible values: 1000 - 86400000 -
Default value: 30000 (30 seconds) -
fadeSpeedSpeed of the update animation. (Milliseconds)
-
Possible values:0 - 5000 -
Default value: 4000 (4 seconds) -
complimentsThe list of compliments.
-
Possible values: An object with three arrays: morning, afternoon andevening. See compliment configuration below. -
Default value: See compliment configuration below. -
remoteFileExternal file from which to load the compliments
-
Possible values:Path to a JSON file containing compliments, configured - as per the value of the compliments configuration (see below). An object with three arrays: - morning, afternoon and evening. - compliments.json -
Default value: null (Do not load from file) -
+| Option | Description +| ---------------- | ----------- +| `updateInterval` | How often does the compliment have to change? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `30000` (30 seconds) +| `fadeSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `4000` (4 seconds) +| `compliments` | The list of compliments.

**Possible values:** An object with three arrays: `morning`, `afternoon` and`evening`. See _compliment configuration_ below.
**Default value:** See _compliment configuration_ below. +| `remoteFile` | External file from which to load the compliments

**Possible values:** Path to a JSON file containing compliments, configured as per the value of the _compliments configuration_ (see below). An object with three arrays: `morning`, `afternoon` and `evening`. - `compliments.json`
**Default value:** `null` (Do not load from file) ### Compliment configuration @@ -74,36 +38,36 @@ The `compliments` property contains an object with three arrays: morningday_sunny -* day_cloudy -* cloudy -* cloudy_windy -* showers -* rain -* thunderstorm -* snow -* fog -* night_clear -* night_cloudy -* night_showers -* night_rain -* night_thunderstorm -* night_snow -* night_alt_cloudy_windy +* `day_sunny` +* `day_cloudy` +* `cloudy` +* `cloudy_windy` +* `showers` +* `rain` +* `thunderstorm` +* `snow` +* `fog` +* `night_clear` +* `night_cloudy` +* `night_showers` +* `night_rain` +* `night_thunderstorm` +* `night_snow` +* `night_alt_cloudy_windy` #### Example use with currentweather module ````javascript config: { compliments: { day_sunny: [ - 'Today is a sunny day', - 'It\'s a beautiful day' + "Today is a sunny day", + "It's a beautiful day" ], snow: [ - 'Snowball battle!' + "Snowball battle!" ], rain: [ - 'Don\'t forget your umbrella' + "Don't forget your umbrella" ] } } @@ -115,19 +79,19 @@ config: { config: { compliments: { morning: [ - 'Good morning, handsome!', - 'Enjoy your day!', - 'How was your sleep?' + "Good morning, handsome!", + "Enjoy your day!", + "How was your sleep?" ], afternoon: [ - 'Hello, beauty!', + "Hello, beauty!", 'You look sexy!', - 'Looking good today!' + "Looking good today!" ], evening: [ - 'Wow, you look hot!', - 'You look nice!', - 'Hi, sexy!' + "Wow, you look hot!", + "You look nice!", + "Hi, sexy!" ] } } diff --git a/modules/default/currentweather/README.md b/modules/default/currentweather/README.md index ccef543c..65913d82 100644 --- a/modules/default/currentweather/README.md +++ b/modules/default/currentweather/README.md @@ -8,14 +8,14 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'currentweather', - position: 'top_right', // This can be any of the regions. + module: "currentweather", + position: "top_right", // This can be any of the regions. // Best results in left or right regions. config: { // See 'Configuration options' for more information. - location: 'Amsterdam,Netherlands', - locationID: '', //Location ID from http://openweathermap.org/help/city_list.txt - appid: 'abcde12345abcde12345abcde12345ab' //openweathermap.org API key. + location: "Amsterdam,Netherlands", + locationID: "", //Location ID from http://openweathermap.org/help/city_list.txt + appid: "abcde12345abcde12345abcde12345ab" //openweathermap.org API key. } } ] @@ -26,189 +26,52 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
locationThe location used for weather information.
-
Example: 'Amsterdam,Netherlands' -
Default value: false

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

- Note: When the location and locationID are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. -
appidThe OpenWeatherMap API key, which can be obtained by creating an OpenWeatherMap account.
-
This value is REQUIRED -
unitsWhat units to use. Specified by config.js
-
Possible values: config.units = Specified by config.js, default = Kelvin, metric = Celsius, imperial =Fahrenheit -
Default value: config.units -
roundTempRound temperature value to nearest integer.
-
Possible values: true (round to integer) or false (display exact value with decimal point) -
Default value: false -
updateIntervalHow often does the content needs to be fetched? (Milliseconds)
-
Possible values: 1000 - 86400000 -
Default value: 600000 (10 minutes) -
animationSpeedSpeed of the update animation. (Milliseconds)
-
Possible values:0 - 5000 -
Default value: 1000 (1 second) -
timeFormatUse 12 or 24 hour format.
-
Possible values: 12 or 24 -
Default value: uses value of config.timeFormat -
showPeriodShow the period (am/pm) with 12 hour format
-
Possible values: true or false -
Default value: true -
showPeriodUpperShow the period (AM/PM) with 12 hour format as uppercase
-
Possible values: true or false -
Default value: false -
showWindDirectionShow the wind direction next to the wind speed.
-
Possible values: true or false -
Default value: true -
showHumidityShow the current humidity
-
Possible values: true or false -
Default value: false -
onlyTempShow only current Temperature and weather icon.
-
Possible values: true or false -
Default value: false -
useBeaufortPick between using the Beaufort scale for wind speed or using the default units.
-
Possible values: true or false -
Default value: true -
langThe language of the days.
-
Possible values: en, nl, ru, etc ... -
Default value: uses value of config.language -
initialLoadDelayThe 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)
-
Possible values: 1000 - 5000 -
Default value: 0 -
retryDelayThe delay before retrying after a request failure. (Milliseconds)
-
Possible values: 1000 - 60000 -
Default value: 2500 -
apiVersionThe OpenWeatherMap API version to use.
-
Default value: 2.5 -
apiBaseThe OpenWeatherMap base URL.
-
Default value: 'http://api.openweathermap.org/data/' -
weatherEndpointThe OpenWeatherMap API endPoint.
-
Default value: 'weather' -
appendLocationNameToHeaderIf set to true, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather.
-
Default value: true -
calendarClassThe class for the calender module to base the event based weather information on.
-
Default value: 'calendar' -
iconTableThe conversion table to convert the weather conditions to weather-icons.
-
Default value: iconTable: { - '01d':'wi-day-sunny', - '02d':'wi-day-cloudy', - '03d':'wi-cloudy', - '04d':'wi-cloudy-windy', - '09d':'wi-showers', - '10d':'wi-rain', - '11d':'wi-thunderstorm', - '13d':'wi-snow', - '50d':'wi-fog', - '01n':'wi-night-clear', - '02n':'wi-night-cloudy', - '03n':'wi-night-cloudy', - '04n':'wi-night-cloudy', - '09n':'wi-night-showers', - '10n':'wi-night-rain', - '11n':'wi-night-thunderstorm', - '13n':'wi-night-snow', - '50n':'wi-night-alt-cloudy-windy' - } -
+| Option | Description +| ---------------------------- | ----------- +| `location` | The location used for weather information.

**Example:** `'Amsterdam,Netherlands'`
**Default value:** `false`

**Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. +| `locationID` | Location ID from [OpenWeatherMap](http://openweathermap.org/help/city_list.txt) **This will override anything you put in location.**
Leave blank if you want to use location.
**Example:** `1234567`
**Default value:** `false`

**Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. +| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account.

This value is **REQUIRED** +| `units` | What units to use. Specified by config.js

**Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit
**Default value:** `config.units` +| `roundTemp` | Round temperature value to nearest integer.

**Possible values:** `true` (round to integer) or `false` (display exact value with decimal point)
**Default value:** `false` +| `updateInterval` | How often does the content needs to be fetched? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `600000` (10 minutes) +| `animationSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `1000` (1 second) +| `timeFormat` | Use 12 or 24 hour format.

**Possible values:** `12` or `24`
**Default value:** uses value of _config.timeFormat_ +| `showPeriod` | Show the period (am/pm) with 12 hour format

**Possible values:** `true` or `false`
**Default value:** `true` +| `showPeriodUpper` | Show the period (AM/PM) with 12 hour format as uppercase

**Possible values:** `true` or `false`
**Default value:** `false` +| `showWindDirection` | Show the wind direction next to the wind speed.

**Possible values:** `true` or `false`
**Default value:** `true` +| `showHumidity` | Show the current humidity

**Possible values:** `true` or `false`
**Default value:** `false` +| `onlyTemp` | Show only current Temperature and weather icon.

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

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

**Possible values:** `en`, `nl`, `ru`, etc ...
**Default value:** uses value of _config.language_ +| `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)

**Possible values:** `1000` - `5000`
**Default value:** `0` +| `retryDelay` | The delay before retrying after a request failure. (Milliseconds)

**Possible values:** `1000` - `60000`
**Default value:** `2500` +| `apiVersion` | The OpenWeatherMap API version to use.

**Default value:** `2.5` +| `apiBase` | The OpenWeatherMap base URL.

**Default value:** `'http://api.openweathermap.org/data/'` +| `weatherEndpoint` | The OpenWeatherMap API endPoint.

**Default value:** `'weather'` +| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather.

**Default value:** `true` +| `calendarClass` | The class for the calender module to base the event based weather information on.

**Default value:** `'calendar'` +| `iconTable` | The conversion table to convert the weather conditions to weather-icons.

**Default value:** view tabel below. + +#### Default Icon Table +````javascript +iconTable: { + '01d': 'wi-day-sunny', + '02d': 'wi-day-cloudy', + '03d': 'wi-cloudy', + '04d': 'wi-cloudy-windy', + '09d': 'wi-showers', + '10d': 'wi-rain', + '11d': 'wi-thunderstorm', + '13d': 'wi-snow', + '50d': 'wi-fog', + '01n': 'wi-night-clear', + '02n': 'wi-night-cloudy', + '03n': 'wi-night-cloudy', + '04n': 'wi-night-cloudy', + '09n': 'wi-night-showers', + '10n': 'wi-night-rain', + '11n': 'wi-night-thunderstorm', + '13n': 'wi-night-snow', + '50n': 'wi-night-alt-cloudy-windy' +} +```` diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index e92550ea..135af54a 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -296,7 +296,7 @@ Module.register("currentweather",{ */ processWeather: function(data) { - if (!data || !data.main || !data.main.temp) { + if (!data || !data.main || typeof data.main.temp === "undefined") { // Did not receive usable new data. // Maybe this needs a better check? return; diff --git a/modules/default/helloworld/README.md b/modules/default/helloworld/README.md index 72e7d023..d86fce3d 100644 --- a/modules/default/helloworld/README.md +++ b/modules/default/helloworld/README.md @@ -6,11 +6,11 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'helloworld', - position: 'bottom_bar', // This can be any of the regions. + module: "helloworld", + position: "bottom_bar", // This can be any of the regions. config: { // See 'Configuration options' for more information. - text: 'Hello world!' + text: "Hello world!" } } ] @@ -20,23 +20,6 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - - - -
OptionDescription
textThe text to display.
-
Example: 'Hello world!' -
Default value: 'Hello world!' -
+| Option | Description +| ------ | ----------- +| `text` | The text to display.

**Example:** `'Hello world!'`
**Default value:** `'Hello world!'` diff --git a/modules/default/newsfeed/README.md b/modules/default/newsfeed/README.md index 58c7b9ae..bfaa1aad 100644 --- a/modules/default/newsfeed/README.md +++ b/modules/default/newsfeed/README.md @@ -1,15 +1,16 @@ # Module: News Feed The `newsfeed ` module is one of the default modules of the MagicMirror. -This module displays news headlines based on an RSS feed. +This module displays news headlines based on an RSS feed. Scrolling through news headlines happens time-based (````updateInterval````), but can also be controlled by sending news feed specific notifications to the module. ## Using the module +### Configuration To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'newsfeed', - position: 'bottom_bar', // This can be any of the regions. Best results in center regions. + module: "newsfeed", + position: "bottom_bar", // This can be any of the regions. Best results in center regions. config: { // The config property is optional. // If no config is set, an example calendar is shown. @@ -30,152 +31,51 @@ modules: [ ] ```` +### Notifications +#### Interacting with the module +MagicMirror's [notification mechanism](https://github.com/MichMich/MagicMirror/tree/master/modules#thissendnotificationnotification-payload) allows to send notifications to the `newsfeed` module. The following notifications are supported: + +| Notification Identifier | Description +| ----------------------- | ----------- +| `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.
The module expects that the module's configuration option `showDescription` is set to `false` (default value).

When received a _second consecutive time_, shows the full news article in an IFRAME.
This requires that the news page can be embedded in an IFRAME, e.g. doesn't have the HTTP response header [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) set to e.g. `DENY`. +| `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. + +#### Example +The following example shows how the next news article title can be displayed on the MagicMirror. +````javascript +this.sendNotification('ARTICLE_NEXT'); +```` + +#### `newsfeed` specific notification emitting modules +The third party [MMM-Gestures](https://github.com/thobach/MMM-Gestures) module supports above notifications when moving your hand up, down, left or right in front of a gesture sensor attached to the MagicMirror. See module's readme for more details. + ## Configuration options The following properties can be configured: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - removeStartTags: false, - removeEndTags: false, - startTags: [], - endTags: [] - - - - - - - - - - - - - - - - - - - -
OptionDescription
feedsAn array of feed urls that will be used as source.
- More info about this object can be found below. -
Default value: [ - { - title: "New York Times", - url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", - encoding: "UTF-8" - } - ] -
showSourceTitleDisplay the title of the source.
-
Possible values: true or false -
Default value: true -
showPublishDateDisplay the publish date of an headline.
-
Possible values: true or false -
Default value: true -
showDescriptionDisplay the description of an item.
-
Possible values: true or false -
Default value: false -
reloadIntervalHow often does the content needs to be fetched? (Milliseconds)
-
Possible values: 1000 - 86400000 -
Default value: 300000 (5 minutes) -
updateIntervalHow often do you want to display a new headline? (Milliseconds)
-
Possible values:1000 - 60000 -
Default value: 10000 (10 seconds) -
animationSpeedSpeed of the update animation. (Milliseconds)
-
Possible values:0 - 5000 -
Default value: 2500 (2.5 seconds) -
maxNewsItemsTotal amount of news items to cycle through. (0 for unlimited)
-
Possible values:0 - ... -
Default value: 0 -
removeStartTagsSome newsfeeds feature tags at the beginning of their titles or descriptions, such as [VIDEO]. - This setting allows for the removal of specified tags from the beginning of an item's description and/or title.
-
Possible values:'title', 'description', 'both' -
startTagsList the tags you would like to have removed at the beginning of the feed item
-
Possible values: ['TAG'] or ['TAG1','TAG2',...] -
removeEndTagsRemove specified tags from the end of an item's description and/or title.
-
Possible values:'title', 'description', 'both' -
endTagsList the tags you would like to have removed at the end of the feed item
-
Possible values: ['TAG'] or ['TAG1','TAG2',...] -
+| Option | Description +| ----------------- | ----------- +| `feeds` | An array of feed urls that will be used as source.
More info about this object can be found below.
**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.

**Possible values:** `true` or `false`
**Default value:** `true` +| `showPublishDate` | Display the publish date of an headline.

**Possible values:** `true` or `false`
**Default value:** `true` +| `showDescription` | Display the description of an item.

**Possible values:** `true` or `false`
**Default value:** `false` +| `reloadInterval` | How often does the content needs to be fetched? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `300000` (5 minutes) +| `updateInterval` | How often do you want to display a new headline? (Milliseconds)

**Possible values:**`1000` - `60000`
**Default value:** `10000` (10 seconds) +| `animationSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `2500` (2.5 seconds) +| `maxNewsItems` | Total amount of news items to cycle through. (0 for unlimited)

**Possible values:**`0` - `...`
**Default value:** `0` +| `removeStartTags` | Some newsfeeds feature tags at the **beginning** of their titles or descriptions, such as _[VIDEO]_. This setting allows for the removal of specified tags from the beginning of an item's description and/or title.

**Possible values:**`'title'`, `'description'`, `'both'` +| `startTags` | List the tags you would like to have removed at the beginning of the feed item

**Possible values:** `['TAG']` or `['TAG1','TAG2',...]` +| `removeEndTags` | Remove specified tags from the **end** of an item's description and/or title.

**Possible values:**`'title'`, `'description'`, `'both'` +| `endTags` | List the tags you would like to have removed at the end of the feed item

**Possible values:** `['TAG']` or `['TAG1','TAG2',...]` The `feeds` property contains an array with multiple objects. These objects have the following properties: - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
titleThe name of the feed source to be displayed above the news items.
-
This property is optional. -
urlThe url of the feed used for the headlines.
-
Example: 'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml' -
encodingThe encoding of the news feed.
-
This property is optional. -
Possible values:'UTF-8', 'ISO-8859-1', etc ... -
Default value: 'UTF-8' -
+| Option | Description +| ---------- | ----------- +| `title` | The name of the feed source to be displayed above the news items.

This property is optional. +| `url` | The url of the feed used for the headlines.

**Example:** `'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'` +| `encoding` | The encoding of the news feed.

This property is optional.
**Possible values:**`'UTF-8'`, `'ISO-8859-1'`, etc ...
**Default value:** `'UTF-8'` diff --git a/modules/default/newsfeed/fetcher.js b/modules/default/newsfeed/fetcher.js index b7511de9..f4fb44d9 100644 --- a/modules/default/newsfeed/fetcher.js +++ b/modules/default/newsfeed/fetcher.js @@ -85,7 +85,12 @@ 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/)"} - request({uri: url, encoding: null, headers: headers}).pipe(iconv.decodeStream(encoding)).pipe(parser); + request({uri: url, encoding: null, headers: headers}) + .on("error", function(error) { + fetchFailedCallback(self, error); + scheduleTimer(); + }) + .pipe(iconv.decodeStream(encoding)).pipe(parser); }; diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 74014208..aed917f8 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -89,7 +89,8 @@ Module.register("newsfeed",{ if (this.newsItems.length > 0) { - if (this.config.showSourceTitle || this.config.showPublishDate) { + // this.config.showFullArticle is a run-time configuration, triggered by optional notifications + if (!this.config.showFullArticle && (this.config.showSourceTitle || this.config.showPublishDate)) { var sourceAndTimestamp = document.createElement("div"); sourceAndTimestamp.className = "light small dimmed"; @@ -152,10 +153,12 @@ Module.register("newsfeed",{ } - var title = document.createElement("div"); - title.className = "bright medium light"; - title.innerHTML = this.newsItems[this.activeItem].title; - wrapper.appendChild(title); + if(!this.config.showFullArticle){ + var title = document.createElement("div"); + title.className = "bright medium light"; + title.innerHTML = this.newsItems[this.activeItem].title; + wrapper.appendChild(title); + } if (this.config.showDescription) { var description = document.createElement("div"); @@ -164,6 +167,21 @@ Module.register("newsfeed",{ wrapper.appendChild(description); } + if (this.config.showFullArticle) { + var fullArticle = document.createElement("iframe"); + fullArticle.className = ""; + fullArticle.style.width = "100%"; + 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; + wrapper.appendChild(fullArticle); + } + + + } else { wrapper.innerHTML = this.translate("LOADING"); wrapper.className = "small dimmed"; @@ -256,7 +274,7 @@ Module.register("newsfeed",{ self.updateDom(self.config.animationSpeed); - setInterval(function() { + timer = setInterval(function() { self.activeItem++; self.updateDom(self.config.animationSpeed); }, this.config.updateInterval); @@ -273,5 +291,50 @@ Module.register("newsfeed",{ return string.charAt(0).toUpperCase() + string.slice(1); }, + resetDescrOrFullArticleAndTimer: function() { + this.config.showDescription = false; + this.config.showFullArticle = false; + if(!timer){ + this.scheduleUpdateInterval(); + } + }, + + notificationReceived: function(notification, payload, sender) { + Log.info(this.name + " - received notification: " + notification); + if(notification == "ARTICLE_NEXT"){ + var before = this.activeItem; + this.activeItem++; + if (this.activeItem >= this.newsItems.length) { + this.activeItem = 0; + } + this.resetDescrOrFullArticleAndTimer(); + Log.info(this.name + " - going from article #" + before + " to #" + this.activeItem + " (of " + this.newsItems.length + ")"); + this.updateDom(100); + } else if(notification == "ARTICLE_PREVIOUS"){ + var before = this.activeItem; + this.activeItem--; + if (this.activeItem < 0) { + this.activeItem = this.newsItems.length - 1; + } + this.resetDescrOrFullArticleAndTimer(); + Log.info(this.name + " - going from article #" + before + " to #" + this.activeItem + " (of " + this.newsItems.length + ")"); + this.updateDom(100); + } + // 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); + } else if(notification == "ARTICLE_LESS_DETAILS"){ + this.resetDescrOrFullArticleAndTimer(); + Log.info(this.name + " - showing only article titles again"); + this.updateDom(100); + } else { + Log.info(this.name + " - unknown notification, ignoring: " + notification); + } + }, }); diff --git a/modules/default/updatenotification/README.md b/modules/default/updatenotification/README.md index 7d839087..54ba213a 100644 --- a/modules/default/updatenotification/README.md +++ b/modules/default/updatenotification/README.md @@ -8,8 +8,8 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'updatenotification', - position: 'top_center', // This can be any of the regions. + module: "updatenotification", + position: "top_center", // This can be any of the regions. config: { // The config property is optional. // See 'Configuration options' for more information. @@ -22,21 +22,6 @@ modules: [ The following properties can be configured: - - - - - - - - - - - - - - -
OptionDescription
updateIntervalHow often do you want to check for a new version? This value represents the interval in milliseconds.
-
Possible values: Any value above 60000 (1 minute); -
Default value: 600000 (10 minutes); -
\ No newline at end of file +| Option | Description +| ---------------- | ----------- +| `updateInterval` | How often do you want to check for a new version? This value represents the interval in milliseconds.

**Possible values:** Any value above `60000` (1 minute)
**Default value:** `600000` (10 minutes); diff --git a/modules/default/weatherforecast/README.md b/modules/default/weatherforecast/README.md index 6b5e3930..3568f7de 100644 --- a/modules/default/weatherforecast/README.md +++ b/modules/default/weatherforecast/README.md @@ -8,14 +8,14 @@ To use this module, add it to the modules array in the `config/config.js` file: ````javascript modules: [ { - module: 'weatherforecast', - position: 'top_right', // This can be any of the regions. + module: "weatherforecast", + position: "top_right", // This can be any of the regions. // Best results in left or right regions. config: { // See 'Configuration options' for more information. - location: 'Amsterdam,Netherlands', - locationID: '', //Location ID from http://openweathermap.org/help/city_list.txt - appid: 'abcde12345abcde12345abcde12345ab' //openweathermap.org API key. + location: "Amsterdam,Netherlands", + locationID: "", //Location ID from http://openweathermap.org/help/city_list.txt + appid: "abcde12345abcde12345abcde12345ab" //openweathermap.org API key. } } ] @@ -25,177 +25,50 @@ modules: [ The following properties can be configured: +| Option | Description +| ---------------------------- | ----------- +| `location` | The location used for weather information.

**Example:** `'Amsterdam,Netherlands'`
**Default value:** `false`

**Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. +| `locationID` | Location ID from [OpenWeatherMap](http://openweathermap.org/help/city_list.txt) **This will override anything you put in location.**
Leave blank if you want to use location.
**Example:** `1234567`
**Default value:** `false`

**Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. +| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account.

This value is **REQUIRED** +| `units` | What units to use. Specified by config.js

**Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit
**Default value:** `config.units` +| `roundTemp` | Round temperature values to nearest integer.

**Possible values:** `true` (round to integer) or `false` (display exact value with decimal point)
**Default value:** `false` +| `maxNumberOfDays` | How many days of forecast to return. Specified by config.js

**Possible values:** `1` - `16`
**Default value:** `7` (7 days)
This value is optional. By default the weatherforecast module will return 7 days. +| `showRainAmount` | Should the predicted rain amount be displayed?

**Possible values:** `true` or `false`
**Default value:** `false`
This value is optional. By default the weatherforecast module will not display the predicted amount of rain. +| `updateInterval` | How often does the content needs to be fetched? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `600000` (10 minutes) +| `animationSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `1000` (1 second) +| `lang` | The language of the days.

**Possible values:** `en`, `nl`, `ru`, etc ...
**Default value:** uses value of _config.language_ +| `fade` | Fade the future events to black. (Gradient)

**Possible values:** `true` or `false`
**Default value:** `true` +| `fadePoint` | Where to start fade?

**Possible values:** `0` (top of the list) - `1` (bottom of list)
**Default value:** `0.25` +| `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)

**Possible values:** `1000` - `5000`
**Default value:** `2500` (2.5 seconds delay. This delay is used to keep the OpenWeather API happy.) +| `retryDelay` | The delay before retrying after a request failure. (Milliseconds)

**Possible values:** `1000` - `60000`
**Default value:** `2500` +| `apiVersion` | The OpenWeatherMap API version to use.

**Default value:** `2.5` +| `apiBase` | The OpenWeatherMap base URL.

**Default value:** `'http://api.openweathermap.org/data/'` +| `forecastEndpoint` | The OpenWeatherMap API endPoint.

**Default value:** `'forecast/daily'` +| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather.

**Default value:** `true` +| `calendarClass` | The class for the calender module to base the event based weather information on.

**Default value:** `'calendar'` +| `iconTable` | The conversion table to convert the weather conditions to weather-icons.

**Default value:** view table below + `colored` | If set 'colored' to true the min-temp get a blue tone and the max-temp get a red tone.

**Default value:** `'false'` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionDescription
locationThe location used for weather information.
-
Example: 'Amsterdam,Netherlands' -
Default value: false

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

- Note: When the location and locationID are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used. -
appidThe OpenWeatherMap API key, which can be obtained by creating an OpenWeatherMap account.
-
This value is REQUIRED -
unitsWhat units to use. Specified by config.js
-
Possible values: config.units = Specified by config.js, default = Kelvin, metric = Celsius, imperial =Fahrenheit -
Default value: config.units -
roundTempRound temperature values to nearest integer.
-
Possible values: true (round to integer) or false (display exact value with decimal point) -
Default value: false -
maxNumberOfDaysHow many days of forecast to return. Specified by config.js
-
Possible values: 1 - 16 -
Default value: 7 (7 days) -
This value is optional. By default the weatherforecast module will return 7 days. -
showRainAmountShould the predicted rain amount be displayed?
-
Possible values: true or false -
Default value: false -
This value is optional. By default the weatherforecast module will not display the predicted amount of rain. -
updateIntervalHow often does the content needs to be fetched? (Milliseconds)
-
Possible values: 1000 - 86400000 -
Default value: 600000 (10 minutes) -
animationSpeedSpeed of the update animation. (Milliseconds)
-
Possible values:0 - 5000 -
Default value: 1000 (1 second) -
langThe language of the days.
-
Possible values: en, nl, ru, etc ... -
Default value: uses value of config.language -
fadeFade the future events to black. (Gradient)
-
Possible values: true or false -
Default value: true -
fadePointWhere to start fade?
-
Possible values: 0 (top of the list) - 1 (bottom of list) -
Default value: 0.25 -
initialLoadDelayThe 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)
-
Possible values: 1000 - 5000 -
Default value: 2500 (2.5 seconds delay. This delay is used to keep the OpenWeather API happy.) -
retryDelayThe delay before retrying after a request failure. (Milliseconds)
-
Possible values: 1000 - 60000 -
Default value: 2500 -
apiVersionThe OpenWeatherMap API version to use.
-
Default value: 2.5 -
apiBaseThe OpenWeatherMap base URL.
-
Default value: 'http://api.openweathermap.org/data/' -
forecastEndpointThe OpenWeatherMap API endPoint.
-
Default value: 'forecast/daily' -
appendLocationNameToHeaderIf set to true, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather.
-
Default value: true -
calendarClassThe class for the calender module to base the event based weather information on.
-
Default value: 'calendar' -
iconTableThe conversion table to convert the weather conditions to weather-icons.
-
Default value: iconTable: { - '01d':'wi-day-sunny', - '02d':'wi-day-cloudy', - '03d':'wi-cloudy', - '04d':'wi-cloudy-windy', - '09d':'wi-showers', - '10d':'wi-rain', - '11d':'wi-thunderstorm', - '13d':'wi-snow', - '50d':'wi-fog', - '01n':'wi-night-clear', - '02n':'wi-night-cloudy', - '03n':'wi-night-cloudy', - '04n':'wi-night-cloudy', - '09n':'wi-night-showers', - '10n':'wi-night-rain', - '11n':'wi-night-thunderstorm', - '13n':'wi-night-snow', - '50n':'wi-night-alt-cloudy-windy' - } -
coloredIf set 'colored' to true the min-temp get a blue tone and the max-temp get a red tone.
-
Default value: false -
+#### Default Icon Table +````javascript +iconTable: { + '01d': 'wi-day-sunny', + '02d': 'wi-day-cloudy', + '03d': 'wi-cloudy', + '04d': 'wi-cloudy-windy', + '09d': 'wi-showers', + '10d': 'wi-rain', + '11d': 'wi-thunderstorm', + '13d': 'wi-snow', + '50d': 'wi-fog', + '01n': 'wi-night-clear', + '02n': 'wi-night-cloudy', + '03n': 'wi-night-cloudy', + '04n': 'wi-night-cloudy', + '09n': 'wi-night-showers', + '10n': 'wi-night-rain', + '11n': 'wi-night-thunderstorm', + '13n': 'wi-night-snow', + '50n': 'wi-night-alt-cloudy-windy' +} +```` diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js index 32daec30..211e5082 100644 --- a/modules/default/weatherforecast/weatherforecast.js +++ b/modules/default/weatherforecast/weatherforecast.js @@ -154,7 +154,11 @@ Module.register("weatherforecast",{ if (isNaN(forecast.rain)) { rainCell.innerHTML = ""; } else { - rainCell.innerHTML = forecast.rain + " mm"; + if(config.units !== "imperial") { + rainCell.innerHTML = forecast.rain + " mm"; + } else { + rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2) + " in"; + } } rainCell.className = "align-right bright rain"; row.appendChild(rainCell); diff --git a/modules/node_modules/node_helper/index.js b/modules/node_modules/node_helper/index.js index dc57ef36..bdeccf8b 100644 --- a/modules/node_modules/node_helper/index.js +++ b/modules/node_modules/node_helper/index.js @@ -14,6 +14,11 @@ NodeHelper = Class.extend({ console.log("Initializing new module helper ..."); }, + loaded: function(callback) { + console.log("Module helper loaded: " + this.name); + callback(); + }, + start: function() { console.log("Staring module helper: " + this.name); }, diff --git a/package.json b/package.json index 118c9837..9d94a012 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,12 @@ { "name": "magicmirror", - "version": "2.1.0", + "version": "2.1.1", "description": "A modular interface for smart mirrors.", "main": "js/electron.js", "scripts": { - "start": "electron js/electron.js" + "start": "sh run-start.sh", + "postinstall": "sh installers/postinstall/postinstall.sh", + "test": "./node_modules/mocha/bin/mocha tests --recursive" }, "repository": { "type": "git", @@ -26,12 +28,14 @@ }, "homepage": "https://github.com/MichMich/MagicMirror#readme", "devDependencies": { + "chai": "^3.5.0", "grunt": "latest", "grunt-eslint": "latest", "grunt-jsonlint": "latest", "grunt-markdownlint": "^1.0.13", "grunt-stylelint": "latest", "grunt-yamllint": "latest", + "mocha": "^3.2.0", "stylelint-config-standard": "latest", "time-grunt": "latest" }, @@ -44,7 +48,7 @@ "iconv-lite": "latest", "moment": "latest", "request": "^2.78.0", - "rrule": "latest", + "rrule-alt": "^2.2.3", "simple-git": "^1.62.0", "socket.io": "^1.5.1", "valid-url": "latest", diff --git a/run-start.sh b/run-start.sh new file mode 100644 index 00000000..6c4d4003 --- /dev/null +++ b/run-start.sh @@ -0,0 +1,4 @@ +if [ -z "$DISPLAY" ]; then #If not set DISPLAY is SSH remote or tty + export DISPLAY=:0 # Set by defaul display +fi +electron js/electron.js diff --git a/splashscreen/splash.png b/splashscreen/splash.png index f3da394b..b2acc495 100644 Binary files a/splashscreen/splash.png and b/splashscreen/splash.png differ diff --git a/tests/functions/compare-version.js b/tests/functions/compare-version.js new file mode 100644 index 00000000..8cc22101 --- /dev/null +++ b/tests/functions/compare-version.js @@ -0,0 +1,20 @@ +var chai = require("chai"); +var expect = chai.expect; +var classMM = require("../../js/class.js"); // require for load module.js +var moduleMM = require("../../js/module.js") + +describe("Test function cmpVersions in js/module.js", function() { + + it("should return -1 when comparing 2.1 to 2.2", function() { + expect(moduleMM._test.cmpVersions("2.1", "2.2")).to.equal(-1); + }); + + it("should be return 0 when comparing 2.2 to 2.2", function() { + expect(moduleMM._test.cmpVersions("2.2", "2.2")).to.equal(0); + }); + + it("should be return 1 when comparing 1.1 to 1.0", function() { + expect(moduleMM._test.cmpVersions("1.1", "1.0")).to.equal(1); + }); +}); + diff --git a/tests/global_vars/root_path.js b/tests/global_vars/root_path.js new file mode 100644 index 00000000..04edc03f --- /dev/null +++ b/tests/global_vars/root_path.js @@ -0,0 +1,25 @@ +var fs = require("fs"); +var path = require("path"); +var chai = require("chai"); +var expect = chai.expect; + +describe("Test global.root_path, set in js/app.js", function() { + var appMM = require("../../js/app.js") + + var expectedSubPaths = [ + "modules", + "serveronly", + "js", + "js/app.js", + "js/main.js", + "js/electron.js", + "config" + ]; + + expectedSubPaths.forEach(subpath => { + it(`should contain a file/folder "${subpath}"`, function() { + expect(fs.existsSync(path.join(global.root_path, subpath))).to.equal(true); + }); + }); +}); + diff --git a/translations/af.json b/translations/af.json new file mode 100644 index 00000000..894b14ea --- /dev/null +++ b/translations/af.json @@ -0,0 +1,34 @@ +{ + /* GENERAL */ + "LOADING": "Besig om te laai …", + + /* CALENDAR */ + "TODAY": "Vandag", + "TOMORROW": "Môre", + "DAYAFTERTOMORROW": "Oormôre", + "RUNNING": "Eindig in", + "EMPTY": "Geen komende gebeurtenisse.", + + /* WEATHER */ + "N": "N", + "NNE": "NNO", + "NE": "NO", + "ENE": "ONO", + "E": "O", + "ESE": "OSO", + "SE": "SO", + "SSE": "SSO", + "S": "S", + "SSW": "SSW", + "SW": "SW", + "WSW": "WSW", + "W": "W", + "WNW": "WNW", + "NW": "NW", + "NNW": "NNW", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "MagicMirror² update beskikbaar.", + "UPDATE_NOTIFICATION_MODULE": "Update beskikbaar vir MODULE_NAME module.", + "UPDATE_INFO": "Die huidige installasie is COMMIT_COUNT agter op die BRANCH_NAME branch." +} diff --git a/translations/da.json b/translations/da.json index 4b346437..5ad271fe 100644 --- a/translations/da.json +++ b/translations/da.json @@ -25,7 +25,7 @@ "W": "V", "WNW": "VNV", "NW": "NV", - "NNW": "NNV" + "NNW": "NNV", /* UPDATE INFO */ diff --git a/translations/fi.json b/translations/fi.json index b753039e..59fa0180 100644 --- a/translations/fi.json +++ b/translations/fi.json @@ -5,6 +5,7 @@ /* CALENDAR */ "TODAY": "Tänään", "TOMORROW": "Huomenna", + "DAYAFTERTOMORROW": "Ylihuomenna", "RUNNING": "Meneillään", "EMPTY": "Ei tulevia tapahtumia.", @@ -24,5 +25,9 @@ "W": "L", "WNW": "LPL", "NW": "PL", - "NNW": "PPL" + "NNW": "PPL", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "MagicMirror² päivitys saatavilla.", + "UPDATE_NOTIFICATION_MODULE": "Päivitys saatavilla moduulille MODULE_NAME." } diff --git a/translations/hu.json b/translations/hu.json new file mode 100644 index 00000000..069ad1ad --- /dev/null +++ b/translations/hu.json @@ -0,0 +1,34 @@ +{ + /* GENERAL */ + "LOADING": "Betöltés …", + + /* CALENDAR */ + "TODAY": "Ma", + "TOMORROW": "Holnap", + "DAYAFTERTOMORROW": "Holnapután", + "RUNNING": "Vége lesz", + "EMPTY": "Nincs közelgő esemény.", + + /* WEATHER */ + "N": "É", + "NNE": "ÉÉK", + "NE": "ÉK", + "ENE": "KÉK", + "E": "K", + "ESE": "KDK", + "SE": "DK", + "SSE": "DDK", + "S": "D", + "SSW": "DDNy", + "SW": "DNy", + "WSW": "NyDNy", + "W": "Ny", + "WNW": "NyÉNy", + "NW": "ÉNy", + "NNW": "ÉÉNy", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "MagicMirror² elérhető egy frissítés!", + "UPDATE_NOTIFICATION_MODULE": "A frissítés MODULE_NAME modul néven érhető el.", + "UPDATE_INFO": "A jelenlegi telepítés COMMIT_COUNT mögött BRANCH_NAME ágon található." +} \ No newline at end of file diff --git a/translations/is.json b/translations/is.json new file mode 100644 index 00000000..d3e6d6cb --- /dev/null +++ b/translations/is.json @@ -0,0 +1,34 @@ +{ + /* GENERAL */ + "LOADING": "Hleð upp …", + + /* CALENDAR */ + "TODAY": "Í dag", + "TOMORROW": "Á morgun", + "DAYAFTERTOMORROW": "Ekki á morgun, heldur hinn", + "RUNNING": "Endar eftir", + "EMPTY": "Ekkert framundan.", + + /* WEATHER */ + "N": "N", + "NNE": "NNA", + "NE": "NA", + "ENE": "ANA", + "E": "A", + "ESE": "ASA", + "SE": "SA", + "SSE": "SSA", + "S": "S", + "SSW": "SSV", + "SW": "SV", + "WSW": "VSV", + "W": "V", + "WNW": "VNV", + "NW": "NV", + "NNW": "NNV", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "MagicMirror² uppfærsla í boði.", + "UPDATE_NOTIFICATION_MODULE": "Uppfærsla í boði fyrir MODULE_NAME module.", + "UPDATE_INFO": "Núverandi kerfi er COMMIT_COUNT á eftir BRANCH_NAME branchinu." +} diff --git a/translations/pl.json b/translations/pl.json index 7a47745b..06bf3b5c 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -24,10 +24,10 @@ "W": "W", "WNW": "WNW", "NW": "NW", - "NNW": "NNW" - + "NNW": "NNW", + /* UPDATE INFO */ "UPDATE_NOTIFICATION": "Dostępna jest aktualizacja MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostępna jest aktualizacja modułu MODULE_NAME.", - "UPDATE_INFO": "The current installation is COMMIT_COUNT behind on the BRANCH_NAME branch." + "UPDATE_INFO": "Zainstalowana wersja odbiega o COMMIT_COUNT commitów od gałęzi BRANCH_NAME." } diff --git a/translations/ru.json b/translations/ru.json new file mode 100644 index 00000000..053385ee --- /dev/null +++ b/translations/ru.json @@ -0,0 +1,34 @@ +{ + /* GENERAL */ + "LOADING": "Загрузка …", + + /* CALENDAR */ + "TODAY": "Сегодня", + "TOMORROW": "Завтра", + "DAYAFTERTOMORROW": "Послезавтра", + "RUNNING": "Заканчивается через", + "EMPTY": "Нет предстоящих событий", + + /* WEATHER */ + "N": "С", + "NNE": "ССВ", + "NE": "СВ", + "ENE": "ВСВ", + "E": "В", + "ESE": "ВЮВ", + "SE": "ЮВ", + "SSE": "ЮЮВ", + "S": "Ю", + "SSW": "ЮЮЗ", + "SW": "ЮЗ", + "WSW": "ЗЮЗ", + "W": "З", + "WNW": "ЗСЗ", + "NW": "СЗ", + "NNW": "ССЗ", + + /* UPDATE INFO */ + "UPDATE_NOTIFICATION": "Есть обновление для MagicMirror².", + "UPDATE_NOTIFICATION_MODULE": "Есть обновление для MODULE_NAME модуля.", + "UPDATE_INFO": "Данная инсталляция позади BRANCH_NAME ветки на COMMIT_COUNT коммитов." +} diff --git a/translations/translations.js b/translations/translations.js index d572c803..c10da418 100644 --- a/translations/translations.js +++ b/translations/translations.js @@ -26,4 +26,8 @@ var translations = { "gr" : "translations/gr.json", // Greek "da" : "translations/da.json", // Danish "tr" : "translations/tr.json", // Turkish + "ru" : "translations/ru.json", // Russian + "af" : "translations/af.json", // Afrikaans + "hu" : "translations/hu.json", // Hungarian + "is" : "translations/is.json", // Icelandic };