mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-28 09:42:21 -04:00
Run prettier over ALL files once
No other changes done in this commit
This commit is contained in:
parent
3a5a29efc0
commit
abb5dc5739
160 changed files with 2369 additions and 2210 deletions
5
.github/CONTRIBUTING.md
vendored
5
.github/CONTRIBUTING.md
vendored
|
@ -1,5 +1,4 @@
|
||||||
Contribution Policy for MagicMirror²
|
# Contribution Policy for MagicMirror²
|
||||||
====================================
|
|
||||||
|
|
||||||
Thanks for contributing to MagicMirror²!
|
Thanks for contributing to MagicMirror²!
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ Problems installing or configuring your MagicMirror? Check out: [https://forum.m
|
||||||
|
|
||||||
When submitting a new issue, please supply the following information:
|
When submitting a new issue, please supply the following information:
|
||||||
|
|
||||||
**Platform**: Place your platform here... give us your web browser/Electron version *and* your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX).
|
**Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX).
|
||||||
|
|
||||||
**Node Version**: Make sure it's version 0.12.13 or later.
|
**Node Version**: Make sure it's version 0.12.13 or later.
|
||||||
|
|
||||||
|
|
7
.github/ISSUE_TEMPLATE.md
vendored
7
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,24 +1,29 @@
|
||||||
## I'm not sure if this is a bug
|
## I'm not sure if this is a bug
|
||||||
|
|
||||||
If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt)
|
If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt)
|
||||||
|
|
||||||
## I'm having troubles installing or configuring MagicMirror
|
## I'm having troubles installing or configuring MagicMirror
|
||||||
|
|
||||||
Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting)
|
Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting)
|
||||||
|
|
||||||
## I found a bug in the MagicMirror installer
|
## I found a bug in the MagicMirror installer
|
||||||
|
|
||||||
If you are facing an issue or found a bug while trying to install MagicMirror via the installer please report it in the respective GitHub repository:
|
If you are facing an issue or found a bug while trying to install MagicMirror via the installer please report it in the respective GitHub repository:
|
||||||
[https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts)
|
[https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts)
|
||||||
|
|
||||||
## I found a bug in the MagicMirror Docker image
|
## I found a bug in the MagicMirror Docker image
|
||||||
|
|
||||||
If you are facing an issue or found a bug while running MagicMirror inside a Docker container please create an issue in the GitHub repository of the MagicMirror Docker image:
|
If you are facing an issue or found a bug while running MagicMirror inside a Docker container please create an issue in the GitHub repository of the MagicMirror Docker image:
|
||||||
[https://github.com/bastilimbach/docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror)
|
[https://github.com/bastilimbach/docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## I found a bug in MagicMirror
|
## I found a bug in MagicMirror
|
||||||
|
|
||||||
Please make sure to only submit reproducible issues. You can safely remove everything above the dividing line.
|
Please make sure to only submit reproducible issues. You can safely remove everything above the dividing line.
|
||||||
When submitting a new issue, please supply the following information:
|
When submitting a new issue, please supply the following information:
|
||||||
|
|
||||||
**Platform**: Place your platform here... give us your web browser/Electron version *and* your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX).
|
**Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3, Windows, Mac, Linux, System V UNIX).
|
||||||
|
|
||||||
**Node Version**: Make sure it's version 8 or later.
|
**Node Version**: Make sure it's version 8 or later.
|
||||||
|
|
||||||
|
|
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -7,8 +7,7 @@ pull request to send us your changes. This makes everyone's lives
|
||||||
easier (including yours) and helps us out on the development team.
|
easier (including yours) and helps us out on the development team.
|
||||||
Thanks!
|
Thanks!
|
||||||
|
|
||||||
|
- Does the pull request solve a **related** issue?
|
||||||
* Does the pull request solve a **related** issue?
|
- If so, can you reference the issue?
|
||||||
* If so, can you reference the issue?
|
- What does the pull request accomplish? Use a list if needed.
|
||||||
* What does the pull request accomplish? Use a list if needed.
|
- If it includes major visual changes please add screenshots.
|
||||||
* If it includes major visual changes please add screenshots.
|
|
||||||
|
|
80
CHANGELOG.md
80
CHANGELOG.md
|
@ -7,13 +7,14 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
## [2.12.0] - Unreleased (Develop Branch)
|
## [2.12.0] - Unreleased (Develop Branch)
|
||||||
|
|
||||||
*This release is scheduled to be released on 2020-07-01.*
|
_This release is scheduled to be released on 2020-07-01._
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added prettier for an even cleaner codebase
|
- Added prettier for an even cleaner codebase
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Cleaned up alert module code
|
- Cleaned up alert module code
|
||||||
- Cleaned up check_config code
|
- Cleaned up check_config code
|
||||||
- Replaced grunt-based linters with their non-grunt equivalents
|
- Replaced grunt-based linters with their non-grunt equivalents
|
||||||
|
@ -22,9 +23,11 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||||
- Cleaned up all "no-undef" warnings from eslint
|
- Cleaned up all "no-undef" warnings from eslint
|
||||||
|
|
||||||
### Deleted
|
### Deleted
|
||||||
|
|
||||||
- Removed truetype (ttf) fonts
|
- Removed truetype (ttf) fonts
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- The broken modules due to Socket.io change from last release [#1973](https://github.com/MichMich/MagicMirror/issues/1973)
|
- The broken modules due to Socket.io change from last release [#1973](https://github.com/MichMich/MagicMirror/issues/1973)
|
||||||
- Add backward compatibility for old module code in socketclient.js [#1973](https://github.com/MichMich/MagicMirror/issues/1973)
|
- Add backward compatibility for old module code in socketclient.js [#1973](https://github.com/MichMich/MagicMirror/issues/1973)
|
||||||
|
|
||||||
|
@ -37,11 +40,13 @@ In the past years the project has grown a lot. This came with a huge downside: p
|
||||||
For more information regarding this major change, please check issue [#1860](https://github.com/MichMich/MagicMirror/issues/1860).
|
For more information regarding this major change, please check issue [#1860](https://github.com/MichMich/MagicMirror/issues/1860).
|
||||||
|
|
||||||
### Deleted
|
### Deleted
|
||||||
|
|
||||||
- Remove installers.
|
- Remove installers.
|
||||||
- Remove externalized scripts.
|
- Remove externalized scripts.
|
||||||
- Remove jshint dependency, instead eslint checks your config file now
|
- Remove jshint dependency, instead eslint checks your config file now
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Brazilian translation for "FEELS".
|
- Brazilian translation for "FEELS".
|
||||||
- Ukrainian translation.
|
- Ukrainian translation.
|
||||||
- Finnish translation for "PRECIP", "UPDATE_INFO_MULTIPLE" and "UPDATE_INFO_SINGLE".
|
- Finnish translation for "PRECIP", "UPDATE_INFO_MULTIPLE" and "UPDATE_INFO_SINGLE".
|
||||||
|
@ -56,6 +61,7 @@ For more information regarding this major change, please check issue [#1860](htt
|
||||||
- Add HTTPS support for clientonly-mode.
|
- Add HTTPS support for clientonly-mode.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Force declaration of public ip address in config file (ISSUE #1852)
|
- Force declaration of public ip address in config file (ISSUE #1852)
|
||||||
- Fixes `run-start.sh`: If running in docker-container, don't check the environment, just start electron (ISSUE #1859)
|
- Fixes `run-start.sh`: If running in docker-container, don't check the environment, just start electron (ISSUE #1859)
|
||||||
- Fix calendar time offset for recurring events crossing Daylight Savings Time (ISSUE #1798)
|
- Fix calendar time offset for recurring events crossing Daylight Savings Time (ISSUE #1798)
|
||||||
|
@ -66,6 +72,7 @@ For more information regarding this major change, please check issue [#1860](htt
|
||||||
- Fix update checking skipping 3rd party modules the first time
|
- Fix update checking skipping 3rd party modules the first time
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Remove documentation from core repository and link to new dedicated docs site: [docs.magicmirror.builders](https://docs.magicmirror.builders).
|
- Remove documentation from core repository and link to new dedicated docs site: [docs.magicmirror.builders](https://docs.magicmirror.builders).
|
||||||
- Updated config.js.sample: Corrected some grammar on `config.js.sample` comment section.
|
- Updated config.js.sample: Corrected some grammar on `config.js.sample` comment section.
|
||||||
- Removed `run-start.sh` script and update start commands:
|
- Removed `run-start.sh` script and update start commands:
|
||||||
|
@ -79,6 +86,7 @@ For more information regarding this major change, please check issue [#1860](htt
|
||||||
## [2.10.1] - 2020-01-10
|
## [2.10.1] - 2020-01-10
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Updated README.md: Added links to the official documentation website and remove links to broken installer.
|
- Updated README.md: Added links to the official documentation website and remove links to broken installer.
|
||||||
|
|
||||||
## [2.10.0] - 2020-01-01
|
## [2.10.0] - 2020-01-01
|
||||||
|
@ -88,12 +96,14 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`.
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Timestamps in log output.
|
- Timestamps in log output.
|
||||||
- Padding in dateheader mode of the calendar module.
|
- Padding in dateheader mode of the calendar module.
|
||||||
- New upgrade script to help users consume regular updates installers/upgrade-script.sh.
|
- New upgrade script to help users consume regular updates installers/upgrade-script.sh.
|
||||||
- New script to help setup pm2, without install installers/fixuppm2.sh.
|
- New script to help setup pm2, without install installers/fixuppm2.sh.
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Updated lower bound of `lodash` and `helmet` dependencies for security patches.
|
- Updated lower bound of `lodash` and `helmet` dependencies for security patches.
|
||||||
- Updated compliments.js to handle newline in text, as textfields to not interpolate contents.
|
- Updated compliments.js to handle newline in text, as textfields to not interpolate contents.
|
||||||
- Updated raspberry.sh installer script to handle new platform issues, split node/npm, pm2, and screen saver changes.
|
- Updated raspberry.sh installer script to handle new platform issues, split node/npm, pm2, and screen saver changes.
|
||||||
|
@ -102,6 +112,7 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
- Only check for xwindows running if not on macOS.
|
- Only check for xwindows running if not on macOS.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed issue in weatherforecast module where predicted amount of rain was not using the decimal symbol specified in config.js.
|
- Fixed issue in weatherforecast module where predicted amount of rain was not using the decimal symbol specified in config.js.
|
||||||
- Module header now updates correctly, if a module need to dynamically show/hide its header based on a condition.
|
- Module header now updates correctly, if a module need to dynamically show/hide its header based on a condition.
|
||||||
- Fix handling of config.js for serverOnly mode commented out.
|
- Fix handling of config.js for serverOnly mode commented out.
|
||||||
|
@ -114,18 +125,21 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Spanish translation for "PRECIP".
|
- Spanish translation for "PRECIP".
|
||||||
- Adding a Malay (Malaysian) translation for MagicMirror².
|
- Adding a Malay (Malaysian) translation for MagicMirror².
|
||||||
- Add test check URLs of vendors 200 and 404 HTTP CODE.
|
- Add test check URLs of vendors 200 and 404 HTTP CODE.
|
||||||
- Add tests for new weather module and helper to stub ajax requests.
|
- Add tests for new weather module and helper to stub ajax requests.
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Updatenotification module: Display update notification for a limited (configurable) time.
|
- Updatenotification module: Display update notification for a limited (configurable) time.
|
||||||
- Enabled e2e/vendor_spec.js tests.
|
- Enabled e2e/vendor_spec.js tests.
|
||||||
- The css/custom.css will be renamed after the next release. We've added into `run-start.sh` an instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MichMich/MagicMirror/issues/1540)
|
- The css/custom.css will be renamed after the next release. We've added into `run-start.sh` an instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MichMich/MagicMirror/issues/1540)
|
||||||
- Disable sending of notification CLOCK_SECOND when displaySeconds is false.
|
- Disable sending of notification CLOCK_SECOND when displaySeconds is false.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Updatenotification module: Properly handle race conditions, prevent crash.
|
- Updatenotification module: Properly handle race conditions, prevent crash.
|
||||||
- Send `NEWS_FEED` notification also for the first news messages which are shown.
|
- Send `NEWS_FEED` notification also for the first news messages which are shown.
|
||||||
- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MichMich/MagicMirror/issues/1722)
|
- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MichMich/MagicMirror/issues/1722)
|
||||||
|
@ -137,6 +151,7 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Option to show event location in calendar
|
- Option to show event location in calendar
|
||||||
- Finnish translation for "Feels" and "Weeks"
|
- Finnish translation for "Feels" and "Weeks"
|
||||||
- Russian translation for “Feels”
|
- Russian translation for “Feels”
|
||||||
|
@ -156,6 +171,7 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
- Added to `newsfeed.js`: in order to design the news article better with css, three more class-names were introduced: newsfeed-desc, newsfeed-desc, newsfeed-desc
|
- Added to `newsfeed.js`: in order to design the news article better with css, three more class-names were introduced: newsfeed-desc, newsfeed-desc, newsfeed-desc
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- English translation for "Feels" to "Feels like"
|
- English translation for "Feels" to "Feels like"
|
||||||
- Fixed the example calendar url in `config.js.sample`
|
- Fixed the example calendar url in `config.js.sample`
|
||||||
- Update `ical.js` to solve various calendar issues.
|
- Update `ical.js` to solve various calendar issues.
|
||||||
|
@ -163,6 +179,7 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
- Only update clock once per minute when seconds aren't shown
|
- Only update clock once per minute when seconds aren't shown
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed uncaught exception, race condition on module update
|
- Fixed uncaught exception, race condition on module update
|
||||||
- Fixed issue [#1696](https://github.com/MichMich/MagicMirror/issues/1696), some ical files start date to not parse to date type
|
- Fixed issue [#1696](https://github.com/MichMich/MagicMirror/issues/1696), some ical files start date to not parse to date type
|
||||||
- Allowance HTML5 autoplay-policy (policy is changed from Chrome 66 updates)
|
- Allowance HTML5 autoplay-policy (policy is changed from Chrome 66 updates)
|
||||||
|
@ -174,6 +191,7 @@ Special thanks to @sdetweil for all his great contributions!
|
||||||
- Updated the fetchedLocationName variable in currentweather.js so that city shows up in the header
|
- Updated the fetchedLocationName variable in currentweather.js so that city shows up in the header
|
||||||
|
|
||||||
### Updated installer
|
### Updated installer
|
||||||
|
|
||||||
- give non-pi2+ users (pi0, odroid, jetson nano, mac, windows, ...) option to continue install
|
- give non-pi2+ users (pi0, odroid, jetson nano, mac, windows, ...) option to continue install
|
||||||
- use current username vs hardcoded 'pi' to support non-pi install
|
- use current username vs hardcoded 'pi' to support non-pi install
|
||||||
- check for npm installed. node install doesn't do npm anymore
|
- check for npm installed. node install doesn't do npm anymore
|
||||||
|
@ -190,6 +208,7 @@ Fixed `package.json` version number.
|
||||||
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues running Electron, make sure your [Raspbian is up to date](https://www.raspberrypi.org/documentation/raspbian/updating.md).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Italian translation for "Feels"
|
- Italian translation for "Feels"
|
||||||
- Basic Klingon (tlhIngan Hol) translations
|
- Basic Klingon (tlhIngan Hol) translations
|
||||||
- Disabled the screensaver on raspbian with installation script
|
- Disabled the screensaver on raspbian with installation script
|
||||||
|
@ -203,12 +222,14 @@ Fixed `package.json` version number.
|
||||||
- Add `name` config option for calendars to be sent along with event broadcasts
|
- Add `name` config option for calendars to be sent along with event broadcasts
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MichMich/MagicMirror/issues/1500)
|
- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MichMich/MagicMirror/issues/1500)
|
||||||
- Updated modernizr code in alert module, fixed a small typo there too
|
- Updated modernizr code in alert module, fixed a small typo there too
|
||||||
- More verbose error message on console if the config is malformed
|
- More verbose error message on console if the config is malformed
|
||||||
- Updated installer script to install Node.js version 10.x
|
- Updated installer script to install Node.js version 10.x
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503), [#1511](https://github.com/MichMich/MagicMirror/issues/1511).
|
- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503), [#1511](https://github.com/MichMich/MagicMirror/issues/1511).
|
||||||
- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MichMich/MagicMirror/issues/1285).
|
- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MichMich/MagicMirror/issues/1285).
|
||||||
- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504).
|
- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504).
|
||||||
|
@ -226,6 +247,7 @@ Fixed `package.json` version number.
|
||||||
- Fix documentation of `useKMPHwind` option in currentweather
|
- Fix documentation of `useKMPHwind` option in currentweather
|
||||||
|
|
||||||
### New weather module
|
### New weather module
|
||||||
|
|
||||||
- Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
|
- Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
|
||||||
- Dimmed loading indicator for weather forecast.
|
- Dimmed loading indicator for weather forecast.
|
||||||
- Implemented config option `decimalSymbol` [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
|
- Implemented config option `decimalSymbol` [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
|
||||||
|
@ -243,11 +265,13 @@ Fixed `package.json` version number.
|
||||||
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues updating, make sure you are running the latest version of Node.
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues updating, make sure you are running the latest version of Node.
|
||||||
|
|
||||||
### ✨ Experimental ✨
|
### ✨ Experimental ✨
|
||||||
|
|
||||||
- New default [module weather](modules/default/weather). This module will eventually replace the current `currentweather` and `weatherforecast` modules. The new module is still pretty experimental, but it's included so you can give it a try and help us improve this module. Please give us you feedback using [this forum post](https://forum.magicmirror.builders/topic/9335/default-weather-module-refactoring).
|
- New default [module weather](modules/default/weather). This module will eventually replace the current `currentweather` and `weatherforecast` modules. The new module is still pretty experimental, but it's included so you can give it a try and help us improve this module. Please give us you feedback using [this forum post](https://forum.magicmirror.builders/topic/9335/default-weather-module-refactoring).
|
||||||
|
|
||||||
A huge, huge, huge thanks to user @fewieden for all his hard work on the new `weather` module!
|
A huge, huge, huge thanks to user @fewieden for all his hard work on the new `weather` module!
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Possibility to add classes to the cell of symbol, title and time of the events of calendar.
|
- Possibility to add classes to the cell of symbol, title and time of the events of calendar.
|
||||||
- Font-awesome 5, still has 4 for backwards compatibility.
|
- Font-awesome 5, still has 4 for backwards compatibility.
|
||||||
- Missing `showEnd` in calendar documentation
|
- Missing `showEnd` in calendar documentation
|
||||||
|
@ -262,6 +286,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Documentation for the existing `scale` option in the Weather Forecast module.
|
- Documentation for the existing `scale` option in the Weather Forecast module.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Allow parsing recurring calendar events where the start date is before 1900
|
- Allow parsing recurring calendar events where the start date is before 1900
|
||||||
- Fixed Polish translation for Single Update Info
|
- Fixed Polish translation for Single Update Info
|
||||||
- Ignore entries with unparseable details in the calendar module
|
- Ignore entries with unparseable details in the calendar module
|
||||||
|
@ -269,15 +294,17 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MichMich/MagicMirror/issues/1478)
|
- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MichMich/MagicMirror/issues/1478)
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- The default calendar setting `showEnd` is changed to `false`.
|
- The default calendar setting `showEnd` is changed to `false`.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- The Weather Forecast module by default displays the ° symbol after every numeric value to be consistent with the Current Weather module.
|
|
||||||
|
|
||||||
|
- The Weather Forecast module by default displays the ° symbol after every numeric value to be consistent with the Current Weather module.
|
||||||
|
|
||||||
## [2.5.0] - 2018-10-01
|
## [2.5.0] - 2018-10-01
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Romanian translation for "Feels"
|
- Romanian translation for "Feels"
|
||||||
- Support multi-line compliments
|
- Support multi-line compliments
|
||||||
- Simplified Chinese translation for "Feels"
|
- Simplified Chinese translation for "Feels"
|
||||||
|
@ -292,6 +319,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Support for showing end of events through config parameters showEnd and dateEndFormat
|
- Support for showing end of events through config parameters showEnd and dateEndFormat
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed gzip encoded calendar loading issue #1400.
|
- Fixed gzip encoded calendar loading issue #1400.
|
||||||
- Mixup between german and spanish translation for newsfeed.
|
- Mixup between german and spanish translation for newsfeed.
|
||||||
- Fixed close dates to be absolute, if no configured in the config.js - module Calendar
|
- Fixed close dates to be absolute, if no configured in the config.js - module Calendar
|
||||||
|
@ -337,11 +365,13 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Add update translations for Português Brasileiro
|
- Add update translations for Português Brasileiro
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Upgrade to Electron 2.0.0.
|
- Upgrade to Electron 2.0.0.
|
||||||
- Remove yarn-or-npm which breaks production builds.
|
- Remove yarn-or-npm which breaks production builds.
|
||||||
- Invoke module suspend even if no dom content. [#1308](https://github.com/MichMich/MagicMirror/issues/1308)
|
- Invoke module suspend even if no dom content. [#1308](https://github.com/MichMich/MagicMirror/issues/1308)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MichMich/MagicMirror/issues/1247)
|
- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MichMich/MagicMirror/issues/1247)
|
||||||
- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MichMich/MagicMirror/issues/1240)
|
- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MichMich/MagicMirror/issues/1240)
|
||||||
- In default module currentWeather/currentWeather.js line 296, 300, self.config.animationSpeed can not be found because the notificationReceived function does not have "self" variable.
|
- In default module currentWeather/currentWeather.js line 296, 300, self.config.animationSpeed can not be found because the notificationReceived function does not have "self" variable.
|
||||||
|
@ -354,6 +384,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MichMich/MagicMirror/issues/1263)
|
- Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MichMich/MagicMirror/issues/1263)
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Updated Italian translation
|
- Updated Italian translation
|
||||||
- Updated German translation
|
- Updated German translation
|
||||||
- Updated Dutch translation
|
- Updated Dutch translation
|
||||||
|
@ -361,6 +392,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
## [2.3.1] - 2018-04-01
|
## [2.3.1] - 2018-04-01
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MichMich/MagicMirror/issues/1243)
|
- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MichMich/MagicMirror/issues/1243)
|
||||||
|
|
||||||
## [2.3.0] - 2018-04-01
|
## [2.3.0] - 2018-04-01
|
||||||
|
@ -381,6 +413,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Add dc:date to parsing in newsfeed module, which allows parsing of more rss feeds.
|
- Add dc:date to parsing in newsfeed module, which allows parsing of more rss feeds.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Add link to GitHub repository which contains the respective Dockerfile.
|
- Add link to GitHub repository which contains the respective Dockerfile.
|
||||||
- Optimized automated unit tests cloneObject, cmpVersions
|
- Optimized automated unit tests cloneObject, cmpVersions
|
||||||
- Update notifications use now translation templates instead of normal strings.
|
- Update notifications use now translation templates instead of normal strings.
|
||||||
|
@ -388,6 +421,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Changed Electron dependency to v1.7.13.
|
- Changed Electron dependency to v1.7.13.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- News article in fullscreen (iframe) is now shown in front of modules.
|
- News article in fullscreen (iframe) is now shown in front of modules.
|
||||||
- Forecast respects maxNumberOfDays regardless of endpoint.
|
- Forecast respects maxNumberOfDays regardless of endpoint.
|
||||||
- Fix exception on translation of objects.
|
- Fix exception on translation of objects.
|
||||||
|
@ -405,6 +439,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
## [2.2.1] - 2018-01-01
|
## [2.2.1] - 2018-01-01
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed linting errors.
|
- Fixed linting errors.
|
||||||
|
|
||||||
## [2.2.0] - 2018-01-01
|
## [2.2.0] - 2018-01-01
|
||||||
|
@ -412,10 +447,12 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Calendar week is now handled with a variable translation in order to move number language specific.
|
- Calendar 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.
|
- Reverted the Electron dependency back to 1.4.15 since newer version don't seem to work on the Raspberry Pi very well.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add option to use [Nunjucks](https://mozilla.github.io/nunjucks/) templates in modules. (See `helloworld` module as an example.)
|
- 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 Bulgarian translations for MagicMirror² and Alert module.
|
||||||
- Add graceful shutdown of modules by calling `stop` function of each `node_helper` on SIGINT before exiting.
|
- Add graceful shutdown of modules by calling `stop` function of each `node_helper` on SIGINT before exiting.
|
||||||
|
@ -429,6 +466,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Add option for decimal symbols other than the decimal point for temperature values in both default weather modules: WeatherForecast and CurrentWeather.
|
- Add option for decimal symbols other than the decimal point for temperature values in both default weather modules: WeatherForecast and CurrentWeather.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed issue with calendar module showing more than `maximumEntries` allows
|
- Fixed issue with calendar module showing more than `maximumEntries` allows
|
||||||
- WeatherForecast and CurrentWeather are now using HTTPS instead of HTTP
|
- WeatherForecast and CurrentWeather are now using HTTPS instead of HTTP
|
||||||
- Correcting translation for Indonesian language
|
- Correcting translation for Indonesian language
|
||||||
|
@ -439,9 +477,11 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Remove Roboto fonts files inside `fonts` and these are installed by npm install command.
|
- Remove Roboto fonts files inside `fonts` and these are installed by npm install command.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add `clientonly` script to start only the electron client for a remote server.
|
- 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 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 `.vscode/` folder to `.gitignore` to keep custom Visual Studio Code config out of git.
|
||||||
|
@ -458,6 +498,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Add Slack badge to Readme.
|
- Add Slack badge to Readme.
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Changed 'default.js' - listen on all attached interfaces by default.
|
- Changed 'default.js' - listen on all attached interfaces by default.
|
||||||
- Add execution of `npm list` after the test are ran in Travis CI.
|
- Add execution of `npm list` after the test are ran in Travis CI.
|
||||||
- Change hooks for the vendors e2e tests.
|
- Change hooks for the vendors e2e tests.
|
||||||
|
@ -466,6 +507,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Set version of the `express-ipfilter` on 0.3.1.
|
- Set version of the `express-ipfilter` on 0.3.1.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed issue with incorrect alignment of analog clock when displayed in the center column of the MM.
|
- Fixed issue with incorrect alignment of analog clock when displayed in the center column of the MM.
|
||||||
- Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM.
|
- Fixed 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 'excludedEvents' count towards 'maximumEntries'.
|
||||||
|
@ -476,11 +518,13 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
## [2.1.2] - 2017-07-01
|
## [2.1.2] - 2017-07-01
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Revert Docker related changes in favor of [docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror). All Docker images are outsourced. ([#856](https://github.com/MichMich/MagicMirror/pull/856))
|
- Revert Docker related changes in favor of [docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror). All Docker images are outsourced. ([#856](https://github.com/MichMich/MagicMirror/pull/856))
|
||||||
- Change Docker base image (Debian + Node) to an arm based distro (AlpineARM + Node) ([#846](https://github.com/MichMich/MagicMirror/pull/846))
|
- Change Docker base image (Debian + Node) to an arm based distro (AlpineARM + Node) ([#846](https://github.com/MichMich/MagicMirror/pull/846))
|
||||||
- Fix the dockerfile to have it running from the first time.
|
- Fix the dockerfile to have it running from the first time.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add in option to wrap long calendar events to multiple lines using `wrapEvents` configuration option.
|
- Add in option to wrap long calendar events to multiple lines using `wrapEvents` configuration option.
|
||||||
- Add test e2e `show title newsfeed` for newsfeed module.
|
- Add test e2e `show title newsfeed` for newsfeed module.
|
||||||
- Add task to check configuration file.
|
- Add task to check configuration file.
|
||||||
|
@ -499,11 +543,13 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Added Romanian translation.
|
- Added Romanian translation.
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Added missing keys to Polish translation.
|
- Added missing keys to Polish translation.
|
||||||
- Added missing key to German 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
|
### Fixed
|
||||||
|
|
||||||
- Fix instruction in README for using automatically installer script.
|
- Fix instruction in README for using automatically installer script.
|
||||||
- Bug of duplicated compliments as described in [here](https://forum.magicmirror.builders/topic/2381/compliments-module-stops-cycling-compliments).
|
- Bug of duplicated compliments as described in [here](https://forum.magicmirror.builders/topic/2381/compliments-module-stops-cycling-compliments).
|
||||||
- Fix double message about port when server is starting
|
- Fix double message about port when server is starting
|
||||||
|
@ -517,6 +563,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Add `anytime` group for Compliments module.
|
- 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.
|
- Installer: Use init config.js from config.js.sample.
|
||||||
|
@ -532,8 +579,9 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Restructured Test Suite.
|
- Restructured Test Suite.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)).
|
- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)).
|
||||||
- Calendar-specific support for `maximumEntries`, and ` maximumNumberOfDays`.
|
- Calendar-specific support for `maximumEntries`, and `maximumNumberOfDays`.
|
||||||
- Add loaded function to modules, providing an async callback.
|
- 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)
|
- 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.
|
- Add use pm2 for manager process into Installer RaspberryPi script.
|
||||||
|
@ -574,6 +622,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Added a configurable Week section to the clock module.
|
- Added a configurable Week section to the clock module.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Update .gitignore to not ignore default modules folder.
|
- Update .gitignore to not ignore default modules folder.
|
||||||
- Remove white flash on boot up.
|
- Remove white flash on boot up.
|
||||||
- Added `update` in Raspberry Pi installation script.
|
- Added `update` in Raspberry Pi installation script.
|
||||||
|
@ -590,6 +639,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Finnish translation.
|
- Finnish translation.
|
||||||
- Danish translation.
|
- Danish translation.
|
||||||
- Turkish translation.
|
- Turkish translation.
|
||||||
|
@ -620,6 +670,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Add root_path for global vars
|
- Add root_path for global vars
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Modified translations for Frysk.
|
- Modified translations for Frysk.
|
||||||
- Modified core English translations.
|
- Modified core English translations.
|
||||||
- Updated package.json as a result of Snyk security update.
|
- Updated package.json as a result of Snyk security update.
|
||||||
|
@ -630,6 +681,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Modules are now secure, and Helmet is now used to prevent abuse of the Mirror's API.
|
- Modules are now secure, and Helmet is now used to prevent abuse of the Mirror's API.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Solve an issue where module margins would appear when the first module of a section was hidden.
|
- Solve an issue where module margins would appear when the first module of a section was hidden.
|
||||||
- Solved visual display errors on chrome, if all modules in one of the right sections are hidden.
|
- Solved visual display errors on chrome, if all modules in one of the right sections are hidden.
|
||||||
- Global and Module default config values are no longer modified when setting config values.
|
- Global and Module default config values are no longer modified when setting config values.
|
||||||
|
@ -640,6 +692,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
## [2.0.5] - 2016-09-20
|
## [2.0.5] - 2016-09-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'.
|
- Added ability to remove tags from the beginning or end of newsfeed items in 'newsfeed.js'.
|
||||||
- Added ability to define "the day after tomorrow" for calendar events (Definition for German and Dutch already included).
|
- Added ability to define "the day after tomorrow" for calendar events (Definition for German and Dutch already included).
|
||||||
- Added CII Badge (we are compliant with the CII Best Practices)
|
- Added CII Badge (we are compliant with the CII Best Practices)
|
||||||
|
@ -647,11 +700,13 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Add the ability to turn off and on the date display in the Clock Module
|
- Add the ability to turn off and on the date display in the Clock Module
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix typo in installer.
|
- Fix typo in installer.
|
||||||
- Add message to unsupported Pi error to mention that Pi Zeros must use server only mode, as ARMv6 is unsupported. Closes #374.
|
- Add message to unsupported Pi error to mention that Pi Zeros must use server only mode, as ARMv6 is unsupported. Closes #374.
|
||||||
- Fix API url for weather API.
|
- Fix API url for weather API.
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Force fullscreen when kioskmode is active.
|
- Force fullscreen when kioskmode is active.
|
||||||
- Update the .github templates and information with more modern information.
|
- Update the .github templates and information with more modern information.
|
||||||
- Update the Gruntfile with a more functional StyleLint implementation.
|
- Update the Gruntfile with a more functional StyleLint implementation.
|
||||||
|
@ -659,6 +714,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
## [2.0.4] - 2016-08-07
|
## [2.0.4] - 2016-08-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Brazilian Portuguese Translation.
|
- Brazilian Portuguese Translation.
|
||||||
- Option to enable Kiosk mode.
|
- Option to enable Kiosk mode.
|
||||||
- Added ability to start the app with Dev Tools.
|
- Added ability to start the app with Dev Tools.
|
||||||
|
@ -666,6 +722,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Greek Translation
|
- Greek Translation
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Prevent `getModules()` selectors from returning duplicate entries.
|
- Prevent `getModules()` selectors from returning duplicate entries.
|
||||||
- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337))
|
- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337))
|
||||||
- Corrected grammar in `module.js` from 'suspend' to 'suspended'.
|
- Corrected grammar in `module.js` from 'suspend' to 'suspended'.
|
||||||
|
@ -674,55 +731,72 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
|
||||||
- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MichMich/MagicMirror/issues/388))
|
- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MichMich/MagicMirror/issues/388))
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
- Updated package.json to fix possible vulnerabilities. (Using Snyk)
|
- Updated package.json to fix possible vulnerabilities. (Using Snyk)
|
||||||
- Updated weathericons
|
- Updated weathericons
|
||||||
- Updated default weatherforecast to work with the new icons.
|
- Updated default weatherforecast to work with the new icons.
|
||||||
- More detailed error message in case config file couldn't be loaded.
|
- More detailed error message in case config file couldn't be loaded.
|
||||||
|
|
||||||
## [2.0.3] - 2016-07-12
|
## [2.0.3] - 2016-07-12
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add max newsitems parameter to the newsfeed module.
|
- Add max newsitems parameter to the newsfeed module.
|
||||||
- Translations for Simplified Chinese, Traditional Chinese and Japanese.
|
- Translations for Simplified Chinese, Traditional Chinese and Japanese.
|
||||||
- Polish Translation
|
- Polish Translation
|
||||||
- Add an analog clock in addition to the digital one.
|
- Add an analog clock in addition to the digital one.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300))
|
- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300))
|
||||||
- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319))
|
- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Added default string to calendar titleReplace.
|
- Added default string to calendar titleReplace.
|
||||||
|
|
||||||
## [2.0.2] - 2016-06-05
|
## [2.0.2] - 2016-06-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Norwegian Translations (nb and nn)
|
- Norwegian Translations (nb and nn)
|
||||||
- Portuguese Translation
|
- Portuguese Translation
|
||||||
- Swedish Translation
|
- Swedish Translation
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Added reference to Italian Translation.
|
- Added reference to Italian Translation.
|
||||||
- Added the missing NE translation to all languages. [#344](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.
|
- Added proper User-Agent string to calendar call.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Add option to use locationID in weather modules.
|
- Add option to use locationID in weather modules.
|
||||||
|
|
||||||
## [2.0.1] - 2016-05-18
|
## [2.0.1] - 2016-05-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Changelog
|
- Changelog
|
||||||
- Italian Translation
|
- Italian Translation
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Improve the installer by fetching the latest Node.js without any 3rd party interferences.
|
- Improve the installer by fetching the latest Node.js without any 3rd party interferences.
|
||||||
|
|
||||||
## [2.0.0] - 2016-05-03
|
## [2.0.0] - 2016-05-03
|
||||||
|
|
||||||
### Initial release of MagicMirror²
|
### Initial release of MagicMirror²
|
||||||
|
|
||||||
It includes (but is not limited to) the following features:
|
It includes (but is not limited to) the following features:
|
||||||
|
|
||||||
- Modular system allowing 3rd party plugins.
|
- Modular system allowing 3rd party plugins.
|
||||||
- An Node/Electron based application taking away the need for external servers or browsers.
|
- An Node/Electron based application taking away the need for external servers or browsers.
|
||||||
- A complete development API documentation.
|
- A complete development API documentation.
|
||||||
- Small cute fairies that kiss you while you sleep.
|
- Small cute fairies that kiss you while you sleep.
|
||||||
|
|
||||||
## [1.0.0] - 2014-02-16
|
## [1.0.0] - 2014-02-16
|
||||||
|
|
||||||
### Initial release of MagicMirror.
|
### Initial release of MagicMirror.
|
||||||
|
|
||||||
This was part of the blogpost: [https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the](https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the)
|
This was part of the blogpost: [https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the](https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
=====================
|
|
||||||
|
|
||||||
Copyright © 2016-2019 Michael Teeuw
|
Copyright © 2016-2019 Michael Teeuw
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
MagicMirror² focuses on a modular plugin system and uses [Electron](https://www.electronjs.org/) as an application wrapper. So no more web server or browser installs necessary!
|
MagicMirror² focuses on a modular plugin system and uses [Electron](https://www.electronjs.org/) as an application wrapper. So no more web server or browser installs necessary!
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
For the full documentation including **[installation instructions](https://docs.magicmirror.builders/getting-started/installation.html)**, please visit our dedicated documentation website: [https://docs.magicmirror.builders](https://docs.magicmirror.builders).
|
For the full documentation including **[installation instructions](https://docs.magicmirror.builders/getting-started/installation.html)**, please visit our dedicated documentation website: [https://docs.magicmirror.builders](https://docs.magicmirror.builders).
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
- Website: [https://magicmirror.builders](https://magicmirror.builders)
|
- Website: [https://magicmirror.builders](https://magicmirror.builders)
|
||||||
- Documentation: [https://docs.magicmirror.builders](https://docs.magicmirror.builders)
|
- Documentation: [https://docs.magicmirror.builders](https://docs.magicmirror.builders)
|
||||||
- Forum: [https://forum.magicmirror.builders](https://forum.magicmirror.builders)
|
- Forum: [https://forum.magicmirror.builders](https://forum.magicmirror.builders)
|
||||||
|
@ -28,7 +30,6 @@ For the full documentation including **[installation instructions](https://docs.
|
||||||
|
|
||||||
Contributions of all kinds are welcome, not only in the form of code but also with regards bug reports and documentation. For the full contribution guidelines, check out: [https://docs.magicmirror.builders/getting-started/contributing.html](https://docs.magicmirror.builders/getting-started/contributing.html)
|
Contributions of all kinds are welcome, not only in the form of code but also with regards bug reports and documentation. For the full contribution guidelines, check out: [https://docs.magicmirror.builders/getting-started/contributing.html](https://docs.magicmirror.builders/getting-started/contributing.html)
|
||||||
|
|
||||||
|
|
||||||
## Enjoying MagicMirror? Consider a donation!
|
## Enjoying MagicMirror? Consider a donation!
|
||||||
|
|
||||||
MagicMirror² is opensource and free. That doesn't mean we don't need any money.
|
MagicMirror² is opensource and free. That doesn't mean we don't need any money.
|
||||||
|
|
|
@ -32,16 +32,16 @@
|
||||||
var configData = "";
|
var configData = "";
|
||||||
|
|
||||||
// Gather incoming data
|
// Gather incoming data
|
||||||
response.on("data", function(chunk) {
|
response.on("data", function (chunk) {
|
||||||
configData += chunk;
|
configData += chunk;
|
||||||
});
|
});
|
||||||
// Resolve promise at the end of the HTTP/HTTPS stream
|
// Resolve promise at the end of the HTTP/HTTPS stream
|
||||||
response.on("end", function() {
|
response.on("end", function () {
|
||||||
resolve(JSON.parse(configData));
|
resolve(JSON.parse(configData));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
request.on("error", function(error) {
|
request.on("error", function (error) {
|
||||||
reject(new Error(`Unable to read config from server (${url} (${error.message}`));
|
reject(new Error(`Unable to read config from server (${url} (${error.message}`));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -96,7 +96,6 @@
|
||||||
console.log(`There something wrong. The clientonly is not running code ${code}`);
|
console.log(`There something wrong. The clientonly is not running code ${code}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(function (reason) {
|
.catch(function (reason) {
|
||||||
fail(`Unable to connect to server: (${reason})`);
|
fail(`Unable to connect to server: (${reason})`);
|
||||||
|
@ -104,4 +103,4 @@
|
||||||
} else {
|
} else {
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}());
|
})();
|
||||||
|
|
|
@ -2,21 +2,14 @@
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
src:
|
src: local("Roboto Thin"), local("Roboto-Thin"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff") format("woff");
|
||||||
local("Roboto Thin"),
|
|
||||||
local("Roboto-Thin"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff2") format("woff2"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Roboto Condensed";
|
font-family: "Roboto Condensed";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
src:
|
src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Light.woff2") format("woff2"),
|
||||||
local("Roboto Condensed Light"),
|
|
||||||
local("RobotoCondensed-Light"),
|
|
||||||
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.woff") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,10 +17,7 @@
|
||||||
font-family: "Roboto Condensed";
|
font-family: "Roboto Condensed";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src:
|
src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Regular.woff2") format("woff2"),
|
||||||
local("Roboto Condensed"),
|
|
||||||
local("RobotoCondensed-Regular"),
|
|
||||||
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.woff") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +25,7 @@
|
||||||
font-family: "Roboto Condensed";
|
font-family: "Roboto Condensed";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
src:
|
src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Bold.woff2") format("woff2"),
|
||||||
local("Roboto Condensed Bold"),
|
|
||||||
local("RobotoCondensed-Bold"),
|
|
||||||
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.woff") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,42 +33,26 @@
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src:
|
src: local("Roboto"), local("Roboto-Regular"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff");
|
||||||
local("Roboto"),
|
|
||||||
local("Roboto-Regular"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
src:
|
src: local("Roboto Medium"), local("Roboto-Medium"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff") format("woff");
|
||||||
local("Roboto Medium"),
|
|
||||||
local("Roboto-Medium"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff2") format("woff2"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
src:
|
src: local("Roboto Bold"), local("Roboto-Bold"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff") format("woff");
|
||||||
local("Roboto Bold"),
|
|
||||||
local("Roboto-Bold"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff2") format("woff2"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
src:
|
src: local("Roboto Light"), local("Roboto-Light"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff") format("woff");
|
||||||
local("Roboto Light"),
|
|
||||||
local("Roboto-Light"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff2") format("woff2"),
|
|
||||||
url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
44
js/app.js
44
js/app.js
|
@ -44,7 +44,7 @@ process.on("uncaughtException", function (err) {
|
||||||
|
|
||||||
/* App - The core app.
|
/* App - The core app.
|
||||||
*/
|
*/
|
||||||
var App = function() {
|
var App = function () {
|
||||||
var nodeHelpers = [];
|
var nodeHelpers = [];
|
||||||
|
|
||||||
/* loadConfig(callback)
|
/* loadConfig(callback)
|
||||||
|
@ -53,14 +53,14 @@ var App = function() {
|
||||||
*
|
*
|
||||||
* argument callback function - The callback function.
|
* argument callback function - The callback function.
|
||||||
*/
|
*/
|
||||||
var loadConfig = function(callback) {
|
var loadConfig = function (callback) {
|
||||||
console.log("Loading config ...");
|
console.log("Loading config ...");
|
||||||
var defaults = require(__dirname + "/defaults.js");
|
var defaults = require(__dirname + "/defaults.js");
|
||||||
|
|
||||||
// For this check proposed to TestSuite
|
// For this check proposed to TestSuite
|
||||||
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
|
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
|
||||||
var configFilename = path.resolve(global.root_path + "/config/config.js");
|
var configFilename = path.resolve(global.root_path + "/config/config.js");
|
||||||
if (typeof(global.configuration_file) !== "undefined") {
|
if (typeof global.configuration_file !== "undefined") {
|
||||||
configFilename = path.resolve(global.configuration_file);
|
configFilename = path.resolve(global.configuration_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,23 +82,19 @@ var App = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var checkDeprecatedOptions = function(userConfig) {
|
var checkDeprecatedOptions = function (userConfig) {
|
||||||
var deprecated = require(global.root_path + "/js/deprecated.js");
|
var deprecated = require(global.root_path + "/js/deprecated.js");
|
||||||
var deprecatedOptions = deprecated.configs;
|
var deprecatedOptions = deprecated.configs;
|
||||||
|
|
||||||
var usedDeprecated = [];
|
var usedDeprecated = [];
|
||||||
|
|
||||||
deprecatedOptions.forEach(function(option) {
|
deprecatedOptions.forEach(function (option) {
|
||||||
if (userConfig.hasOwnProperty(option)) {
|
if (userConfig.hasOwnProperty(option)) {
|
||||||
usedDeprecated.push(option);
|
usedDeprecated.push(option);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (usedDeprecated.length > 0) {
|
if (usedDeprecated.length > 0) {
|
||||||
console.warn(Utils.colors.warn(
|
console.warn(Utils.colors.warn("WARNING! Your config is using deprecated options: " + usedDeprecated.join(", ") + ". Check README and CHANGELOG for more up-to-date ways of getting the same functionality."));
|
||||||
"WARNING! Your config is using deprecated options: " +
|
|
||||||
usedDeprecated.join(", ") +
|
|
||||||
". Check README and CHANGELOG for more up-to-date ways of getting the same functionality.")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,8 +103,7 @@ var App = function() {
|
||||||
*
|
*
|
||||||
* argument module string - The name of the module (including subpath).
|
* argument module string - The name of the module (including subpath).
|
||||||
*/
|
*/
|
||||||
var loadModule = function(module, callback) {
|
var loadModule = function (module, callback) {
|
||||||
|
|
||||||
var elements = module.split("/");
|
var elements = module.split("/");
|
||||||
var moduleName = elements[elements.length - 1];
|
var moduleName = elements[elements.length - 1];
|
||||||
var moduleFolder = __dirname + "/../modules/" + module;
|
var moduleFolder = __dirname + "/../modules/" + module;
|
||||||
|
@ -156,13 +151,13 @@ var App = function() {
|
||||||
*
|
*
|
||||||
* argument module string - The name of the module (including subpath).
|
* argument module string - The name of the module (including subpath).
|
||||||
*/
|
*/
|
||||||
var loadModules = function(modules, callback) {
|
var loadModules = function (modules, callback) {
|
||||||
console.log("Loading module helpers ...");
|
console.log("Loading module helpers ...");
|
||||||
|
|
||||||
var loadNextModule = function() {
|
var loadNextModule = function () {
|
||||||
if (modules.length > 0) {
|
if (modules.length > 0) {
|
||||||
var nextModule = modules[0];
|
var nextModule = modules[0];
|
||||||
loadModule(nextModule, function() {
|
loadModule(nextModule, function () {
|
||||||
modules = modules.slice(1);
|
modules = modules.slice(1);
|
||||||
loadNextModule();
|
loadNextModule();
|
||||||
});
|
});
|
||||||
|
@ -205,9 +200,8 @@ var App = function() {
|
||||||
*
|
*
|
||||||
* argument callback function - The callback function.
|
* argument callback function - The callback function.
|
||||||
*/
|
*/
|
||||||
this.start = function(callback) {
|
this.start = function (callback) {
|
||||||
|
loadConfig(function (c) {
|
||||||
loadConfig(function(c) {
|
|
||||||
config = c;
|
config = c;
|
||||||
|
|
||||||
var modules = [];
|
var modules = [];
|
||||||
|
@ -219,8 +213,8 @@ var App = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadModules(modules, function() {
|
loadModules(modules, function () {
|
||||||
var server = new Server(config, function(app, io) {
|
var server = new Server(config, function (app, io) {
|
||||||
console.log("Server started ...");
|
console.log("Server started ...");
|
||||||
|
|
||||||
for (var h in nodeHelpers) {
|
for (var h in nodeHelpers) {
|
||||||
|
@ -245,7 +239,7 @@ var App = function() {
|
||||||
* This calls each node_helper's STOP() function, if it exists.
|
* This calls each node_helper's STOP() function, if it exists.
|
||||||
* Added to fix #1056
|
* Added to fix #1056
|
||||||
*/
|
*/
|
||||||
this.stop = function() {
|
this.stop = function () {
|
||||||
for (var h in nodeHelpers) {
|
for (var h in nodeHelpers) {
|
||||||
var nodeHelper = nodeHelpers[h];
|
var nodeHelper = nodeHelpers[h];
|
||||||
if (typeof nodeHelper.stop === "function") {
|
if (typeof nodeHelper.stop === "function") {
|
||||||
|
@ -262,7 +256,9 @@ var App = function() {
|
||||||
*/
|
*/
|
||||||
process.on("SIGINT", () => {
|
process.on("SIGINT", () => {
|
||||||
console.log("[SIGINT] Received. Shutting down server...");
|
console.log("[SIGINT] Received. Shutting down server...");
|
||||||
setTimeout(() => { process.exit(0); }, 3000); // Force quit after 3 seconds
|
setTimeout(() => {
|
||||||
|
process.exit(0);
|
||||||
|
}, 3000); // Force quit after 3 seconds
|
||||||
this.stop();
|
this.stop();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
@ -271,7 +267,9 @@ var App = function() {
|
||||||
*/
|
*/
|
||||||
process.on("SIGTERM", () => {
|
process.on("SIGTERM", () => {
|
||||||
console.log("[SIGTERM] Received. Shutting down server...");
|
console.log("[SIGTERM] Received. Shutting down server...");
|
||||||
setTimeout(() => { process.exit(0); }, 3000); // Force quit after 3 seconds
|
setTimeout(() => {
|
||||||
|
process.exit(0);
|
||||||
|
}, 3000); // Force quit after 3 seconds
|
||||||
this.stop();
|
this.stop();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -53,13 +53,15 @@ function checkConfigFile() {
|
||||||
console.info(Utils.colors.info("Checking file... "), configFileName);
|
console.info(Utils.colors.info("Checking file... "), configFileName);
|
||||||
// I'm not sure if all ever is utf-8
|
// I'm not sure if all ever is utf-8
|
||||||
fs.readFile(configFileName, "utf-8", function (err, data) {
|
fs.readFile(configFileName, "utf-8", function (err, data) {
|
||||||
if (err) { throw err; }
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
const messages = linter.verify(data, config);
|
const messages = linter.verify(data, config);
|
||||||
if (messages.length === 0) {
|
if (messages.length === 0) {
|
||||||
console.log("Your configuration file doesn't contain syntax errors :)");
|
console.log("Your configuration file doesn't contain syntax errors :)");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
messages.forEach(error => {
|
messages.forEach((error) => {
|
||||||
console.log("Line", error.line, "col", error.column, error.message);
|
console.log("Line", error.line, "col", error.column, error.message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
16
js/class.js
16
js/class.js
|
@ -9,10 +9,14 @@
|
||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
var initializing = false;
|
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)
|
// The base Class implementation (does nothing)
|
||||||
this.Class = function () { };
|
this.Class = function () {};
|
||||||
|
|
||||||
// Create a new Class that inherits from this class
|
// Create a new Class that inherits from this class
|
||||||
Class.extend = function (prop) {
|
Class.extend = function (prop) {
|
||||||
|
@ -32,8 +36,9 @@
|
||||||
// Copy the properties over onto the new prototype
|
// Copy the properties over onto the new prototype
|
||||||
for (var name in prop) {
|
for (var name in prop) {
|
||||||
// Check if we're overwriting an existing function
|
// Check if we're overwriting an existing function
|
||||||
prototype[name] = typeof prop[name] === "function" &&
|
prototype[name] =
|
||||||
typeof _super[name] === "function" && fnTest.test(prop[name]) ? (function (name, fn) {
|
typeof prop[name] === "function" && typeof _super[name] === "function" && fnTest.test(prop[name])
|
||||||
|
? (function (name, fn) {
|
||||||
return function () {
|
return function () {
|
||||||
var tmp = this._super;
|
var tmp = this._super;
|
||||||
|
|
||||||
|
@ -48,7 +53,8 @@
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
})(name, prop[name]) : prop[name];
|
})(name, prop[name])
|
||||||
|
: prop[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
// The dummy class constructor
|
// The dummy class constructor
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*/
|
*/
|
||||||
var address = "localhost";
|
var address = "localhost";
|
||||||
var port = 8080;
|
var port = 8080;
|
||||||
if (typeof(mmPort) !== "undefined") {
|
if (typeof mmPort !== "undefined") {
|
||||||
port = mmPort;
|
port = mmPort;
|
||||||
}
|
}
|
||||||
var defaults = {
|
var defaults = {
|
||||||
|
@ -68,14 +68,16 @@ var defaults = {
|
||||||
config: {
|
config: {
|
||||||
text: "www.michaelteeuw.nl"
|
text: "www.michaelteeuw.nl"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
paths: {
|
paths: {
|
||||||
modules: "modules",
|
modules: "modules",
|
||||||
vendor: "vendor"
|
vendor: "vendor"
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = defaults;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = defaults;
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var deprecated = {
|
var deprecated = {
|
||||||
configs: ["kioskmode"],
|
configs: ["kioskmode"]
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = deprecated;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = deprecated;
|
||||||
|
}
|
||||||
|
|
|
@ -62,21 +62,21 @@ function createWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set responders for window events.
|
// Set responders for window events.
|
||||||
mainWindow.on("closed", function() {
|
mainWindow.on("closed", function () {
|
||||||
mainWindow = null;
|
mainWindow = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.kioskmode) {
|
if (config.kioskmode) {
|
||||||
mainWindow.on("blur", function() {
|
mainWindow.on("blur", function () {
|
||||||
mainWindow.focus();
|
mainWindow.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindow.on("leave-full-screen", function() {
|
mainWindow.on("leave-full-screen", function () {
|
||||||
mainWindow.setFullScreen(true);
|
mainWindow.setFullScreen(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindow.on("resize", function() {
|
mainWindow.on("resize", function () {
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
mainWindow.reload();
|
mainWindow.reload();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
|
@ -85,17 +85,17 @@ function createWindow() {
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
// This method will be called when Electron has finished
|
||||||
// initialization and is ready to create browser windows.
|
// initialization and is ready to create browser windows.
|
||||||
app.on("ready", function() {
|
app.on("ready", function () {
|
||||||
console.log("Launching application.");
|
console.log("Launching application.");
|
||||||
createWindow();
|
createWindow();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
// Quit when all windows are closed.
|
||||||
app.on("window-all-closed", function() {
|
app.on("window-all-closed", function () {
|
||||||
createWindow();
|
createWindow();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on("activate", function() {
|
app.on("activate", function () {
|
||||||
// On OS X it's common to re-create a window in the app when the
|
// On OS X it's common to re-create a window in the app when the
|
||||||
// dock icon is clicked and there are no other windows open.
|
// dock icon is clicked and there are no other windows open.
|
||||||
if (mainWindow === null) {
|
if (mainWindow === null) {
|
||||||
|
@ -112,7 +112,9 @@ app.on("activate", function() {
|
||||||
app.on("before-quit", (event) => {
|
app.on("before-quit", (event) => {
|
||||||
console.log("Shutting down server...");
|
console.log("Shutting down server...");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setTimeout(() => { process.exit(0); }, 3000); // Force-quit after 3 seconds.
|
setTimeout(() => {
|
||||||
|
process.exit(0);
|
||||||
|
}, 3000); // Force-quit after 3 seconds.
|
||||||
core.stop();
|
core.stop();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
@ -120,7 +122,7 @@ app.on("before-quit", (event) => {
|
||||||
// Start the core application if server is run on localhost
|
// Start the core application if server is run on localhost
|
||||||
// This starts all node helpers and starts the webserver.
|
// 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) {
|
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) > -1) {
|
||||||
core.start(function(c) {
|
core.start(function (c) {
|
||||||
config = c;
|
config = c;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
72
js/loader.js
72
js/loader.js
|
@ -6,8 +6,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var Loader = (function() {
|
var Loader = (function () {
|
||||||
|
|
||||||
/* Create helper variables */
|
/* Create helper variables */
|
||||||
|
|
||||||
var loadedModuleFiles = [];
|
var loadedModuleFiles = [];
|
||||||
|
@ -19,14 +18,13 @@ var Loader = (function() {
|
||||||
/* loadModules()
|
/* loadModules()
|
||||||
* Loops thru all modules and requests load for every module.
|
* Loops thru all modules and requests load for every module.
|
||||||
*/
|
*/
|
||||||
var loadModules = function() {
|
var loadModules = function () {
|
||||||
|
|
||||||
var moduleData = getModuleData();
|
var moduleData = getModuleData();
|
||||||
|
|
||||||
var loadNextModule = function() {
|
var loadNextModule = function () {
|
||||||
if (moduleData.length > 0) {
|
if (moduleData.length > 0) {
|
||||||
var nextModule = moduleData[0];
|
var nextModule = moduleData[0];
|
||||||
loadModule(nextModule, function() {
|
loadModule(nextModule, function () {
|
||||||
moduleData = moduleData.slice(1);
|
moduleData = moduleData.slice(1);
|
||||||
loadNextModule();
|
loadNextModule();
|
||||||
});
|
});
|
||||||
|
@ -35,11 +33,10 @@ var Loader = (function() {
|
||||||
// This is done after all the modules so we can
|
// This is done after all the modules so we can
|
||||||
// overwrite all the defined styles.
|
// overwrite all the defined styles.
|
||||||
|
|
||||||
loadFile(config.customCss, function() {
|
loadFile(config.customCss, function () {
|
||||||
// custom.css loaded. Start all modules.
|
// custom.css loaded. Start all modules.
|
||||||
startModules();
|
startModules();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,7 +46,7 @@ var Loader = (function() {
|
||||||
/* startModules()
|
/* startModules()
|
||||||
* Loops thru all modules and requests start for every module.
|
* Loops thru all modules and requests start for every module.
|
||||||
*/
|
*/
|
||||||
var startModules = function() {
|
var startModules = function () {
|
||||||
for (var m in moduleObjects) {
|
for (var m in moduleObjects) {
|
||||||
var module = moduleObjects[m];
|
var module = moduleObjects[m];
|
||||||
module.start();
|
module.start();
|
||||||
|
@ -64,7 +61,7 @@ var Loader = (function() {
|
||||||
*
|
*
|
||||||
* return array - module data as configured in config
|
* return array - module data as configured in config
|
||||||
*/
|
*/
|
||||||
var getAllModules = function() {
|
var getAllModules = function () {
|
||||||
return config.modules;
|
return config.modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,7 +70,7 @@ var Loader = (function() {
|
||||||
*
|
*
|
||||||
* return array - Module information.
|
* return array - Module information.
|
||||||
*/
|
*/
|
||||||
var getModuleData = function() {
|
var getModuleData = function () {
|
||||||
var modules = getAllModules();
|
var modules = getAllModules();
|
||||||
var moduleFiles = [];
|
var moduleFiles = [];
|
||||||
|
|
||||||
|
@ -97,12 +94,12 @@ var Loader = (function() {
|
||||||
index: m,
|
index: m,
|
||||||
identifier: "module_" + m + "_" + module,
|
identifier: "module_" + m + "_" + module,
|
||||||
name: moduleName,
|
name: moduleName,
|
||||||
path: moduleFolder + "/" ,
|
path: moduleFolder + "/",
|
||||||
file: moduleName + ".js",
|
file: moduleName + ".js",
|
||||||
position: moduleData.position,
|
position: moduleData.position,
|
||||||
header: moduleData.header,
|
header: moduleData.header,
|
||||||
config: moduleData.config,
|
config: moduleData.config,
|
||||||
classes: (typeof moduleData.classes !== "undefined") ? moduleData.classes + " " + module : module
|
classes: typeof moduleData.classes !== "undefined" ? moduleData.classes + " " + module : module
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,13 +112,13 @@ var Loader = (function() {
|
||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
* argument module object - Information about the module we want to load.
|
* argument module object - Information about the module we want to load.
|
||||||
*/
|
*/
|
||||||
var loadModule = function(module, callback) {
|
var loadModule = function (module, callback) {
|
||||||
var url = module.path + "/" + module.file;
|
var url = module.path + "/" + module.file;
|
||||||
|
|
||||||
var afterLoad = function() {
|
var afterLoad = function () {
|
||||||
var moduleObject = Module.create(module.name);
|
var moduleObject = Module.create(module.name);
|
||||||
if (moduleObject) {
|
if (moduleObject) {
|
||||||
bootstrapModule(module, moduleObject, function() {
|
bootstrapModule(module, moduleObject, function () {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,7 +129,7 @@ var Loader = (function() {
|
||||||
if (loadedModuleFiles.indexOf(url) !== -1) {
|
if (loadedModuleFiles.indexOf(url) !== -1) {
|
||||||
afterLoad();
|
afterLoad();
|
||||||
} else {
|
} else {
|
||||||
loadFile(url, function() {
|
loadFile(url, function () {
|
||||||
loadedModuleFiles.push(url);
|
loadedModuleFiles.push(url);
|
||||||
afterLoad();
|
afterLoad();
|
||||||
});
|
});
|
||||||
|
@ -146,16 +143,16 @@ var Loader = (function() {
|
||||||
* argument mObj object - Modules instance.
|
* argument mObj object - Modules instance.
|
||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
*/
|
*/
|
||||||
var bootstrapModule = function(module, mObj, callback) {
|
var bootstrapModule = function (module, mObj, callback) {
|
||||||
Log.info("Bootstrapping module: " + module.name);
|
Log.info("Bootstrapping module: " + module.name);
|
||||||
|
|
||||||
mObj.setData(module);
|
mObj.setData(module);
|
||||||
|
|
||||||
mObj.loadScripts(function() {
|
mObj.loadScripts(function () {
|
||||||
Log.log("Scripts loaded for: " + module.name);
|
Log.log("Scripts loaded for: " + module.name);
|
||||||
mObj.loadStyles(function() {
|
mObj.loadStyles(function () {
|
||||||
Log.log("Styles loaded for: " + module.name);
|
Log.log("Styles loaded for: " + module.name);
|
||||||
mObj.loadTranslations(function() {
|
mObj.loadTranslations(function () {
|
||||||
Log.log("Translations loaded for: " + module.name);
|
Log.log("Translations loaded for: " + module.name);
|
||||||
moduleObjects.push(mObj);
|
moduleObjects.push(mObj);
|
||||||
callback();
|
callback();
|
||||||
|
@ -170,8 +167,7 @@ var Loader = (function() {
|
||||||
* argument fileName string - Path of the file we want to load.
|
* argument fileName string - Path of the file we want to load.
|
||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
*/
|
*/
|
||||||
var loadFile = function(fileName, callback) {
|
var loadFile = function (fileName, callback) {
|
||||||
|
|
||||||
var extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
|
var extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
|
||||||
|
|
||||||
switch (extension.toLowerCase()) {
|
switch (extension.toLowerCase()) {
|
||||||
|
@ -180,12 +176,16 @@ var Loader = (function() {
|
||||||
var script = document.createElement("script");
|
var script = document.createElement("script");
|
||||||
script.type = "text/javascript";
|
script.type = "text/javascript";
|
||||||
script.src = fileName;
|
script.src = fileName;
|
||||||
script.onload = function() {
|
script.onload = function () {
|
||||||
if (typeof callback === "function") {callback();}
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
script.onerror = function() {
|
script.onerror = function () {
|
||||||
console.error("Error on loading script:", fileName);
|
console.error("Error on loading script:", fileName);
|
||||||
if (typeof callback === "function") {callback();}
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementsByTagName("body")[0].appendChild(script);
|
document.getElementsByTagName("body")[0].appendChild(script);
|
||||||
|
@ -196,12 +196,16 @@ var Loader = (function() {
|
||||||
stylesheet.rel = "stylesheet";
|
stylesheet.rel = "stylesheet";
|
||||||
stylesheet.type = "text/css";
|
stylesheet.type = "text/css";
|
||||||
stylesheet.href = fileName;
|
stylesheet.href = fileName;
|
||||||
stylesheet.onload = function() {
|
stylesheet.onload = function () {
|
||||||
if (typeof callback === "function") {callback();}
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
stylesheet.onerror = function() {
|
stylesheet.onerror = function () {
|
||||||
console.error("Error on loading stylesheet:", fileName);
|
console.error("Error on loading stylesheet:", fileName);
|
||||||
if (typeof callback === "function") {callback();}
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementsByTagName("head")[0].appendChild(stylesheet);
|
document.getElementsByTagName("head")[0].appendChild(stylesheet);
|
||||||
|
@ -211,11 +215,10 @@ var Loader = (function() {
|
||||||
|
|
||||||
/* Public Methods */
|
/* Public Methods */
|
||||||
return {
|
return {
|
||||||
|
|
||||||
/* loadModules()
|
/* loadModules()
|
||||||
* Load all modules as defined in the config.
|
* Load all modules as defined in the config.
|
||||||
*/
|
*/
|
||||||
loadModules: function() {
|
loadModules: function () {
|
||||||
loadModules();
|
loadModules();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -227,8 +230,7 @@ var Loader = (function() {
|
||||||
* argument module Module Object - the module that calls the loadFile function.
|
* argument module Module Object - the module that calls the loadFile function.
|
||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
*/
|
*/
|
||||||
loadFile: function(fileName, module, callback) {
|
loadFile: function (fileName, module, callback) {
|
||||||
|
|
||||||
if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) {
|
if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) {
|
||||||
Log.log("File already loaded: " + fileName);
|
Log.log("File already loaded: " + fileName);
|
||||||
callback();
|
callback();
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
const Log = (function() {
|
const Log = (function () {
|
||||||
return {
|
return {
|
||||||
info: Function.prototype.bind.call(console.info, console),
|
info: Function.prototype.bind.call(console.info, console),
|
||||||
log: Function.prototype.bind.call(console.log, console),
|
log: Function.prototype.bind.call(console.log, console),
|
||||||
|
|
133
js/main.js
133
js/main.js
|
@ -6,8 +6,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var MM = (function() {
|
var MM = (function () {
|
||||||
|
|
||||||
var modules = [];
|
var modules = [];
|
||||||
|
|
||||||
/* Private Methods */
|
/* Private Methods */
|
||||||
|
@ -16,10 +15,10 @@ var MM = (function() {
|
||||||
* Create dom objects for all modules that
|
* Create dom objects for all modules that
|
||||||
* are configured for a specific position.
|
* are configured for a specific position.
|
||||||
*/
|
*/
|
||||||
var createDomObjects = function() {
|
var createDomObjects = function () {
|
||||||
var domCreationPromises = [];
|
var domCreationPromises = [];
|
||||||
|
|
||||||
modules.forEach(function(module) {
|
modules.forEach(function (module) {
|
||||||
if (typeof module.data.position !== "string") {
|
if (typeof module.data.position !== "string") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -52,14 +51,16 @@ var MM = (function() {
|
||||||
|
|
||||||
var domCreationPromise = updateDom(module, 0);
|
var domCreationPromise = updateDom(module, 0);
|
||||||
domCreationPromises.push(domCreationPromise);
|
domCreationPromises.push(domCreationPromise);
|
||||||
domCreationPromise.then(function() {
|
domCreationPromise
|
||||||
|
.then(function () {
|
||||||
sendNotification("MODULE_DOM_CREATED", null, null, module);
|
sendNotification("MODULE_DOM_CREATED", null, null, module);
|
||||||
}).catch(Log.error);
|
})
|
||||||
|
.catch(Log.error);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateWrapperStates();
|
updateWrapperStates();
|
||||||
|
|
||||||
Promise.all(domCreationPromises).then(function() {
|
Promise.all(domCreationPromises).then(function () {
|
||||||
sendNotification("DOM_OBJECTS_CREATED");
|
sendNotification("DOM_OBJECTS_CREATED");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -69,8 +70,8 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* argument position string - The name of the position.
|
* argument position string - The name of the position.
|
||||||
*/
|
*/
|
||||||
var selectWrapper = function(position) {
|
var selectWrapper = function (position) {
|
||||||
var classes = position.replace("_"," ");
|
var classes = position.replace("_", " ");
|
||||||
var parentWrapper = document.getElementsByClassName(classes);
|
var parentWrapper = document.getElementsByClassName(classes);
|
||||||
if (parentWrapper.length > 0) {
|
if (parentWrapper.length > 0) {
|
||||||
var wrapper = parentWrapper[0].getElementsByClassName("container");
|
var wrapper = parentWrapper[0].getElementsByClassName("container");
|
||||||
|
@ -88,7 +89,7 @@ var MM = (function() {
|
||||||
* argument sender Module - The module that sent the notification.
|
* argument sender Module - The module that sent the notification.
|
||||||
* argument sendTo Module - The module to send the notification to. (optional)
|
* argument sendTo Module - The module to send the notification to. (optional)
|
||||||
*/
|
*/
|
||||||
var sendNotification = function(notification, payload, sender, sendTo) {
|
var sendNotification = function (notification, payload, sender, sendTo) {
|
||||||
for (var m in modules) {
|
for (var m in modules) {
|
||||||
var module = modules[m];
|
var module = modules[m];
|
||||||
if (module !== sender && (!sendTo || module === sendTo)) {
|
if (module !== sender && (!sendTo || module === sendTo)) {
|
||||||
|
@ -105,8 +106,8 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return Promise - Resolved when the dom is fully updated.
|
* return Promise - Resolved when the dom is fully updated.
|
||||||
*/
|
*/
|
||||||
var updateDom = function(module, speed) {
|
var updateDom = function (module, speed) {
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function (resolve) {
|
||||||
var newContentPromise = module.getDom();
|
var newContentPromise = module.getDom();
|
||||||
var newHeader = module.getHeader();
|
var newHeader = module.getHeader();
|
||||||
|
|
||||||
|
@ -115,11 +116,13 @@ var MM = (function() {
|
||||||
newContentPromise = Promise.resolve(newContentPromise);
|
newContentPromise = Promise.resolve(newContentPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
newContentPromise.then(function(newContent) {
|
newContentPromise
|
||||||
|
.then(function (newContent) {
|
||||||
var updatePromise = updateDomWithContent(module, speed, newHeader, newContent);
|
var updatePromise = updateDomWithContent(module, speed, newHeader, newContent);
|
||||||
|
|
||||||
updatePromise.then(resolve).catch(Log.error);
|
updatePromise.then(resolve).catch(Log.error);
|
||||||
}).catch(Log.error);
|
})
|
||||||
|
.catch(Log.error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,8 +136,8 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return Promise - Resolved when the module dom has been updated.
|
* return Promise - Resolved when the module dom has been updated.
|
||||||
*/
|
*/
|
||||||
var updateDomWithContent = function(module, speed, newHeader, newContent) {
|
var updateDomWithContent = function (module, speed, newHeader, newContent) {
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function (resolve) {
|
||||||
if (module.hidden || !speed) {
|
if (module.hidden || !speed) {
|
||||||
updateModuleContent(module, newHeader, newContent);
|
updateModuleContent(module, newHeader, newContent);
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -152,7 +155,7 @@ var MM = (function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hideModule(module, speed / 2, function() {
|
hideModule(module, speed / 2, function () {
|
||||||
updateModuleContent(module, newHeader, newContent);
|
updateModuleContent(module, newHeader, newContent);
|
||||||
if (!module.hidden) {
|
if (!module.hidden) {
|
||||||
showModule(module, speed / 2);
|
showModule(module, speed / 2);
|
||||||
|
@ -171,7 +174,7 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return bool - Does the module need an update?
|
* return bool - Does the module need an update?
|
||||||
*/
|
*/
|
||||||
var moduleNeedsUpdate = function(module, newHeader, newContent) {
|
var moduleNeedsUpdate = function (module, newHeader, newContent) {
|
||||||
var moduleWrapper = document.getElementById(module.identifier);
|
var moduleWrapper = document.getElementById(module.identifier);
|
||||||
if (moduleWrapper === null) {
|
if (moduleWrapper === null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -201,9 +204,11 @@ var MM = (function() {
|
||||||
* argument newHeader String - The new header that is generated.
|
* argument newHeader String - The new header that is generated.
|
||||||
* argument newContent Domobject - The new content that is generated.
|
* argument newContent Domobject - The new content that is generated.
|
||||||
*/
|
*/
|
||||||
var updateModuleContent = function(module, newHeader, newContent) {
|
var updateModuleContent = function (module, newHeader, newContent) {
|
||||||
var moduleWrapper = document.getElementById(module.identifier);
|
var moduleWrapper = document.getElementById(module.identifier);
|
||||||
if (moduleWrapper === null) {return;}
|
if (moduleWrapper === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var headerWrapper = moduleWrapper.getElementsByClassName("module-header");
|
var headerWrapper = moduleWrapper.getElementsByClassName("module-header");
|
||||||
var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
|
var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
|
||||||
|
|
||||||
|
@ -221,7 +226,7 @@ var MM = (function() {
|
||||||
* argument speed Number - The speed of the hide animation.
|
* argument speed Number - The speed of the hide animation.
|
||||||
* argument callback function - Called when the animation is done.
|
* argument callback function - Called when the animation is done.
|
||||||
*/
|
*/
|
||||||
var hideModule = function(module, speed, callback, options) {
|
var hideModule = function (module, speed, callback, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
// set lockString if set in options.
|
// set lockString if set in options.
|
||||||
|
@ -238,7 +243,7 @@ var MM = (function() {
|
||||||
moduleWrapper.style.opacity = 0;
|
moduleWrapper.style.opacity = 0;
|
||||||
|
|
||||||
clearTimeout(module.showHideTimer);
|
clearTimeout(module.showHideTimer);
|
||||||
module.showHideTimer = setTimeout(function() {
|
module.showHideTimer = setTimeout(function () {
|
||||||
// To not take up any space, we just make the position absolute.
|
// To not take up any space, we just make the position absolute.
|
||||||
// since it's fade out anyway, we can see it lay above or
|
// since it's fade out anyway, we can see it lay above or
|
||||||
// below other modules. This works way better than adjusting
|
// below other modules. This works way better than adjusting
|
||||||
|
@ -247,11 +252,15 @@ var MM = (function() {
|
||||||
|
|
||||||
updateWrapperStates();
|
updateWrapperStates();
|
||||||
|
|
||||||
if (typeof callback === "function") { callback(); }
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
}, speed);
|
}, speed);
|
||||||
} else {
|
} else {
|
||||||
// invoke callback even if no content, issue 1308
|
// invoke callback even if no content, issue 1308
|
||||||
if (typeof callback === "function") { callback(); }
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -262,13 +271,13 @@ var MM = (function() {
|
||||||
* argument speed Number - The speed of the show animation.
|
* argument speed Number - The speed of the show animation.
|
||||||
* argument callback function - Called when the animation is done.
|
* argument callback function - Called when the animation is done.
|
||||||
*/
|
*/
|
||||||
var showModule = function(module, speed, callback, options) {
|
var showModule = function (module, speed, callback, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
// remove lockString if set in options.
|
// remove lockString if set in options.
|
||||||
if (options.lockString) {
|
if (options.lockString) {
|
||||||
var index = module.lockStrings.indexOf(options.lockString);
|
var index = module.lockStrings.indexOf(options.lockString);
|
||||||
if ( index !== -1) {
|
if (index !== -1) {
|
||||||
module.lockStrings.splice(index, 1);
|
module.lockStrings.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,12 +310,16 @@ var MM = (function() {
|
||||||
moduleWrapper.style.opacity = 1;
|
moduleWrapper.style.opacity = 1;
|
||||||
|
|
||||||
clearTimeout(module.showHideTimer);
|
clearTimeout(module.showHideTimer);
|
||||||
module.showHideTimer = setTimeout(function() {
|
module.showHideTimer = setTimeout(function () {
|
||||||
if (typeof callback === "function") { callback(); }
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
}, speed);
|
}, speed);
|
||||||
} else {
|
} else {
|
||||||
// invoke callback
|
// invoke callback
|
||||||
if (typeof callback === "function") { callback(); }
|
if (typeof callback === "function") {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -321,15 +334,15 @@ var MM = (function() {
|
||||||
* an ugly top margin. By using this function, the top bar will be hidden if the
|
* an ugly top margin. By using this function, the top bar will be hidden if the
|
||||||
* update notification is not visible.
|
* update notification is not visible.
|
||||||
*/
|
*/
|
||||||
var updateWrapperStates = function() {
|
var updateWrapperStates = function () {
|
||||||
var positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];
|
var positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];
|
||||||
|
|
||||||
positions.forEach(function(position) {
|
positions.forEach(function (position) {
|
||||||
var wrapper = selectWrapper(position);
|
var wrapper = selectWrapper(position);
|
||||||
var moduleWrappers = wrapper.getElementsByClassName("module");
|
var moduleWrappers = wrapper.getElementsByClassName("module");
|
||||||
|
|
||||||
var showWrapper = false;
|
var showWrapper = false;
|
||||||
Array.prototype.forEach.call(moduleWrappers, function(moduleWrapper) {
|
Array.prototype.forEach.call(moduleWrappers, function (moduleWrapper) {
|
||||||
if (moduleWrapper.style.position === "" || moduleWrapper.style.position === "static") {
|
if (moduleWrapper.style.position === "" || moduleWrapper.style.position === "static") {
|
||||||
showWrapper = true;
|
showWrapper = true;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +355,7 @@ var MM = (function() {
|
||||||
/* loadConfig()
|
/* loadConfig()
|
||||||
* Loads the core config and combines it with de system defaults.
|
* Loads the core config and combines it with de system defaults.
|
||||||
*/
|
*/
|
||||||
var loadConfig = function() {
|
var loadConfig = function () {
|
||||||
// FIXME: Think about how to pass config around without breaking tests
|
// FIXME: Think about how to pass config around without breaking tests
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
if (typeof config === "undefined") {
|
if (typeof config === "undefined") {
|
||||||
|
@ -360,8 +373,7 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* argument modules array - Array of modules.
|
* argument modules array - Array of modules.
|
||||||
*/
|
*/
|
||||||
var setSelectionMethodsForModules = function(modules) {
|
var setSelectionMethodsForModules = function (modules) {
|
||||||
|
|
||||||
/* withClass(className)
|
/* withClass(className)
|
||||||
* calls modulesByClass to filter modules with the specified classes.
|
* calls modulesByClass to filter modules with the specified classes.
|
||||||
*
|
*
|
||||||
|
@ -369,7 +381,7 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return array - Filtered collection of modules.
|
* return array - Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var withClass = function(className) {
|
var withClass = function (className) {
|
||||||
return modulesByClass(className, true);
|
return modulesByClass(className, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -380,7 +392,7 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return array - Filtered collection of modules.
|
* return array - Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var exceptWithClass = function(className) {
|
var exceptWithClass = function (className) {
|
||||||
return modulesByClass(className, false);
|
return modulesByClass(className, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -392,13 +404,13 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return array - Filtered collection of modules.
|
* return array - Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var modulesByClass = function(className, include) {
|
var modulesByClass = function (className, include) {
|
||||||
var searchClasses = className;
|
var searchClasses = className;
|
||||||
if (typeof className === "string") {
|
if (typeof className === "string") {
|
||||||
searchClasses = className.split(" ");
|
searchClasses = className.split(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
var newModules = modules.filter(function(module) {
|
var newModules = modules.filter(function (module) {
|
||||||
var classes = module.data.classes.toLowerCase().split(" ");
|
var classes = module.data.classes.toLowerCase().split(" ");
|
||||||
|
|
||||||
for (var c in searchClasses) {
|
for (var c in searchClasses) {
|
||||||
|
@ -422,8 +434,8 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return array - Filtered collection of modules.
|
* return array - Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var exceptModule = function(module) {
|
var exceptModule = function (module) {
|
||||||
var newModules = modules.filter(function(mod) {
|
var newModules = modules.filter(function (mod) {
|
||||||
return mod.identifier !== module.identifier;
|
return mod.identifier !== module.identifier;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -436,16 +448,24 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* argument callback function - The function to execute with the module as an argument.
|
* argument callback function - The function to execute with the module as an argument.
|
||||||
*/
|
*/
|
||||||
var enumerate = function(callback) {
|
var enumerate = function (callback) {
|
||||||
modules.map(function(module) {
|
modules.map(function (module) {
|
||||||
callback(module);
|
callback(module);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof modules.withClass === "undefined") { Object.defineProperty(modules, "withClass", {value: withClass, enumerable: false}); }
|
if (typeof modules.withClass === "undefined") {
|
||||||
if (typeof modules.exceptWithClass === "undefined") { Object.defineProperty(modules, "exceptWithClass", {value: exceptWithClass, enumerable: false}); }
|
Object.defineProperty(modules, "withClass", { value: withClass, enumerable: false });
|
||||||
if (typeof modules.exceptModule === "undefined") { Object.defineProperty(modules, "exceptModule", {value: exceptModule, enumerable: false}); }
|
}
|
||||||
if (typeof modules.enumerate === "undefined") { Object.defineProperty(modules, "enumerate", {value: enumerate, enumerable: false}); }
|
if (typeof modules.exceptWithClass === "undefined") {
|
||||||
|
Object.defineProperty(modules, "exceptWithClass", { value: exceptWithClass, enumerable: false });
|
||||||
|
}
|
||||||
|
if (typeof modules.exceptModule === "undefined") {
|
||||||
|
Object.defineProperty(modules, "exceptModule", { value: exceptModule, enumerable: false });
|
||||||
|
}
|
||||||
|
if (typeof modules.enumerate === "undefined") {
|
||||||
|
Object.defineProperty(modules, "enumerate", { value: enumerate, enumerable: false });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -454,7 +474,7 @@ var MM = (function() {
|
||||||
/* init()
|
/* init()
|
||||||
* Main init method.
|
* Main init method.
|
||||||
*/
|
*/
|
||||||
init: function() {
|
init: function () {
|
||||||
Log.info("Initializing MagicMirror.");
|
Log.info("Initializing MagicMirror.");
|
||||||
loadConfig();
|
loadConfig();
|
||||||
Translator.loadCoreTranslations(config.language);
|
Translator.loadCoreTranslations(config.language);
|
||||||
|
@ -466,7 +486,7 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* argument moduleObjects array<Module> - All module instances.
|
* argument moduleObjects array<Module> - All module instances.
|
||||||
*/
|
*/
|
||||||
modulesStarted: function(moduleObjects) {
|
modulesStarted: function (moduleObjects) {
|
||||||
modules = [];
|
modules = [];
|
||||||
for (var m in moduleObjects) {
|
for (var m in moduleObjects) {
|
||||||
var module = moduleObjects[m];
|
var module = moduleObjects[m];
|
||||||
|
@ -486,7 +506,7 @@ var MM = (function() {
|
||||||
* argument payload mixed - The payload of the notification.
|
* argument payload mixed - The payload of the notification.
|
||||||
* argument sender Module - The module that sent the notification.
|
* argument sender Module - The module that sent the notification.
|
||||||
*/
|
*/
|
||||||
sendNotification: function(notification, payload, sender) {
|
sendNotification: function (notification, payload, sender) {
|
||||||
if (arguments.length < 3) {
|
if (arguments.length < 3) {
|
||||||
Log.error("sendNotification: Missing arguments.");
|
Log.error("sendNotification: Missing arguments.");
|
||||||
return;
|
return;
|
||||||
|
@ -512,7 +532,7 @@ var MM = (function() {
|
||||||
* argument module Module - The module that needs an update.
|
* argument module Module - The module that needs an update.
|
||||||
* argument speed Number - The number of microseconds for the animation. (optional)
|
* argument speed Number - The number of microseconds for the animation. (optional)
|
||||||
*/
|
*/
|
||||||
updateDom: function(module, speed) {
|
updateDom: function (module, speed) {
|
||||||
if (!(module instanceof Module)) {
|
if (!(module instanceof Module)) {
|
||||||
Log.error("updateDom: Sender should be a module.");
|
Log.error("updateDom: Sender should be a module.");
|
||||||
return;
|
return;
|
||||||
|
@ -527,7 +547,7 @@ var MM = (function() {
|
||||||
*
|
*
|
||||||
* return array - A collection of all modules currently active.
|
* return array - A collection of all modules currently active.
|
||||||
*/
|
*/
|
||||||
getModules: function() {
|
getModules: function () {
|
||||||
setSelectionMethodsForModules(modules);
|
setSelectionMethodsForModules(modules);
|
||||||
return modules;
|
return modules;
|
||||||
},
|
},
|
||||||
|
@ -540,7 +560,7 @@ var MM = (function() {
|
||||||
* argument callback function - Called when the animation is done.
|
* argument callback function - Called when the animation is done.
|
||||||
* argument options object - Optional settings for the hide method.
|
* argument options object - Optional settings for the hide method.
|
||||||
*/
|
*/
|
||||||
hideModule: function(module, speed, callback, options) {
|
hideModule: function (module, speed, callback, options) {
|
||||||
module.hidden = true;
|
module.hidden = true;
|
||||||
hideModule(module, speed, callback, options);
|
hideModule(module, speed, callback, options);
|
||||||
},
|
},
|
||||||
|
@ -553,18 +573,17 @@ var MM = (function() {
|
||||||
* argument callback function - Called when the animation is done.
|
* argument callback function - Called when the animation is done.
|
||||||
* argument options object - Optional settings for the hide method.
|
* argument options object - Optional settings for the hide method.
|
||||||
*/
|
*/
|
||||||
showModule: function(module, speed, callback, options) {
|
showModule: function (module, speed, callback, options) {
|
||||||
// do not change module.hidden yet, only if we really show it later
|
// do not change module.hidden yet, only if we really show it later
|
||||||
showModule(module, speed, callback, options);
|
showModule(module, speed, callback, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Add polyfill for Object.assign.
|
// Add polyfill for Object.assign.
|
||||||
if (typeof Object.assign !== "function") {
|
if (typeof Object.assign !== "function") {
|
||||||
(function() {
|
(function () {
|
||||||
Object.assign = function(target) {
|
Object.assign = function (target) {
|
||||||
"use strict";
|
"use strict";
|
||||||
if (target === undefined || target === null) {
|
if (target === undefined || target === null) {
|
||||||
throw new TypeError("Cannot convert undefined or null to object");
|
throw new TypeError("Cannot convert undefined or null to object");
|
||||||
|
|
55
js/module.js
55
js/module.js
|
@ -7,7 +7,6 @@
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var Module = Class.extend({
|
var Module = Class.extend({
|
||||||
|
|
||||||
/*********************************************************
|
/*********************************************************
|
||||||
* All methods (and properties) below can be subclassed. *
|
* All methods (and properties) below can be subclassed. *
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
|
@ -80,7 +79,7 @@ var Module = Class.extend({
|
||||||
*/
|
*/
|
||||||
getDom: function () {
|
getDom: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function (resolve) {
|
||||||
var div = document.createElement("div");
|
var div = document.createElement("div");
|
||||||
var template = self.getTemplate();
|
var template = self.getTemplate();
|
||||||
var templateData = self.getTemplateData();
|
var templateData = self.getTemplateData();
|
||||||
|
@ -126,7 +125,7 @@ var Module = Class.extend({
|
||||||
* return string - The template string of filename.
|
* return string - The template string of filename.
|
||||||
*/
|
*/
|
||||||
getTemplate: function () {
|
getTemplate: function () {
|
||||||
return "<div class=\"normal\">" + this.name + "</div><div class=\"small dimmed\">" + this.identifier + "</div>";
|
return '<div class="normal">' + this.name + '</div><div class="small dimmed">' + this.identifier + "</div>";
|
||||||
},
|
},
|
||||||
|
|
||||||
/* getTemplateData()
|
/* getTemplateData()
|
||||||
|
@ -161,18 +160,18 @@ var Module = Class.extend({
|
||||||
|
|
||||||
* @returns Nunjucks Environment
|
* @returns Nunjucks Environment
|
||||||
*/
|
*/
|
||||||
nunjucksEnvironment: function() {
|
nunjucksEnvironment: function () {
|
||||||
if (this._nunjucksEnvironment !== null) {
|
if (this._nunjucksEnvironment !== null) {
|
||||||
return this._nunjucksEnvironment;
|
return this._nunjucksEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this._nunjucksEnvironment = new nunjucks.Environment(new nunjucks.WebLoader(this.file(""), {async: true}), {
|
this._nunjucksEnvironment = new nunjucks.Environment(new nunjucks.WebLoader(this.file(""), { async: true }), {
|
||||||
trimBlocks: true,
|
trimBlocks: true,
|
||||||
lstripBlocks: true
|
lstripBlocks: true
|
||||||
});
|
});
|
||||||
this._nunjucksEnvironment.addFilter("translate", function(str) {
|
this._nunjucksEnvironment.addFilter("translate", function (str) {
|
||||||
return self.translate(str);
|
return self.translate(str);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -313,7 +312,9 @@ var Module = Class.extend({
|
||||||
|
|
||||||
// The variable `first` will contain the first
|
// The variable `first` will contain the first
|
||||||
// defined translation after the following line.
|
// defined translation after the following line.
|
||||||
for (var first in translations) { break; }
|
for (var first in translations) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (translations) {
|
if (translations) {
|
||||||
var translationFile = translations[lang] || undefined;
|
var translationFile = translations[lang] || undefined;
|
||||||
|
@ -341,7 +342,7 @@ var Module = Class.extend({
|
||||||
* argument defaultValue string - The default value with variables. (Optional)
|
* argument defaultValue string - The default value with variables. (Optional)
|
||||||
*/
|
*/
|
||||||
translate: function (key, defaultValueOrVariables, defaultValue) {
|
translate: function (key, defaultValueOrVariables, defaultValue) {
|
||||||
if(typeof defaultValueOrVariables === "object") {
|
if (typeof defaultValueOrVariables === "object") {
|
||||||
return Translator.translate(this, key, defaultValueOrVariables) || defaultValue || "";
|
return Translator.translate(this, key, defaultValueOrVariables) || defaultValue || "";
|
||||||
}
|
}
|
||||||
return Translator.translate(this, key) || defaultValueOrVariables || "";
|
return Translator.translate(this, key) || defaultValueOrVariables || "";
|
||||||
|
@ -386,17 +387,22 @@ var Module = Class.extend({
|
||||||
hide: function (speed, callback, options) {
|
hide: function (speed, callback, options) {
|
||||||
if (typeof callback === "object") {
|
if (typeof callback === "object") {
|
||||||
options = callback;
|
options = callback;
|
||||||
callback = function () { };
|
callback = function () {};
|
||||||
}
|
}
|
||||||
|
|
||||||
callback = callback || function () { };
|
callback = callback || function () {};
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
MM.hideModule(self, speed, function () {
|
MM.hideModule(
|
||||||
|
self,
|
||||||
|
speed,
|
||||||
|
function () {
|
||||||
self.suspend();
|
self.suspend();
|
||||||
callback();
|
callback();
|
||||||
}, options);
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* showModule(module, speed, callback)
|
/* showModule(module, speed, callback)
|
||||||
|
@ -409,24 +415,28 @@ var Module = Class.extend({
|
||||||
show: function (speed, callback, options) {
|
show: function (speed, callback, options) {
|
||||||
if (typeof callback === "object") {
|
if (typeof callback === "object") {
|
||||||
options = callback;
|
options = callback;
|
||||||
callback = function () { };
|
callback = function () {};
|
||||||
}
|
}
|
||||||
|
|
||||||
callback = callback || function () { };
|
callback = callback || function () {};
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
MM.showModule(this, speed, function () {
|
MM.showModule(
|
||||||
|
this,
|
||||||
|
speed,
|
||||||
|
function () {
|
||||||
self.resume();
|
self.resume();
|
||||||
callback;
|
callback;
|
||||||
}, options);
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.definitions = {};
|
Module.definitions = {};
|
||||||
|
|
||||||
Module.create = function (name) {
|
Module.create = function (name) {
|
||||||
|
|
||||||
// Make sure module definition is available.
|
// Make sure module definition is available.
|
||||||
if (!Module.definitions[name]) {
|
if (!Module.definitions[name]) {
|
||||||
return;
|
return;
|
||||||
|
@ -442,11 +452,11 @@ Module.create = function (name) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* cmpVersions(a,b)
|
/* cmpVersions(a,b)
|
||||||
* Compare two semantic version numbers and return the difference.
|
* Compare two semantic version numbers and return the difference.
|
||||||
*
|
*
|
||||||
* argument a string - Version number a.
|
* argument a string - Version number a.
|
||||||
* argument a string - Version number b.
|
* argument a string - Version number b.
|
||||||
*/
|
*/
|
||||||
function cmpVersions(a, b) {
|
function cmpVersions(a, b) {
|
||||||
var i, diff;
|
var i, diff;
|
||||||
var regExStrip0 = /(\.0+)+$/;
|
var regExStrip0 = /(\.0+)+$/;
|
||||||
|
@ -464,7 +474,6 @@ function cmpVersions(a, b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.register = function (name, moduleDefinition) {
|
Module.register = function (name, moduleDefinition) {
|
||||||
|
|
||||||
if (moduleDefinition.requiresVersion) {
|
if (moduleDefinition.requiresVersion) {
|
||||||
Log.log("Check MagicMirror version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + window.version);
|
Log.log("Check MagicMirror version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + window.version);
|
||||||
if (cmpVersions(window.version, moduleDefinition.requiresVersion) >= 0) {
|
if (cmpVersions(window.version, moduleDefinition.requiresVersion) >= 0) {
|
||||||
|
|
|
@ -8,16 +8,16 @@ const Class = require("./class.js");
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
|
|
||||||
var NodeHelper = Class.extend({
|
var NodeHelper = Class.extend({
|
||||||
init: function() {
|
init: function () {
|
||||||
console.log("Initializing new module helper ...");
|
console.log("Initializing new module helper ...");
|
||||||
},
|
},
|
||||||
|
|
||||||
loaded: function(callback) {
|
loaded: function (callback) {
|
||||||
console.log("Module helper loaded: " + this.name);
|
console.log("Module helper loaded: " + this.name);
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function () {
|
||||||
console.log("Starting module helper: " + this.name);
|
console.log("Starting module helper: " + this.name);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ var NodeHelper = Class.extend({
|
||||||
* gracefully exit the module.
|
* gracefully exit the module.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
stop: function() {
|
stop: function () {
|
||||||
console.log("Stopping module helper: " + this.name);
|
console.log("Stopping module helper: " + this.name);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ var NodeHelper = Class.extend({
|
||||||
* argument notification string - The identifier of the notification.
|
* argument notification string - The identifier of the notification.
|
||||||
* argument payload mixed - The payload of the notification.
|
* argument payload mixed - The payload of the notification.
|
||||||
*/
|
*/
|
||||||
socketNotificationReceived: function(notification, payload) {
|
socketNotificationReceived: function (notification, payload) {
|
||||||
console.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
|
console.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ var NodeHelper = Class.extend({
|
||||||
*
|
*
|
||||||
* argument name string - Module name.
|
* argument name string - Module name.
|
||||||
*/
|
*/
|
||||||
setName: function(name) {
|
setName: function (name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ var NodeHelper = Class.extend({
|
||||||
*
|
*
|
||||||
* argument path string - Module path.
|
* argument path string - Module path.
|
||||||
*/
|
*/
|
||||||
setPath: function(path) {
|
setPath: function (path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ var NodeHelper = Class.extend({
|
||||||
* argument notification string - The identifier of the notification.
|
* argument notification string - The identifier of the notification.
|
||||||
* argument payload mixed - The payload of the notification.
|
* argument payload mixed - The payload of the notification.
|
||||||
*/
|
*/
|
||||||
sendSocketNotification: function(notification, payload) {
|
sendSocketNotification: function (notification, payload) {
|
||||||
this.io.of(this.name).emit(notification, payload);
|
this.io.of(this.name).emit(notification, payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ var NodeHelper = Class.extend({
|
||||||
*
|
*
|
||||||
* argument app Express app - The Express app object.
|
* argument app Express app - The Express app object.
|
||||||
*/
|
*/
|
||||||
setExpressApp: function(app) {
|
setExpressApp: function (app) {
|
||||||
this.expressApp = app;
|
this.expressApp = app;
|
||||||
|
|
||||||
var publicPath = this.path + "/public";
|
var publicPath = this.path + "/public";
|
||||||
|
@ -88,16 +88,16 @@ var NodeHelper = Class.extend({
|
||||||
*
|
*
|
||||||
* argument io Socket.io - The Socket io object.
|
* argument io Socket.io - The Socket io object.
|
||||||
*/
|
*/
|
||||||
setSocketIO: function(io) {
|
setSocketIO: function (io) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.io = io;
|
self.io = io;
|
||||||
|
|
||||||
console.log("Connecting socket for: " + this.name);
|
console.log("Connecting socket for: " + this.name);
|
||||||
var namespace = this.name;
|
var namespace = this.name;
|
||||||
io.of(namespace).on("connection", function(socket) {
|
io.of(namespace).on("connection", function (socket) {
|
||||||
// add a catch all event.
|
// add a catch all event.
|
||||||
var onevent = socket.onevent;
|
var onevent = socket.onevent;
|
||||||
socket.onevent = function(packet) {
|
socket.onevent = function (packet) {
|
||||||
var args = packet.data || [];
|
var args = packet.data || [];
|
||||||
onevent.call(this, packet); // original call
|
onevent.call(this, packet); // original call
|
||||||
packet.data = ["*"].concat(args);
|
packet.data = ["*"].concat(args);
|
||||||
|
@ -105,7 +105,7 @@ var NodeHelper = Class.extend({
|
||||||
};
|
};
|
||||||
|
|
||||||
// register catch all.
|
// register catch all.
|
||||||
socket.on("*", function(notification, payload) {
|
socket.on("*", function (notification, payload) {
|
||||||
if (notification !== "*") {
|
if (notification !== "*") {
|
||||||
//console.log('received message in namespace: ' + namespace);
|
//console.log('received message in namespace: ' + namespace);
|
||||||
self.socketNotificationReceived(notification, payload);
|
self.socketNotificationReceived(notification, payload);
|
||||||
|
@ -115,9 +115,11 @@ var NodeHelper = Class.extend({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
NodeHelper.create = function(moduleDefinition) {
|
NodeHelper.create = function (moduleDefinition) {
|
||||||
return NodeHelper.extend(moduleDefinition);
|
return NodeHelper.extend(moduleDefinition);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = NodeHelper;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = NodeHelper;
|
||||||
|
}
|
||||||
|
|
21
js/server.js
21
js/server.js
|
@ -13,21 +13,20 @@ var fs = require("fs");
|
||||||
var helmet = require("helmet");
|
var helmet = require("helmet");
|
||||||
var Utils = require(__dirname + "/utils.js");
|
var Utils = require(__dirname + "/utils.js");
|
||||||
|
|
||||||
var Server = function(config, callback) {
|
var Server = function (config, callback) {
|
||||||
|
|
||||||
var port = config.port;
|
var port = config.port;
|
||||||
if (process.env.MM_PORT) {
|
if (process.env.MM_PORT) {
|
||||||
port = process.env.MM_PORT;
|
port = process.env.MM_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
var server = null;
|
var server = null;
|
||||||
if(config.useHttps){
|
if (config.useHttps) {
|
||||||
var options = {
|
var options = {
|
||||||
key: fs.readFileSync(config.httpsPrivateKey),
|
key: fs.readFileSync(config.httpsPrivateKey),
|
||||||
cert: fs.readFileSync(config.httpsCertificate)
|
cert: fs.readFileSync(config.httpsCertificate)
|
||||||
};
|
};
|
||||||
server = require("https").Server(options, app);
|
server = require("https").Server(options, app);
|
||||||
}else{
|
} else {
|
||||||
server = require("http").Server(app);
|
server = require("http").Server(app);
|
||||||
}
|
}
|
||||||
var io = require("socket.io")(server);
|
var io = require("socket.io")(server);
|
||||||
|
@ -40,8 +39,8 @@ var Server = function(config, callback) {
|
||||||
console.info(Utils.colors.warn("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) {
|
app.use(function (req, res, next) {
|
||||||
var result = ipfilter(config.ipWhitelist, {mode: config.ipWhitelist.length === 0 ? "deny" : "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) {
|
if (err === undefined) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
@ -59,20 +58,20 @@ var Server = function(config, callback) {
|
||||||
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get("/version", function(req,res) {
|
app.get("/version", function (req, res) {
|
||||||
res.send(global.version);
|
res.send(global.version);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/config", function(req,res) {
|
app.get("/config", function (req, res) {
|
||||||
res.send(config);
|
res.send(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/", function(req, res) {
|
app.get("/", function (req, res) {
|
||||||
var html = fs.readFileSync(path.resolve(global.root_path + "/index.html"), {encoding: "utf8"});
|
var html = fs.readFileSync(path.resolve(global.root_path + "/index.html"), { encoding: "utf8" });
|
||||||
html = html.replace("#VERSION#", global.version);
|
html = html.replace("#VERSION#", global.version);
|
||||||
|
|
||||||
var configFile = "config/config.js";
|
var configFile = "config/config.js";
|
||||||
if (typeof(global.configuration_file) !== "undefined") {
|
if (typeof global.configuration_file !== "undefined") {
|
||||||
configFile = global.configuration_file;
|
configFile = global.configuration_file;
|
||||||
}
|
}
|
||||||
html = html.replace("#CONFIG_FILE#", configFile);
|
html = html.replace("#CONFIG_FILE#", configFile);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var MMSocket = function(moduleName) {
|
var MMSocket = function (moduleName) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (typeof moduleName !== "string") {
|
if (typeof moduleName !== "string") {
|
||||||
|
@ -17,16 +17,16 @@ var MMSocket = function(moduleName) {
|
||||||
|
|
||||||
// Private Methods
|
// Private Methods
|
||||||
var base = "/";
|
var base = "/";
|
||||||
if ((typeof config !== "undefined") && (typeof config.basePath !== "undefined")) {
|
if (typeof config !== "undefined" && typeof config.basePath !== "undefined") {
|
||||||
base = config.basePath;
|
base = config.basePath;
|
||||||
}
|
}
|
||||||
self.socket = io("/" + self.moduleName, {
|
self.socket = io("/" + self.moduleName, {
|
||||||
path: base + "socket.io"
|
path: base + "socket.io"
|
||||||
});
|
});
|
||||||
var notificationCallback = function() {};
|
var notificationCallback = function () {};
|
||||||
|
|
||||||
var onevent = self.socket.onevent;
|
var onevent = self.socket.onevent;
|
||||||
self.socket.onevent = function(packet) {
|
self.socket.onevent = function (packet) {
|
||||||
var args = packet.data || [];
|
var args = packet.data || [];
|
||||||
onevent.call(this, packet); // original call
|
onevent.call(this, packet); // original call
|
||||||
packet.data = ["*"].concat(args);
|
packet.data = ["*"].concat(args);
|
||||||
|
@ -34,18 +34,18 @@ var MMSocket = function(moduleName) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// register catch all.
|
// register catch all.
|
||||||
self.socket.on("*", function(notification, payload) {
|
self.socket.on("*", function (notification, payload) {
|
||||||
if (notification !== "*") {
|
if (notification !== "*") {
|
||||||
notificationCallback(notification, payload);
|
notificationCallback(notification, payload);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Public Methods
|
// Public Methods
|
||||||
this.setNotificationCallback = function(callback) {
|
this.setNotificationCallback = function (callback) {
|
||||||
notificationCallback = callback;
|
notificationCallback = callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.sendNotification = function(notification, payload) {
|
this.sendNotification = function (notification, payload) {
|
||||||
if (typeof payload === "undefined") {
|
if (typeof payload === "undefined") {
|
||||||
payload = {};
|
payload = {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
* By Christopher Fenner https://github.com/CFenner
|
* By Christopher Fenner https://github.com/CFenner
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var Translator = (function() {
|
var Translator = (function () {
|
||||||
|
|
||||||
/* loadJSON(file, callback)
|
/* loadJSON(file, callback)
|
||||||
* Load a JSON file via XHR.
|
* Load a JSON file via XHR.
|
||||||
*
|
*
|
||||||
|
@ -62,7 +61,7 @@ var Translator = (function() {
|
||||||
currentChar = str[i];
|
currentChar = str[i];
|
||||||
nextChar = str[i + 1];
|
nextChar = str[i + 1];
|
||||||
|
|
||||||
if (!insideComment && currentChar === "\"") {
|
if (!insideComment && currentChar === '"') {
|
||||||
var escaped = str[i - 1] === "\\" && str[i - 2] !== "\\";
|
var escaped = str[i - 1] === "\\" && str[i - 2] !== "\\";
|
||||||
if (!escaped) {
|
if (!escaped) {
|
||||||
insideString = !insideString;
|
insideString = !insideString;
|
||||||
|
@ -119,7 +118,7 @@ var Translator = (function() {
|
||||||
* argument key string - The key of the text to translate.
|
* argument key string - The key of the text to translate.
|
||||||
* argument variables - The variables to use within the translation template (optional)
|
* argument variables - The variables to use within the translation template (optional)
|
||||||
*/
|
*/
|
||||||
translate: function(module, key, variables) {
|
translate: function (module, key, variables) {
|
||||||
variables = variables || {}; //Empty object by default
|
variables = variables || {}; //Empty object by default
|
||||||
|
|
||||||
// Combines template and variables like:
|
// Combines template and variables like:
|
||||||
|
@ -127,18 +126,18 @@ var Translator = (function() {
|
||||||
// variables: {timeToWait: "2 hours", work: "painting"}
|
// variables: {timeToWait: "2 hours", work: "painting"}
|
||||||
// to: "Please wait for 2 hours before continuing with painting."
|
// to: "Please wait for 2 hours before continuing with painting."
|
||||||
function createStringFromTemplate(template, variables) {
|
function createStringFromTemplate(template, variables) {
|
||||||
if(Object.prototype.toString.call(template) !== "[object String]") {
|
if (Object.prototype.toString.call(template) !== "[object String]") {
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
if(variables.fallback && !template.match(new RegExp("{.+}"))) {
|
if (variables.fallback && !template.match(new RegExp("{.+}"))) {
|
||||||
template = variables.fallback;
|
template = variables.fallback;
|
||||||
}
|
}
|
||||||
return template.replace(new RegExp("{([^}]+)}", "g"), function(_unused, varName){
|
return template.replace(new RegExp("{([^}]+)}", "g"), function (_unused, varName) {
|
||||||
return variables[varName] || "{"+varName+"}";
|
return variables[varName] || "{" + varName + "}";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.translations[module.name] && key in this.translations[module.name]) {
|
if (this.translations[module.name] && key in this.translations[module.name]) {
|
||||||
// Log.log("Got translation for " + key + " from module translation: ");
|
// Log.log("Got translation for " + key + " from module translation: ");
|
||||||
return createStringFromTemplate(this.translations[module.name][key], variables);
|
return createStringFromTemplate(this.translations[module.name][key], variables);
|
||||||
}
|
}
|
||||||
|
@ -169,7 +168,7 @@ var Translator = (function() {
|
||||||
* argument isFallback boolean - Flag to indicate fallback translations.
|
* argument isFallback boolean - Flag to indicate fallback translations.
|
||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
*/
|
*/
|
||||||
load: function(module, file, isFallback, callback) {
|
load: function (module, file, isFallback, callback) {
|
||||||
if (!isFallback) {
|
if (!isFallback) {
|
||||||
Log.log(module.name + " - Load translation: " + file);
|
Log.log(module.name + " - Load translation: " + file);
|
||||||
} else {
|
} else {
|
||||||
|
@ -177,8 +176,8 @@ var Translator = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
if(!this.translationsFallback[module.name]) {
|
if (!this.translationsFallback[module.name]) {
|
||||||
loadJSON(module.file(file), function(json) {
|
loadJSON(module.file(file), function (json) {
|
||||||
if (!isFallback) {
|
if (!isFallback) {
|
||||||
self.translations[module.name] = json;
|
self.translations[module.name] = json;
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,12 +195,12 @@ var Translator = (function() {
|
||||||
*
|
*
|
||||||
* argument lang String - The language identifier of the core language.
|
* argument lang String - The language identifier of the core language.
|
||||||
*/
|
*/
|
||||||
loadCoreTranslations: function(lang) {
|
loadCoreTranslations: function (lang) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (lang in translations) {
|
if (lang in translations) {
|
||||||
Log.log("Loading core translation file: " + translations[lang]);
|
Log.log("Loading core translation file: " + translations[lang]);
|
||||||
loadJSON(translations[lang], function(translations) {
|
loadJSON(translations[lang], function (translations) {
|
||||||
self.coreTranslations = translations;
|
self.coreTranslations = translations;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -215,19 +214,21 @@ var Translator = (function() {
|
||||||
* Load the core translations fallback.
|
* Load the core translations fallback.
|
||||||
* The first language defined in translations.js will be used.
|
* The first language defined in translations.js will be used.
|
||||||
*/
|
*/
|
||||||
loadCoreTranslationsFallback: function() {
|
loadCoreTranslationsFallback: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// The variable `first` will contain the first
|
// The variable `first` will contain the first
|
||||||
// defined translation after the following line.
|
// defined translation after the following line.
|
||||||
for (var first in translations) {break;}
|
for (var first in translations) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
Log.log("Loading core translation fallback file: " + translations[first]);
|
Log.log("Loading core translation fallback file: " + translations[first]);
|
||||||
loadJSON(translations[first], function(translations) {
|
loadJSON(translations[first], function (translations) {
|
||||||
self.coreTranslationsFallback = translations;
|
self.coreTranslationsFallback = translations;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -14,4 +14,6 @@ var Utils = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof module !== "undefined") {module.exports = Utils;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = Utils;
|
||||||
|
}
|
||||||
|
|
|
@ -6,8 +6,5 @@
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": ["modules", "node_modules"]
|
||||||
"modules",
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Alert
|
# Module: Alert
|
||||||
|
|
||||||
The alert module is one of the default modules of the MagicMirror. This module displays notifications from other modules.
|
The alert module is one of the default modules of the MagicMirror. This module displays notifications from other modules.
|
||||||
|
|
||||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/alert.html).
|
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/alert.html).
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* By Paul-Vincent Roll https://paulvincentroll.com/
|
* By Paul-Vincent Roll https://paulvincentroll.com/
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("alert",{
|
Module.register("alert", {
|
||||||
defaults: {
|
defaults: {
|
||||||
// scale|slide|genie|jelly|flip|bouncyflip|exploader
|
// scale|slide|genie|jelly|flip|bouncyflip|exploader
|
||||||
effect: "slide",
|
effect: "slide",
|
||||||
|
@ -17,31 +17,33 @@ Module.register("alert",{
|
||||||
//Position
|
//Position
|
||||||
position: "center",
|
position: "center",
|
||||||
//shown at startup
|
//shown at startup
|
||||||
welcome_message: false,
|
welcome_message: false
|
||||||
},
|
},
|
||||||
getScripts: function() {
|
getScripts: function () {
|
||||||
return ["notificationFx.js"];
|
return ["notificationFx.js"];
|
||||||
},
|
},
|
||||||
getStyles: function() {
|
getStyles: function () {
|
||||||
return ["notificationFx.css", "font-awesome.css"];
|
return ["notificationFx.css", "font-awesome.css"];
|
||||||
},
|
},
|
||||||
// Define required translations.
|
// Define required translations.
|
||||||
getTranslations: function() {
|
getTranslations: function () {
|
||||||
return {
|
return {
|
||||||
en: "translations/en.json",
|
en: "translations/en.json",
|
||||||
de: "translations/de.json",
|
de: "translations/de.json",
|
||||||
nl: "translations/nl.json",
|
nl: "translations/nl.json"
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
show_notification: function(message) {
|
show_notification: function (message) {
|
||||||
if (this.config.effect === "slide") {this.config.effect = this.config.effect + "-" + this.config.position;}
|
if (this.config.effect === "slide") {
|
||||||
|
this.config.effect = this.config.effect + "-" + this.config.position;
|
||||||
|
}
|
||||||
let msg = "";
|
let msg = "";
|
||||||
if (message.title) {
|
if (message.title) {
|
||||||
msg += "<span class='thin dimmed medium'>" + message.title + "</span>";
|
msg += "<span class='thin dimmed medium'>" + message.title + "</span>";
|
||||||
}
|
}
|
||||||
if (message.message){
|
if (message.message) {
|
||||||
if (msg !== ""){
|
if (msg !== "") {
|
||||||
msg+= "<br />";
|
msg += "<br />";
|
||||||
}
|
}
|
||||||
msg += "<span class='light bright small'>" + message.message + "</span>";
|
msg += "<span class='light bright small'>" + message.message + "</span>";
|
||||||
}
|
}
|
||||||
|
@ -53,22 +55,26 @@ Module.register("alert",{
|
||||||
ttl: message.timer !== undefined ? message.timer : this.config.display_time
|
ttl: message.timer !== undefined ? message.timer : this.config.display_time
|
||||||
}).show();
|
}).show();
|
||||||
},
|
},
|
||||||
show_alert: function(params, sender) {
|
show_alert: function (params, sender) {
|
||||||
let image = "";
|
let image = "";
|
||||||
//Set standard params if not provided by module
|
//Set standard params if not provided by module
|
||||||
if (typeof params.timer === "undefined") { params.timer = null; }
|
if (typeof params.timer === "undefined") {
|
||||||
if (typeof params.imageHeight === "undefined") { params.imageHeight = "80px"; }
|
params.timer = null;
|
||||||
|
}
|
||||||
|
if (typeof params.imageHeight === "undefined") {
|
||||||
|
params.imageHeight = "80px";
|
||||||
|
}
|
||||||
if (typeof params.imageUrl === "undefined" && typeof params.imageFA === "undefined") {
|
if (typeof params.imageUrl === "undefined" && typeof params.imageFA === "undefined") {
|
||||||
params.imageUrl = null;
|
params.imageUrl = null;
|
||||||
} else if (typeof params.imageFA === "undefined"){
|
} else if (typeof params.imageFA === "undefined") {
|
||||||
image = "<img src='" + (params.imageUrl).toString() + "' height='" + (params.imageHeight).toString() + "' style='margin-bottom: 10px;'/><br />";
|
image = "<img src='" + params.imageUrl.toString() + "' height='" + params.imageHeight.toString() + "' style='margin-bottom: 10px;'/><br />";
|
||||||
} else if (typeof params.imageUrl === "undefined"){
|
} else if (typeof params.imageUrl === "undefined") {
|
||||||
image = "<span class='bright " + "fa fa-" + params.imageFA + "' style='margin-bottom: 10px;font-size:" + (params.imageHeight).toString() + ";'/></span><br />";
|
image = "<span class='bright " + "fa fa-" + params.imageFA + "' style='margin-bottom: 10px;font-size:" + params.imageHeight.toString() + ";'/></span><br />";
|
||||||
}
|
}
|
||||||
//Create overlay
|
//Create overlay
|
||||||
const overlay = document.createElement("div");
|
const overlay = document.createElement("div");
|
||||||
overlay.id = "overlay";
|
overlay.id = "overlay";
|
||||||
overlay.innerHTML += "<div class=\"black_overlay\"></div>";
|
overlay.innerHTML += '<div class="black_overlay"></div>';
|
||||||
document.body.insertBefore(overlay, document.body.firstChild);
|
document.body.insertBefore(overlay, document.body.firstChild);
|
||||||
|
|
||||||
//If module already has an open alert close it
|
//If module already has an open alert close it
|
||||||
|
@ -82,7 +88,7 @@ Module.register("alert",{
|
||||||
message += "<span class='light dimmed medium'>" + params.title + "</span>";
|
message += "<span class='light dimmed medium'>" + params.title + "</span>";
|
||||||
}
|
}
|
||||||
if (params.message) {
|
if (params.message) {
|
||||||
if (message !== ""){
|
if (message !== "") {
|
||||||
message += "<br />";
|
message += "<br />";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +110,8 @@ Module.register("alert",{
|
||||||
this.hide_alert(sender);
|
this.hide_alert(sender);
|
||||||
}, params.timer);
|
}, params.timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
hide_alert: function(sender) {
|
hide_alert: function (sender) {
|
||||||
//Dismiss alert and remove from this.alerts
|
//Dismiss alert and remove from this.alerts
|
||||||
if (this.alerts[sender.name]) {
|
if (this.alerts[sender.name]) {
|
||||||
this.alerts[sender.name].dismiss();
|
this.alerts[sender.name].dismiss();
|
||||||
|
@ -116,18 +121,25 @@ Module.register("alert",{
|
||||||
overlay.parentNode.removeChild(overlay);
|
overlay.parentNode.removeChild(overlay);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setPosition: function(pos) {
|
setPosition: function (pos) {
|
||||||
//Add css to body depending on the set position for notifications
|
//Add css to body depending on the set position for notifications
|
||||||
const sheet = document.createElement("style");
|
const sheet = document.createElement("style");
|
||||||
if (pos === "center") {sheet.innerHTML = ".ns-box {margin-left: auto; margin-right: auto;text-align: center;}";}
|
if (pos === "center") {
|
||||||
if (pos === "right") {sheet.innerHTML = ".ns-box {margin-left: auto;text-align: right;}";}
|
sheet.innerHTML = ".ns-box {margin-left: auto; margin-right: auto;text-align: center;}";
|
||||||
if (pos === "left") {sheet.innerHTML = ".ns-box {margin-right: auto;text-align: left;}";}
|
}
|
||||||
|
if (pos === "right") {
|
||||||
|
sheet.innerHTML = ".ns-box {margin-left: auto;text-align: right;}";
|
||||||
|
}
|
||||||
|
if (pos === "left") {
|
||||||
|
sheet.innerHTML = ".ns-box {margin-right: auto;text-align: left;}";
|
||||||
|
}
|
||||||
document.body.appendChild(sheet);
|
document.body.appendChild(sheet);
|
||||||
|
|
||||||
},
|
},
|
||||||
notificationReceived: function(notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
if (notification === "SHOW_ALERT") {
|
if (notification === "SHOW_ALERT") {
|
||||||
if (typeof payload.type === "undefined") { payload.type = "alert"; }
|
if (typeof payload.type === "undefined") {
|
||||||
|
payload.type = "alert";
|
||||||
|
}
|
||||||
if (payload.type === "alert") {
|
if (payload.type === "alert") {
|
||||||
this.show_alert(payload, sender);
|
this.show_alert(payload, sender);
|
||||||
} else if (payload.type === "notification") {
|
} else if (payload.type === "notification") {
|
||||||
|
@ -137,15 +149,14 @@ Module.register("alert",{
|
||||||
this.hide_alert(sender);
|
this.hide_alert(sender);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
start: function() {
|
start: function () {
|
||||||
this.alerts = {};
|
this.alerts = {};
|
||||||
this.setPosition(this.config.position);
|
this.setPosition(this.config.position);
|
||||||
if (this.config.welcome_message) {
|
if (this.config.welcome_message) {
|
||||||
if (this.config.welcome_message === true){
|
if (this.config.welcome_message === true) {
|
||||||
this.show_notification({title: this.translate("sysTitle"), message: this.translate("welcome")});
|
this.show_notification({ title: this.translate("sysTitle"), message: this.translate("welcome") });
|
||||||
}
|
} else {
|
||||||
else{
|
this.show_notification({ title: this.translate("sysTitle"), message: this.config.welcome_message });
|
||||||
this.show_notification({title: this.translate("sysTitle"), message: this.config.welcome_message});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.info("Starting module: " + this.name);
|
Log.info("Starting module: " + this.name);
|
||||||
|
|
|
@ -235,8 +235,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes animFade {
|
@keyframes animFade {
|
||||||
0% { opacity: 0; }
|
0% {
|
||||||
100% { opacity: 1; }
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes animJelly {
|
@keyframes animJelly {
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
* Copyright 2014, Codrops
|
* Copyright 2014, Codrops
|
||||||
* https://tympanus.net/codrops/
|
* https://tympanus.net/codrops/
|
||||||
*/
|
*/
|
||||||
(function(window) {
|
(function (window) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* extend obj function
|
* extend obj function
|
||||||
*/
|
*/
|
||||||
|
@ -58,19 +57,23 @@
|
||||||
ttl: 6000,
|
ttl: 6000,
|
||||||
al_no: "ns-box",
|
al_no: "ns-box",
|
||||||
// callbacks
|
// callbacks
|
||||||
onClose: function() { return false; },
|
onClose: function () {
|
||||||
onOpen: function() { return false; }
|
return false;
|
||||||
|
},
|
||||||
|
onOpen: function () {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init function
|
* init function
|
||||||
* initialize and cache some vars
|
* initialize and cache some vars
|
||||||
*/
|
*/
|
||||||
NotificationFx.prototype._init = function() {
|
NotificationFx.prototype._init = function () {
|
||||||
// create HTML structure
|
// create HTML structure
|
||||||
this.ntf = document.createElement("div");
|
this.ntf = document.createElement("div");
|
||||||
this.ntf.className = this.options.al_no + " ns-" + this.options.layout + " ns-effect-" + this.options.effect + " ns-type-" + this.options.type;
|
this.ntf.className = this.options.al_no + " ns-" + this.options.layout + " ns-effect-" + this.options.effect + " ns-type-" + this.options.type;
|
||||||
let strinner = "<div class=\"ns-box-inner\">";
|
let strinner = '<div class="ns-box-inner">';
|
||||||
strinner += this.options.message;
|
strinner += this.options.message;
|
||||||
strinner += "</div>";
|
strinner += "</div>";
|
||||||
this.ntf.innerHTML = strinner;
|
this.ntf.innerHTML = strinner;
|
||||||
|
@ -94,15 +97,17 @@
|
||||||
/**
|
/**
|
||||||
* init events
|
* init events
|
||||||
*/
|
*/
|
||||||
NotificationFx.prototype._initEvents = function() {
|
NotificationFx.prototype._initEvents = function () {
|
||||||
// dismiss notification by tapping on it if someone has a touchscreen
|
// dismiss notification by tapping on it if someone has a touchscreen
|
||||||
this.ntf.querySelector(".ns-box-inner").addEventListener("click", () => { this.dismiss(); });
|
this.ntf.querySelector(".ns-box-inner").addEventListener("click", () => {
|
||||||
|
this.dismiss();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* show the notification
|
* show the notification
|
||||||
*/
|
*/
|
||||||
NotificationFx.prototype.show = function() {
|
NotificationFx.prototype.show = function () {
|
||||||
this.active = true;
|
this.active = true;
|
||||||
this.ntf.classList.remove("ns-hide");
|
this.ntf.classList.remove("ns-hide");
|
||||||
this.ntf.classList.add("ns-show");
|
this.ntf.classList.add("ns-show");
|
||||||
|
@ -112,7 +117,7 @@
|
||||||
/**
|
/**
|
||||||
* dismiss the notification
|
* dismiss the notification
|
||||||
*/
|
*/
|
||||||
NotificationFx.prototype.dismiss = function() {
|
NotificationFx.prototype.dismiss = function () {
|
||||||
this.active = false;
|
this.active = false;
|
||||||
clearTimeout(this.dismissttl);
|
clearTimeout(this.dismissttl);
|
||||||
this.ntf.classList.remove("ns-show");
|
this.ntf.classList.remove("ns-show");
|
||||||
|
@ -125,7 +130,9 @@
|
||||||
|
|
||||||
// after animation ends remove ntf from the DOM
|
// after animation ends remove ntf from the DOM
|
||||||
const onEndAnimationFn = (ev) => {
|
const onEndAnimationFn = (ev) => {
|
||||||
if (ev.target !== this.ntf) {return false;}
|
if (ev.target !== this.ntf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
this.ntf.removeEventListener("animationend", onEndAnimationFn);
|
this.ntf.removeEventListener("animationend", onEndAnimationFn);
|
||||||
|
|
||||||
if (ev.target.parentNode === this.options.wrapper) {
|
if (ev.target.parentNode === this.options.wrapper) {
|
||||||
|
@ -140,5 +147,4 @@
|
||||||
* add to global namespace
|
* add to global namespace
|
||||||
*/
|
*/
|
||||||
window.NotificationFx = NotificationFx;
|
window.NotificationFx = NotificationFx;
|
||||||
|
|
||||||
})(window);
|
})(window);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Calendar
|
# Module: Calendar
|
||||||
|
|
||||||
The `calendar` module is one of the default modules of the MagicMirror.
|
The `calendar` module is one of the default modules of the MagicMirror.
|
||||||
This module displays events from a public .ical calendar. It can combine multiple calendars.
|
This module displays events from a public .ical calendar. It can combine multiple calendars.
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("calendar", {
|
Module.register("calendar", {
|
||||||
|
|
||||||
// Define module defaults
|
// Define module defaults
|
||||||
defaults: {
|
defaults: {
|
||||||
maximumEntries: 10, // Total Maximum Entries
|
maximumEntries: 10, // Total Maximum Entries
|
||||||
|
@ -39,8 +38,8 @@ Module.register("calendar", {
|
||||||
calendars: [
|
calendars: [
|
||||||
{
|
{
|
||||||
symbol: "calendar",
|
symbol: "calendar",
|
||||||
url: "https://www.calendarlabs.com/templates/ical/US-Holidays.ics",
|
url: "https://www.calendarlabs.com/templates/ical/US-Holidays.ics"
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
titleReplace: {
|
titleReplace: {
|
||||||
"De verjaardag van ": "",
|
"De verjaardag van ": "",
|
||||||
|
@ -85,7 +84,7 @@ Module.register("calendar", {
|
||||||
var calendarConfig = {
|
var calendarConfig = {
|
||||||
maximumEntries: calendar.maximumEntries,
|
maximumEntries: calendar.maximumEntries,
|
||||||
maximumNumberOfDays: calendar.maximumNumberOfDays,
|
maximumNumberOfDays: calendar.maximumNumberOfDays,
|
||||||
broadcastPastEvents: calendar.broadcastPastEvents,
|
broadcastPastEvents: calendar.broadcastPastEvents
|
||||||
};
|
};
|
||||||
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
|
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
|
||||||
calendarConfig.symbolClass = "";
|
calendarConfig.symbolClass = "";
|
||||||
|
@ -98,7 +97,7 @@ Module.register("calendar", {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we check user and password here for backwards compatibility with old configs
|
// 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("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");
|
Log.warn("https://github.com/MichMich/MagicMirror/tree/v2.1.2/modules/default/calendar#calendar-authentication-options");
|
||||||
calendar.auth = {
|
calendar.auth = {
|
||||||
|
@ -112,7 +111,7 @@ Module.register("calendar", {
|
||||||
// Trigger ADD_CALENDAR every fetchInterval to make sure there is always a calendar
|
// Trigger ADD_CALENDAR every fetchInterval to make sure there is always a calendar
|
||||||
// fetcher running on the server side.
|
// fetcher running on the server side.
|
||||||
var self = this;
|
var self = this;
|
||||||
setInterval(function() {
|
setInterval(function () {
|
||||||
self.addCalendar(calendar.url, calendar.auth, calendarConfig);
|
self.addCalendar(calendar.url, calendar.auth, calendarConfig);
|
||||||
}, self.config.fetchInterval);
|
}, self.config.fetchInterval);
|
||||||
}
|
}
|
||||||
|
@ -144,13 +143,12 @@ Module.register("calendar", {
|
||||||
|
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function () {
|
getDom: function () {
|
||||||
|
|
||||||
var events = this.createEventList();
|
var events = this.createEventList();
|
||||||
var wrapper = document.createElement("table");
|
var wrapper = document.createElement("table");
|
||||||
wrapper.className = this.config.tableClass;
|
wrapper.className = this.config.tableClass;
|
||||||
|
|
||||||
if (events.length === 0) {
|
if (events.length === 0) {
|
||||||
wrapper.innerHTML = (this.loaded) ? this.translate("EMPTY") : this.translate("LOADING");
|
wrapper.innerHTML = this.loaded ? this.translate("EMPTY") : this.translate("LOADING");
|
||||||
wrapper.className = this.config.tableClass + " dimmed";
|
wrapper.className = this.config.tableClass + " dimmed";
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
@ -169,8 +167,8 @@ Module.register("calendar", {
|
||||||
for (var e in events) {
|
for (var e in events) {
|
||||||
var event = events[e];
|
var event = events[e];
|
||||||
var dateAsString = moment(event.startDate, "x").format(this.config.dateFormat);
|
var dateAsString = moment(event.startDate, "x").format(this.config.dateFormat);
|
||||||
if(this.config.timeFormat === "dateheaders"){
|
if (this.config.timeFormat === "dateheaders") {
|
||||||
if(lastSeenDate !== dateAsString){
|
if (lastSeenDate !== dateAsString) {
|
||||||
var dateRow = document.createElement("tr");
|
var dateRow = document.createElement("tr");
|
||||||
dateRow.className = "normal";
|
dateRow.className = "normal";
|
||||||
var dateCell = document.createElement("td");
|
var dateCell = document.createElement("td");
|
||||||
|
@ -181,9 +179,10 @@ Module.register("calendar", {
|
||||||
dateRow.appendChild(dateCell);
|
dateRow.appendChild(dateCell);
|
||||||
wrapper.appendChild(dateRow);
|
wrapper.appendChild(dateRow);
|
||||||
|
|
||||||
if (e >= startFade) { //fading
|
if (e >= startFade) {
|
||||||
|
//fading
|
||||||
currentFadeStep = e - startFade;
|
currentFadeStep = e - startFade;
|
||||||
dateRow.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
|
dateRow.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastSeenDate = dateAsString;
|
lastSeenDate = dateAsString;
|
||||||
|
@ -209,20 +208,20 @@ Module.register("calendar", {
|
||||||
symbolWrapper.className = "symbol align-right " + symbolClass;
|
symbolWrapper.className = "symbol align-right " + symbolClass;
|
||||||
|
|
||||||
var symbols = this.symbolsForUrl(event.url);
|
var symbols = this.symbolsForUrl(event.url);
|
||||||
if(typeof symbols === "string") {
|
if (typeof symbols === "string") {
|
||||||
symbols = [symbols];
|
symbols = [symbols];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < symbols.length; i++) {
|
for (var i = 0; i < symbols.length; i++) {
|
||||||
var symbol = document.createElement("span");
|
var symbol = document.createElement("span");
|
||||||
symbol.className = "fa fa-fw fa-" + symbols[i];
|
symbol.className = "fa fa-fw fa-" + symbols[i];
|
||||||
if(i > 0){
|
if (i > 0) {
|
||||||
symbol.style.paddingLeft = "5px";
|
symbol.style.paddingLeft = "5px";
|
||||||
}
|
}
|
||||||
symbolWrapper.appendChild(symbol);
|
symbolWrapper.appendChild(symbol);
|
||||||
}
|
}
|
||||||
eventWrapper.appendChild(symbolWrapper);
|
eventWrapper.appendChild(symbolWrapper);
|
||||||
} else if(this.config.timeFormat === "dateheaders"){
|
} else if (this.config.timeFormat === "dateheaders") {
|
||||||
var blankCell = document.createElement("td");
|
var blankCell = document.createElement("td");
|
||||||
blankCell.innerHTML = " ";
|
blankCell.innerHTML = " ";
|
||||||
eventWrapper.appendChild(blankCell);
|
eventWrapper.appendChild(blankCell);
|
||||||
|
@ -232,7 +231,6 @@ Module.register("calendar", {
|
||||||
repeatingCountTitle = "";
|
repeatingCountTitle = "";
|
||||||
|
|
||||||
if (this.config.displayRepeatingCountTitle && event.firstYear !== undefined) {
|
if (this.config.displayRepeatingCountTitle && event.firstYear !== undefined) {
|
||||||
|
|
||||||
repeatingCountTitle = this.countTitleForUrl(event.url);
|
repeatingCountTitle = this.countTitleForUrl(event.url);
|
||||||
|
|
||||||
if (repeatingCountTitle !== "") {
|
if (repeatingCountTitle !== "") {
|
||||||
|
@ -255,12 +253,10 @@ Module.register("calendar", {
|
||||||
|
|
||||||
var timeWrapper;
|
var timeWrapper;
|
||||||
|
|
||||||
if(this.config.timeFormat === "dateheaders"){
|
if (this.config.timeFormat === "dateheaders") {
|
||||||
|
|
||||||
if (event.fullDayEvent) {
|
if (event.fullDayEvent) {
|
||||||
titleWrapper.colSpan = "2";
|
titleWrapper.colSpan = "2";
|
||||||
titleWrapper.align = "left";
|
titleWrapper.align = "left";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
timeWrapper = document.createElement("td");
|
timeWrapper = document.createElement("td");
|
||||||
timeWrapper.className = "time light " + this.timeClassForUrl(event.url);
|
timeWrapper.className = "time light " + this.timeClassForUrl(event.url);
|
||||||
|
@ -305,7 +301,7 @@ Module.register("calendar", {
|
||||||
* Note: this needs to be put in its own function, as the whole thing repeats again verbatim
|
* Note: this needs to be put in its own function, as the whole thing repeats again verbatim
|
||||||
*/
|
*/
|
||||||
if (this.config.timeFormat === "absolute") {
|
if (this.config.timeFormat === "absolute") {
|
||||||
if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) {
|
if (this.config.urgency > 1 && event.startDate - now < this.config.urgency * oneDay) {
|
||||||
// This event falls within the config.urgency period that the user has set
|
// This event falls within the config.urgency period that the user has set
|
||||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD")));
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD")));
|
||||||
} else {
|
} else {
|
||||||
|
@ -315,9 +311,9 @@ Module.register("calendar", {
|
||||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD")));
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").from(moment().format("YYYYMMDD")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.config.showEnd){
|
if (this.config.showEnd) {
|
||||||
timeWrapper.innerHTML += "-" ;
|
timeWrapper.innerHTML += "-";
|
||||||
timeWrapper.innerHTML += this.capFirst(moment(event.endDate , "x").format(this.config.fullDayEventDateFormat));
|
timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.fullDayEventDateFormat));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (event.startDate >= new Date()) {
|
if (event.startDate >= new Date()) {
|
||||||
|
@ -327,7 +323,7 @@ Module.register("calendar", {
|
||||||
// If event is within 6 hour, display 'in xxx' time format or moment.fromNow()
|
// If event is within 6 hour, display 'in xxx' time format or moment.fromNow()
|
||||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
||||||
} else {
|
} else {
|
||||||
if(this.config.timeFormat === "absolute" && !this.config.nextDaysRelative) {
|
if (this.config.timeFormat === "absolute" && !this.config.nextDaysRelative) {
|
||||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat));
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat));
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just say 'Today/Tomorrow at such-n-such time'
|
// Otherwise just say 'Today/Tomorrow at such-n-such time'
|
||||||
|
@ -343,7 +339,7 @@ Module.register("calendar", {
|
||||||
* Note: this needs to be put in its own function, as the whole thing repeats again verbatim
|
* Note: this needs to be put in its own function, as the whole thing repeats again verbatim
|
||||||
*/
|
*/
|
||||||
if (this.config.timeFormat === "absolute") {
|
if (this.config.timeFormat === "absolute") {
|
||||||
if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) {
|
if (this.config.urgency > 1 && event.startDate - now < this.config.urgency * oneDay) {
|
||||||
// This event falls within the config.urgency period that the user has set
|
// This event falls within the config.urgency period that the user has set
|
||||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
||||||
} else {
|
} else {
|
||||||
|
@ -364,7 +360,6 @@ Module.register("calendar", {
|
||||||
if (this.config.showEnd) {
|
if (this.config.showEnd) {
|
||||||
timeWrapper.innerHTML += "-";
|
timeWrapper.innerHTML += "-";
|
||||||
timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat));
|
timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll');
|
//timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll');
|
||||||
|
@ -378,7 +373,7 @@ Module.register("calendar", {
|
||||||
// Create fade effect.
|
// Create fade effect.
|
||||||
if (e >= startFade) {
|
if (e >= startFade) {
|
||||||
currentFadeStep = e - startFade;
|
currentFadeStep = e - startFade;
|
||||||
eventWrapper.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
|
eventWrapper.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.showLocation) {
|
if (this.config.showLocation) {
|
||||||
|
@ -401,7 +396,7 @@ Module.register("calendar", {
|
||||||
|
|
||||||
if (e >= startFade) {
|
if (e >= startFade) {
|
||||||
currentFadeStep = e - startFade;
|
currentFadeStep = e - startFade;
|
||||||
locationRow.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
|
locationRow.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,16 +413,16 @@ Module.register("calendar", {
|
||||||
* @param {number} timeFormat Specifies either 12 or 24 hour time format
|
* @param {number} timeFormat Specifies either 12 or 24 hour time format
|
||||||
* @returns {moment.LocaleSpecification}
|
* @returns {moment.LocaleSpecification}
|
||||||
*/
|
*/
|
||||||
getLocaleSpecification: function(timeFormat) {
|
getLocaleSpecification: function (timeFormat) {
|
||||||
switch (timeFormat) {
|
switch (timeFormat) {
|
||||||
case 12: {
|
case 12: {
|
||||||
return { longDateFormat: {LT: "h:mm A"} };
|
return { longDateFormat: { LT: "h:mm A" } };
|
||||||
}
|
}
|
||||||
case 24: {
|
case 24: {
|
||||||
return { longDateFormat: {LT: "HH:mm"} };
|
return { longDateFormat: { LT: "HH:mm" } };
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return { longDateFormat: {LT: moment.localeData().longDateFormat("LT")} };
|
return { longDateFormat: { LT: moment.localeData().longDateFormat("LT") } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -464,37 +459,37 @@ Module.register("calendar", {
|
||||||
var calendar = this.calendarData[c];
|
var calendar = this.calendarData[c];
|
||||||
for (var e in calendar) {
|
for (var e in calendar) {
|
||||||
var event = JSON.parse(JSON.stringify(calendar[e])); // clone object
|
var event = JSON.parse(JSON.stringify(calendar[e])); // clone object
|
||||||
if(event.endDate < now) {
|
if (event.endDate < now) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(this.config.hidePrivate) {
|
if (this.config.hidePrivate) {
|
||||||
if(event.class === "PRIVATE") {
|
if (event.class === "PRIVATE") {
|
||||||
// do not add the current event, skip it
|
// do not add the current event, skip it
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.config.hideOngoing) {
|
if (this.config.hideOngoing) {
|
||||||
if(event.startDate < now) {
|
if (event.startDate < now) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.listContainsEvent(events,event)){
|
if (this.listContainsEvent(events, event)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
event.url = c;
|
event.url = c;
|
||||||
event.today = event.startDate >= today && event.startDate < (today + 24 * 60 * 60 * 1000);
|
event.today = event.startDate >= today && event.startDate < today + 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
/* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
|
/* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
|
||||||
* otherwise, esp. in dateheaders mode it is not clear how long these events are.
|
* otherwise, esp. in dateheaders mode it is not clear how long these events are.
|
||||||
*/
|
*/
|
||||||
var maxCount = Math.ceil(((event.endDate - 1) - moment(event.startDate, "x").endOf("day").format("x"))/(1000*60*60*24)) + 1;
|
var maxCount = Math.ceil((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / (1000 * 60 * 60 * 24)) + 1;
|
||||||
if (this.config.sliceMultiDayEvents && maxCount > 1) {
|
if (this.config.sliceMultiDayEvents && maxCount > 1) {
|
||||||
var splitEvents = [];
|
var splitEvents = [];
|
||||||
var midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x");
|
var midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x");
|
||||||
var count = 1;
|
var count = 1;
|
||||||
while (event.endDate > midnight) {
|
while (event.endDate > midnight) {
|
||||||
var thisEvent = JSON.parse(JSON.stringify(event)); // clone object
|
var thisEvent = JSON.parse(JSON.stringify(event)); // clone object
|
||||||
thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < (today + 24 * 60 * 60 * 1000);
|
thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < today + 24 * 60 * 60 * 1000;
|
||||||
thisEvent.endDate = midnight;
|
thisEvent.endDate = midnight;
|
||||||
thisEvent.title += " (" + count + "/" + maxCount + ")";
|
thisEvent.title += " (" + count + "/" + maxCount + ")";
|
||||||
splitEvents.push(thisEvent);
|
splitEvents.push(thisEvent);
|
||||||
|
@ -504,11 +499,11 @@ Module.register("calendar", {
|
||||||
midnight = moment(midnight, "x").add(1, "day").format("x"); // next day
|
midnight = moment(midnight, "x").add(1, "day").format("x"); // next day
|
||||||
}
|
}
|
||||||
// Last day
|
// Last day
|
||||||
event.title += " ("+count+"/"+maxCount+")";
|
event.title += " (" + count + "/" + maxCount + ")";
|
||||||
splitEvents.push(event);
|
splitEvents.push(event);
|
||||||
|
|
||||||
for (event of splitEvents) {
|
for (event of splitEvents) {
|
||||||
if ((event.endDate > now) && (event.endDate <= future)) {
|
if (event.endDate > now && event.endDate <= future) {
|
||||||
events.push(event);
|
events.push(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,9 +519,9 @@ Module.register("calendar", {
|
||||||
return events.slice(0, this.config.maximumEntries);
|
return events.slice(0, this.config.maximumEntries);
|
||||||
},
|
},
|
||||||
|
|
||||||
listContainsEvent: function(eventList, event){
|
listContainsEvent: function (eventList, event) {
|
||||||
for(var evt of eventList){
|
for (var evt of eventList) {
|
||||||
if(evt.title === event.title && parseInt(evt.startDate) === parseInt(event.startDate)){
|
if (evt.title === event.title && parseInt(evt.startDate) === parseInt(event.startDate)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,7 +544,7 @@ Module.register("calendar", {
|
||||||
titleClass: calendarConfig.titleClass,
|
titleClass: calendarConfig.titleClass,
|
||||||
timeClass: calendarConfig.timeClass,
|
timeClass: calendarConfig.timeClass,
|
||||||
auth: auth,
|
auth: auth,
|
||||||
broadcastPastEvents: calendarConfig.broadcastPastEvents || this.config.broadcastPastEvents,
|
broadcastPastEvents: calendarConfig.broadcastPastEvents || this.config.broadcastPastEvents
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -676,8 +671,9 @@ Module.register("calendar", {
|
||||||
|
|
||||||
for (var i = 0; i < words.length; i++) {
|
for (var i = 0; i < words.length; i++) {
|
||||||
var word = words[i];
|
var word = words[i];
|
||||||
if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) { // max - 1 to account for a space
|
if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) {
|
||||||
currentLine += (word + " ");
|
// max - 1 to account for a space
|
||||||
|
currentLine += word + " ";
|
||||||
} else {
|
} else {
|
||||||
line++;
|
line++;
|
||||||
if (line > maxTitleLines - 1) {
|
if (line > maxTitleLines - 1) {
|
||||||
|
@ -688,9 +684,9 @@ Module.register("calendar", {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentLine.length > 0) {
|
if (currentLine.length > 0) {
|
||||||
temp += (currentLine + "<br>" + word + " ");
|
temp += currentLine + "<br>" + word + " ";
|
||||||
} else {
|
} else {
|
||||||
temp += (word + "<br>");
|
temp += word + "<br>";
|
||||||
}
|
}
|
||||||
currentLine = "";
|
currentLine = "";
|
||||||
}
|
}
|
||||||
|
@ -758,11 +754,10 @@ Module.register("calendar", {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eventList.sort(function(a,b) {
|
eventList.sort(function (a, b) {
|
||||||
return a.startDate - b.startDate;
|
return a.startDate - b.startDate;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sendNotification("CALENDAR_EVENTS", eventList);
|
this.sendNotification("CALENDAR_EVENTS", eventList);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,44 +8,42 @@
|
||||||
const ical = require("./vendor/ical.js");
|
const ical = require("./vendor/ical.js");
|
||||||
const moment = require("moment");
|
const moment = require("moment");
|
||||||
|
|
||||||
var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) {
|
var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var reloadTimer = null;
|
var reloadTimer = null;
|
||||||
var events = [];
|
var events = [];
|
||||||
|
|
||||||
var fetchFailedCallback = function() {};
|
var fetchFailedCallback = function () {};
|
||||||
var eventsReceivedCallback = function() {};
|
var eventsReceivedCallback = function () {};
|
||||||
|
|
||||||
/* fetchCalendar()
|
/* fetchCalendar()
|
||||||
* Initiates calendar fetch.
|
* Initiates calendar fetch.
|
||||||
*/
|
*/
|
||||||
var fetchCalendar = function() {
|
var fetchCalendar = function () {
|
||||||
|
|
||||||
clearTimeout(reloadTimer);
|
clearTimeout(reloadTimer);
|
||||||
reloadTimer = null;
|
reloadTimer = null;
|
||||||
|
|
||||||
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
||||||
var opts = {
|
var opts = {
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": "Mozilla/5.0 (Node.js "+ nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)"
|
"User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)"
|
||||||
},
|
},
|
||||||
gzip: true
|
gzip: true
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auth) {
|
if (auth) {
|
||||||
if(auth.method === "bearer"){
|
if (auth.method === "bearer") {
|
||||||
opts.auth = {
|
opts.auth = {
|
||||||
bearer: auth.pass
|
bearer: auth.pass
|
||||||
};
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
opts.auth = {
|
opts.auth = {
|
||||||
user: auth.user,
|
user: auth.user,
|
||||||
pass: auth.pass
|
pass: auth.pass
|
||||||
};
|
};
|
||||||
|
|
||||||
if(auth.method === "digest"){
|
if (auth.method === "digest") {
|
||||||
opts.auth.sendImmediately = false;
|
opts.auth.sendImmediately = false;
|
||||||
} else {
|
} else {
|
||||||
opts.auth.sendImmediately = true;
|
opts.auth.sendImmediately = true;
|
||||||
|
@ -53,7 +51,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ical.fromURL(url, opts, function(err, data) {
|
ical.fromURL(url, opts, function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
fetchFailedCallback(self, err);
|
fetchFailedCallback(self, err);
|
||||||
scheduleTimer();
|
scheduleTimer();
|
||||||
|
@ -64,17 +62,19 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
var newEvents = [];
|
var newEvents = [];
|
||||||
|
|
||||||
// limitFunction doesn't do much limiting, see comment re: the dates array in rrule section below as to why we need to do the filtering ourselves
|
// limitFunction doesn't do much limiting, see comment re: the dates array in rrule section below as to why we need to do the filtering ourselves
|
||||||
var limitFunction = function(date, i) {return true;};
|
var limitFunction = function (date, i) {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
var eventDate = function(event, time) {
|
var eventDate = function (event, time) {
|
||||||
return (event[time].length === 8) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var e in data) {
|
for (var e in data) {
|
||||||
var event = data[e];
|
var event = data[e];
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
var today = moment().startOf("day").toDate();
|
var today = moment().startOf("day").toDate();
|
||||||
var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1,"seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat.
|
var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat.
|
||||||
var past = today;
|
var past = today;
|
||||||
|
|
||||||
if (includePastEvents) {
|
if (includePastEvents) {
|
||||||
|
@ -91,13 +91,12 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type === "VEVENT") {
|
if (event.type === "VEVENT") {
|
||||||
|
|
||||||
var startDate = eventDate(event, "start");
|
var startDate = eventDate(event, "start");
|
||||||
var endDate;
|
var endDate;
|
||||||
if (typeof event.end !== "undefined") {
|
if (typeof event.end !== "undefined") {
|
||||||
endDate = eventDate(event, "end");
|
endDate = eventDate(event, "end");
|
||||||
} else if(typeof event.duration !== "undefined") {
|
} else if (typeof event.duration !== "undefined") {
|
||||||
var dur=moment.duration(event.duration);
|
var dur = moment.duration(event.duration);
|
||||||
endDate = startDate.clone().add(dur);
|
endDate = startDate.clone().add(dur);
|
||||||
} else {
|
} else {
|
||||||
if (!isFacebookBirthday) {
|
if (!isFacebookBirthday) {
|
||||||
|
@ -175,8 +174,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
var addedEvents = 0;
|
var addedEvents = 0;
|
||||||
|
|
||||||
// can cause problems with e.g. birthdays before 1900
|
// can cause problems with e.g. birthdays before 1900
|
||||||
if(rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 ||
|
if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) {
|
||||||
rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900){
|
|
||||||
rule.origOptions.dtstart.setYear(1900);
|
rule.origOptions.dtstart.setYear(1900);
|
||||||
rule.options.dtstart.setYear(1900);
|
rule.options.dtstart.setYear(1900);
|
||||||
}
|
}
|
||||||
|
@ -187,7 +185,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate();
|
var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate();
|
||||||
var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate();
|
var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate();
|
||||||
var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction);
|
var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction);
|
||||||
var dates = datesLocal.map(function(dateLocal) {
|
var dates = datesLocal.map(function (dateLocal) {
|
||||||
var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate();
|
var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate();
|
||||||
return date;
|
return date;
|
||||||
});
|
});
|
||||||
|
@ -199,17 +197,14 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
// because the logic below will filter out any recurrences that don"t actually belong within
|
// because the logic below will filter out any recurrences that don"t actually belong within
|
||||||
// our display range.
|
// our display range.
|
||||||
// Would be great if there was a better way to handle this.
|
// Would be great if there was a better way to handle this.
|
||||||
if (event.recurrences !== undefined)
|
if (event.recurrences !== undefined) {
|
||||||
{
|
|
||||||
var pastMoment = moment(past);
|
var pastMoment = moment(past);
|
||||||
var futureMoment = moment(future);
|
var futureMoment = moment(future);
|
||||||
|
|
||||||
for (var r in event.recurrences)
|
for (var r in event.recurrences) {
|
||||||
{
|
|
||||||
// Only add dates that weren't already in the range we added from the rrule so that
|
// Only add dates that weren't already in the range we added from the rrule so that
|
||||||
// we don"t double-add those events.
|
// we don"t double-add those events.
|
||||||
if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true)
|
if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true) {
|
||||||
{
|
|
||||||
dates.push(new Date(r));
|
dates.push(new Date(r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +216,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
// ical.js started returning recurrences and exdates as ISOStrings without time information.
|
// ical.js started returning recurrences and exdates as ISOStrings without time information.
|
||||||
// .toISOString().substring(0,10) is the method they use to calculate keys, so we'll do the same
|
// .toISOString().substring(0,10) is the method they use to calculate keys, so we'll do the same
|
||||||
// (see https://github.com/peterbraden/ical.js/pull/84 )
|
// (see https://github.com/peterbraden/ical.js/pull/84 )
|
||||||
var dateKey = date.toISOString().substring(0,10);
|
var dateKey = date.toISOString().substring(0, 10);
|
||||||
var curEvent = event;
|
var curEvent = event;
|
||||||
var showRecurrence = true;
|
var showRecurrence = true;
|
||||||
|
|
||||||
|
@ -234,16 +229,14 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
startDate = moment(date);
|
startDate = moment(date);
|
||||||
|
|
||||||
// For each date that we"re checking, it"s possible that there is a recurrence override for that one day.
|
// For each date that we"re checking, it"s possible that there is a recurrence override for that one day.
|
||||||
if ((curEvent.recurrences !== undefined) && (curEvent.recurrences[dateKey] !== undefined))
|
if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) {
|
||||||
{
|
|
||||||
// We found an override, so for this recurrence, use a potentially different title, start date, and duration.
|
// We found an override, so for this recurrence, use a potentially different title, start date, and duration.
|
||||||
curEvent = curEvent.recurrences[dateKey];
|
curEvent = curEvent.recurrences[dateKey];
|
||||||
startDate = moment(curEvent.start);
|
startDate = moment(curEvent.start);
|
||||||
duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x"));
|
duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x"));
|
||||||
}
|
}
|
||||||
// If there"s no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
|
// If there"s no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
|
||||||
else if ((curEvent.exdate !== undefined) && (curEvent.exdate[dateKey] !== undefined))
|
else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) {
|
||||||
{
|
|
||||||
// This date is an exception date, which means we should skip it in the recurrence pattern.
|
// This date is an exception date, which means we should skip it in the recurrence pattern.
|
||||||
showRecurrence = false;
|
showRecurrence = false;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +258,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
showRecurrence = false;
|
showRecurrence = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((showRecurrence === true) && (addedEvents < maximumEntries)) {
|
if (showRecurrence === true && addedEvents < maximumEntries) {
|
||||||
addedEvents++;
|
addedEvents++;
|
||||||
newEvents.push({
|
newEvents.push({
|
||||||
title: recurrenceTitle,
|
title: recurrenceTitle,
|
||||||
|
@ -284,7 +277,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
} else {
|
} else {
|
||||||
// console.log("Single event ...");
|
// console.log("Single event ...");
|
||||||
// Single event.
|
// Single event.
|
||||||
var fullDayEvent = (isFacebookBirthday) ? true : isFullDayEvent(event);
|
var fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event);
|
||||||
|
|
||||||
if (includePastEvents) {
|
if (includePastEvents) {
|
||||||
if (endDate < past) {
|
if (endDate < past) {
|
||||||
|
@ -329,12 +322,11 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
geo: geo,
|
geo: geo,
|
||||||
description: description
|
description: description
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newEvents.sort(function(a, b) {
|
newEvents.sort(function (a, b) {
|
||||||
return a.startDate - b.startDate;
|
return a.startDate - b.startDate;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -350,10 +342,10 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
/* scheduleTimer()
|
/* scheduleTimer()
|
||||||
* Schedule the timer for the next update.
|
* Schedule the timer for the next update.
|
||||||
*/
|
*/
|
||||||
var scheduleTimer = function() {
|
var scheduleTimer = function () {
|
||||||
//console.log('Schedule update timer.');
|
//console.log('Schedule update timer.');
|
||||||
clearTimeout(reloadTimer);
|
clearTimeout(reloadTimer);
|
||||||
reloadTimer = setTimeout(function() {
|
reloadTimer = setTimeout(function () {
|
||||||
fetchCalendar();
|
fetchCalendar();
|
||||||
}, reloadInterval);
|
}, reloadInterval);
|
||||||
};
|
};
|
||||||
|
@ -365,7 +357,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
*
|
*
|
||||||
* return bool - The event is a fullday event.
|
* return bool - The event is a fullday event.
|
||||||
*/
|
*/
|
||||||
var isFullDayEvent = function(event) {
|
var isFullDayEvent = function (event) {
|
||||||
if (event.start.length === 8 || event.start.dateOnly) {
|
if (event.start.length === 8 || event.start.dateOnly) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +365,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
var start = event.start || 0;
|
var start = event.start || 0;
|
||||||
var startDate = new Date(start);
|
var startDate = new Date(start);
|
||||||
var end = event.end || 0;
|
var end = event.end || 0;
|
||||||
if (((end - start) % (24 * 60 * 60 * 1000)) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) {
|
if ((end - start) % (24 * 60 * 60 * 1000) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) {
|
||||||
// Is 24 hours, and starts on the middle of the night.
|
// Is 24 hours, and starts on the middle of the night.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +382,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
*
|
*
|
||||||
* return bool - The event should be filtered out
|
* return bool - The event should be filtered out
|
||||||
*/
|
*/
|
||||||
var timeFilterApplies = function(now, endDate, filter) {
|
var timeFilterApplies = function (now, endDate, filter) {
|
||||||
if (filter) {
|
if (filter) {
|
||||||
var until = filter.split(" "),
|
var until = filter.split(" "),
|
||||||
value = parseInt(until[0]),
|
value = parseInt(until[0]),
|
||||||
|
@ -413,7 +405,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
var getTitleFromEvent = function (event) {
|
var getTitleFromEvent = function (event) {
|
||||||
var title = "Event";
|
var title = "Event";
|
||||||
if (event.summary) {
|
if (event.summary) {
|
||||||
title = (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary;
|
title = typeof event.summary.val !== "undefined" ? event.summary.val : event.summary;
|
||||||
} else if (event.description) {
|
} else if (event.description) {
|
||||||
title = event.description;
|
title = event.description;
|
||||||
}
|
}
|
||||||
|
@ -442,14 +434,14 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
/* startFetch()
|
/* startFetch()
|
||||||
* Initiate fetchCalendar();
|
* Initiate fetchCalendar();
|
||||||
*/
|
*/
|
||||||
this.startFetch = function() {
|
this.startFetch = function () {
|
||||||
fetchCalendar();
|
fetchCalendar();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* broadcastItems()
|
/* broadcastItems()
|
||||||
* Broadcast the existing events.
|
* Broadcast the existing events.
|
||||||
*/
|
*/
|
||||||
this.broadcastEvents = function() {
|
this.broadcastEvents = function () {
|
||||||
//console.log('Broadcasting ' + events.length + ' events.');
|
//console.log('Broadcasting ' + events.length + ' events.');
|
||||||
eventsReceivedCallback(self);
|
eventsReceivedCallback(self);
|
||||||
};
|
};
|
||||||
|
@ -459,7 +451,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
*
|
*
|
||||||
* argument callback function - The on success callback.
|
* argument callback function - The on success callback.
|
||||||
*/
|
*/
|
||||||
this.onReceive = function(callback) {
|
this.onReceive = function (callback) {
|
||||||
eventsReceivedCallback = callback;
|
eventsReceivedCallback = callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -468,7 +460,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
*
|
*
|
||||||
* argument callback function - The on error callback.
|
* argument callback function - The on error callback.
|
||||||
*/
|
*/
|
||||||
this.onError = function(callback) {
|
this.onError = function (callback) {
|
||||||
fetchFailedCallback = callback;
|
fetchFailedCallback = callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -477,7 +469,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
*
|
*
|
||||||
* return string - The url of this fetcher.
|
* return string - The url of this fetcher.
|
||||||
*/
|
*/
|
||||||
this.url = function() {
|
this.url = function () {
|
||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -486,7 +478,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
||||||
*
|
*
|
||||||
* return array - The current available events for this fetcher.
|
* return array - The current available events for this fetcher.
|
||||||
*/
|
*/
|
||||||
this.events = function() {
|
this.events = function () {
|
||||||
return events;
|
return events;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,12 +24,12 @@ console.log("Create fetcher ...");
|
||||||
|
|
||||||
var fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth);
|
var fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth);
|
||||||
|
|
||||||
fetcher.onReceive(function(fetcher) {
|
fetcher.onReceive(function (fetcher) {
|
||||||
console.log(fetcher.events());
|
console.log(fetcher.events());
|
||||||
console.log("------------------------------------------------------------");
|
console.log("------------------------------------------------------------");
|
||||||
});
|
});
|
||||||
|
|
||||||
fetcher.onError(function(fetcher, error) {
|
fetcher.onError(function (fetcher, error) {
|
||||||
console.log("Fetcher error:");
|
console.log("Fetcher error:");
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,17 +11,16 @@ var CalendarFetcher = require("./calendarfetcher.js");
|
||||||
|
|
||||||
module.exports = NodeHelper.create({
|
module.exports = NodeHelper.create({
|
||||||
// Override start method.
|
// Override start method.
|
||||||
start: function() {
|
start: function () {
|
||||||
var events = [];
|
var events = [];
|
||||||
|
|
||||||
this.fetchers = [];
|
this.fetchers = [];
|
||||||
|
|
||||||
console.log("Starting node helper for: " + this.name);
|
console.log("Starting node helper for: " + this.name);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override socketNotificationReceived method.
|
// Override socketNotificationReceived method.
|
||||||
socketNotificationReceived: function(notification, payload) {
|
socketNotificationReceived: function (notification, payload) {
|
||||||
if (notification === "ADD_CALENDAR") {
|
if (notification === "ADD_CALENDAR") {
|
||||||
//console.log('ADD_CALENDAR: ');
|
//console.log('ADD_CALENDAR: ');
|
||||||
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents);
|
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents);
|
||||||
|
@ -36,11 +35,11 @@ module.exports = NodeHelper.create({
|
||||||
* attribute reloadInterval number - Reload interval in milliseconds.
|
* attribute reloadInterval number - Reload interval in milliseconds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
createFetcher: function(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents) {
|
createFetcher: function (url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (!validUrl.isUri(url)) {
|
if (!validUrl.isUri(url)) {
|
||||||
self.sendSocketNotification("INCORRECT_URL", {url: url});
|
self.sendSocketNotification("INCORRECT_URL", { url: url });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ module.exports = NodeHelper.create({
|
||||||
console.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval);
|
console.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval);
|
||||||
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents);
|
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents);
|
||||||
|
|
||||||
fetcher.onReceive(function(fetcher) {
|
fetcher.onReceive(function (fetcher) {
|
||||||
//console.log('Broadcast events.');
|
//console.log('Broadcast events.');
|
||||||
//console.log(fetcher.events());
|
//console.log(fetcher.events());
|
||||||
|
|
||||||
|
@ -59,7 +58,7 @@ module.exports = NodeHelper.create({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
fetcher.onError(function(fetcher, error) {
|
fetcher.onError(function (fetcher, error) {
|
||||||
console.error("Calendar Error. Could not fetch calendar: ", fetcher.url(), error);
|
console.error("Calendar Error. Could not fetch calendar: ", fetcher.url(), error);
|
||||||
self.sendSocketNotification("FETCH_ERROR", {
|
self.sendSocketNotification("FETCH_ERROR", {
|
||||||
url: fetcher.url(),
|
url: fetcher.url(),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Clock
|
# Module: Clock
|
||||||
|
|
||||||
The `clock` module is one of the default modules of the MagicMirror.
|
The `clock` module is one of the default modules of the MagicMirror.
|
||||||
This module displays the current date and time. The information will be updated realtime.
|
This module displays the current date and time. The information will be updated realtime.
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("clock",{
|
Module.register("clock", {
|
||||||
// Module config defaults.
|
// Module config defaults.
|
||||||
defaults: {
|
defaults: {
|
||||||
displayType: "digital", // options: digital, analog, both
|
displayType: "digital", // options: digital, analog, both
|
||||||
|
@ -31,18 +31,18 @@ Module.register("clock",{
|
||||||
showSunTimes: false,
|
showSunTimes: false,
|
||||||
showMoonTimes: false,
|
showMoonTimes: false,
|
||||||
lat: 47.630539,
|
lat: 47.630539,
|
||||||
lon: -122.344147,
|
lon: -122.344147
|
||||||
},
|
},
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getScripts: function() {
|
getScripts: function () {
|
||||||
return ["moment.js", "moment-timezone.js", "suncalc.js"];
|
return ["moment.js", "moment-timezone.js", "suncalc.js"];
|
||||||
},
|
},
|
||||||
// Define styles.
|
// Define styles.
|
||||||
getStyles: function() {
|
getStyles: function () {
|
||||||
return ["clock_styles.css"];
|
return ["clock_styles.css"];
|
||||||
},
|
},
|
||||||
// Define start sequence.
|
// Define start sequence.
|
||||||
start: function() {
|
start: function () {
|
||||||
Log.info("Starting module: " + this.name);
|
Log.info("Starting module: " + this.name);
|
||||||
|
|
||||||
// Schedule update interval.
|
// Schedule update interval.
|
||||||
|
@ -51,16 +51,16 @@ Module.register("clock",{
|
||||||
self.minute = moment().minute();
|
self.minute = moment().minute();
|
||||||
|
|
||||||
//Calculate how many ms should pass until next update depending on if seconds is displayed or not
|
//Calculate how many ms should pass until next update depending on if seconds is displayed or not
|
||||||
var delayCalculator = function(reducedSeconds) {
|
var delayCalculator = function (reducedSeconds) {
|
||||||
if (self.config.displaySeconds) {
|
if (self.config.displaySeconds) {
|
||||||
return 1000 - moment().milliseconds();
|
return 1000 - moment().milliseconds();
|
||||||
} else {
|
} else {
|
||||||
return ((60 - reducedSeconds) * 1000) - moment().milliseconds();
|
return (60 - reducedSeconds) * 1000 - moment().milliseconds();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//A recursive timeout function instead of interval to avoid drifting
|
//A recursive timeout function instead of interval to avoid drifting
|
||||||
var notificationTimer = function() {
|
var notificationTimer = function () {
|
||||||
self.updateDom();
|
self.updateDom();
|
||||||
|
|
||||||
//If seconds is displayed CLOCK_SECOND-notification should be sent (but not when CLOCK_MINUTE-notification is sent)
|
//If seconds is displayed CLOCK_SECOND-notification should be sent (but not when CLOCK_MINUTE-notification is sent)
|
||||||
|
@ -84,11 +84,9 @@ Module.register("clock",{
|
||||||
|
|
||||||
// Set locale.
|
// Set locale.
|
||||||
moment.locale(config.language);
|
moment.locale(config.language);
|
||||||
|
|
||||||
},
|
},
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function() {
|
getDom: function () {
|
||||||
|
|
||||||
var wrapper = document.createElement("div");
|
var wrapper = document.createElement("div");
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
|
@ -127,12 +125,12 @@ Module.register("clock",{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.clockBold === true) {
|
if (this.config.clockBold === true) {
|
||||||
timeString = now.format(hourSymbol + "[<span class=\"bold\">]mm[</span>]");
|
timeString = now.format(hourSymbol + '[<span class="bold">]mm[</span>]');
|
||||||
} else {
|
} else {
|
||||||
timeString = now.format(hourSymbol + ":mm");
|
timeString = now.format(hourSymbol + ":mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.config.showDate){
|
if (this.config.showDate) {
|
||||||
dateWrapper.innerHTML = now.format(this.config.dateFormat);
|
dateWrapper.innerHTML = now.format(this.config.dateFormat);
|
||||||
}
|
}
|
||||||
if (this.config.showWeek) {
|
if (this.config.showWeek) {
|
||||||
|
@ -173,9 +171,18 @@ Module.register("clock",{
|
||||||
}
|
}
|
||||||
const untilNextEvent = moment.duration(moment(nextEvent).diff(now));
|
const untilNextEvent = moment.duration(moment(nextEvent).diff(now));
|
||||||
const untilNextEventString = untilNextEvent.hours() + "h " + untilNextEvent.minutes() + "m";
|
const untilNextEventString = untilNextEvent.hours() + "h " + untilNextEvent.minutes() + "m";
|
||||||
sunWrapper.innerHTML = "<span class=\"" + (isVisible ? "bright" : "") + "\"><i class=\"fa fa-sun-o\" aria-hidden=\"true\"></i> " + untilNextEventString + "</span>" +
|
sunWrapper.innerHTML =
|
||||||
"<span><i class=\"fa fa-arrow-up\" aria-hidden=\"true\"></i>" + formatTime(this.config, sunTimes.sunrise) + "</span>" +
|
'<span class="' +
|
||||||
"<span><i class=\"fa fa-arrow-down\" aria-hidden=\"true\"></i>" + formatTime(this.config, sunTimes.sunset) + "</span>";
|
(isVisible ? "bright" : "") +
|
||||||
|
'"><i class="fa fa-sun-o" aria-hidden="true"></i> ' +
|
||||||
|
untilNextEventString +
|
||||||
|
"</span>" +
|
||||||
|
'<span><i class="fa fa-arrow-up" aria-hidden="true"></i>' +
|
||||||
|
formatTime(this.config, sunTimes.sunrise) +
|
||||||
|
"</span>" +
|
||||||
|
'<span><i class="fa fa-arrow-down" aria-hidden="true"></i>' +
|
||||||
|
formatTime(this.config, sunTimes.sunset) +
|
||||||
|
"</span>";
|
||||||
}
|
}
|
||||||
if (this.config.showMoonTimes) {
|
if (this.config.showMoonTimes) {
|
||||||
const moonIllumination = SunCalc.getMoonIllumination(now.toDate());
|
const moonIllumination = SunCalc.getMoonIllumination(now.toDate());
|
||||||
|
@ -190,9 +197,18 @@ Module.register("clock",{
|
||||||
}
|
}
|
||||||
const isVisible = now.isBetween(moonRise, moonSet) || moonTimes.alwaysUp === true;
|
const isVisible = now.isBetween(moonRise, moonSet) || moonTimes.alwaysUp === true;
|
||||||
const illuminatedFractionString = Math.round(moonIllumination.fraction * 100) + "%";
|
const illuminatedFractionString = Math.round(moonIllumination.fraction * 100) + "%";
|
||||||
moonWrapper.innerHTML = "<span class=\"" + (isVisible ? "bright" : "") + "\"><i class=\"fa fa-moon-o\" aria-hidden=\"true\"></i> " + illuminatedFractionString + "</span>" +
|
moonWrapper.innerHTML =
|
||||||
"<span><i class=\"fa fa-arrow-up\" aria-hidden=\"true\"></i> " + (moonRise ? formatTime(this.config, moonRise) : "...") + "</span>"+
|
'<span class="' +
|
||||||
"<span><i class=\"fa fa-arrow-down\" aria-hidden=\"true\"></i> " + (moonSet ? formatTime(this.config, moonSet) : "...") + "</span>";
|
(isVisible ? "bright" : "") +
|
||||||
|
'"><i class="fa fa-moon-o" aria-hidden="true"></i> ' +
|
||||||
|
illuminatedFractionString +
|
||||||
|
"</span>" +
|
||||||
|
'<span><i class="fa fa-arrow-up" aria-hidden="true"></i> ' +
|
||||||
|
(moonRise ? formatTime(this.config, moonRise) : "...") +
|
||||||
|
"</span>" +
|
||||||
|
'<span><i class="fa fa-arrow-down" aria-hidden="true"></i> ' +
|
||||||
|
(moonSet ? formatTime(this.config, moonSet) : "...") +
|
||||||
|
"</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
|
@ -217,13 +233,12 @@ Module.register("clock",{
|
||||||
clockCircle.style.height = this.config.analogSize;
|
clockCircle.style.height = this.config.analogSize;
|
||||||
|
|
||||||
if (this.config.analogFace !== "" && this.config.analogFace !== "simple" && this.config.analogFace !== "none") {
|
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.background = "url(" + this.data.path + "faces/" + this.config.analogFace + ".svg)";
|
||||||
clockCircle.style.backgroundSize = "100%";
|
clockCircle.style.backgroundSize = "100%";
|
||||||
|
|
||||||
// The following line solves issue: https://github.com/MichMich/MagicMirror/issues/611
|
// The following line solves issue: https://github.com/MichMich/MagicMirror/issues/611
|
||||||
// clockCircle.style.border = "1px solid black";
|
// clockCircle.style.border = "1px solid black";
|
||||||
clockCircle.style.border = "rgba(0, 0, 0, 0.1)"; //Updated fix for Issue 611 where non-black backgrounds are used
|
clockCircle.style.border = "rgba(0, 0, 0, 0.1)"; //Updated fix for Issue 611 where non-black backgrounds are used
|
||||||
|
|
||||||
} else if (this.config.analogFace !== "none") {
|
} else if (this.config.analogFace !== "none") {
|
||||||
clockCircle.style.border = "2px solid white";
|
clockCircle.style.border = "2px solid white";
|
||||||
}
|
}
|
||||||
|
@ -303,9 +318,9 @@ Module.register("clock",{
|
||||||
digitalWrapper.appendChild(moonWrapper);
|
digitalWrapper.appendChild(moonWrapper);
|
||||||
digitalWrapper.appendChild(weekWrapper);
|
digitalWrapper.appendChild(weekWrapper);
|
||||||
|
|
||||||
var appendClocks = function(condition, pos1, pos2) {
|
var appendClocks = function (condition, pos1, pos2) {
|
||||||
var padding = [0,0,0,0];
|
var padding = [0, 0, 0, 0];
|
||||||
padding[(placement === condition) ? pos1 : pos2] = "20px";
|
padding[placement === condition ? pos1 : pos2] = "20px";
|
||||||
analogWrapper.style.padding = padding.join(" ");
|
analogWrapper.style.padding = padding.join(" ");
|
||||||
if (placement === condition) {
|
if (placement === condition) {
|
||||||
wrapper.appendChild(analogWrapper);
|
wrapper.appendChild(analogWrapper);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Compliments
|
# Module: Compliments
|
||||||
|
|
||||||
The `compliments` module is one of the default modules of the MagicMirror.
|
The `compliments` module is one of the default modules of the MagicMirror.
|
||||||
This module displays a random compliment.
|
This module displays a random compliment.
|
||||||
|
|
||||||
|
|
|
@ -5,31 +5,14 @@
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("compliments", {
|
Module.register("compliments", {
|
||||||
|
|
||||||
// Module config defaults.
|
// Module config defaults.
|
||||||
defaults: {
|
defaults: {
|
||||||
compliments: {
|
compliments: {
|
||||||
anytime: [
|
anytime: ["Hey there sexy!"],
|
||||||
"Hey there sexy!"
|
morning: ["Good morning, handsome!", "Enjoy your day!", "How was your sleep?"],
|
||||||
],
|
afternoon: ["Hello, beauty!", "You look sexy!", "Looking good today!"],
|
||||||
morning: [
|
evening: ["Wow, you look hot!", "You look nice!", "Hi, sexy!"],
|
||||||
"Good morning, handsome!",
|
"....-01-01": ["Happy new year!"]
|
||||||
"Enjoy your day!",
|
|
||||||
"How was your sleep?"
|
|
||||||
],
|
|
||||||
afternoon: [
|
|
||||||
"Hello, beauty!",
|
|
||||||
"You look sexy!",
|
|
||||||
"Looking good today!"
|
|
||||||
],
|
|
||||||
evening: [
|
|
||||||
"Wow, you look hot!",
|
|
||||||
"You look nice!",
|
|
||||||
"Hi, sexy!"
|
|
||||||
],
|
|
||||||
"....-01-01": [
|
|
||||||
"Happy new year!"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
updateInterval: 30000,
|
updateInterval: 30000,
|
||||||
remoteFile: null,
|
remoteFile: null,
|
||||||
|
@ -41,31 +24,31 @@ Module.register("compliments", {
|
||||||
random: true,
|
random: true,
|
||||||
mockDate: null
|
mockDate: null
|
||||||
},
|
},
|
||||||
lastIndexUsed:-1,
|
lastIndexUsed: -1,
|
||||||
// Set currentweather from module
|
// Set currentweather from module
|
||||||
currentWeatherType: "",
|
currentWeatherType: "",
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getScripts: function() {
|
getScripts: function () {
|
||||||
return ["moment.js"];
|
return ["moment.js"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define start sequence.
|
// Define start sequence.
|
||||||
start: function() {
|
start: function () {
|
||||||
Log.info("Starting module: " + this.name);
|
Log.info("Starting module: " + this.name);
|
||||||
|
|
||||||
this.lastComplimentIndex = -1;
|
this.lastComplimentIndex = -1;
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this.config.remoteFile !== null) {
|
if (this.config.remoteFile !== null) {
|
||||||
this.complimentFile(function(response) {
|
this.complimentFile(function (response) {
|
||||||
self.config.compliments = JSON.parse(response);
|
self.config.compliments = JSON.parse(response);
|
||||||
self.updateDom();
|
self.updateDom();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule update timer.
|
// Schedule update timer.
|
||||||
setInterval(function() {
|
setInterval(function () {
|
||||||
self.updateDom(self.config.fadeSpeed);
|
self.updateDom(self.config.fadeSpeed);
|
||||||
}, this.config.updateInterval);
|
}, this.config.updateInterval);
|
||||||
},
|
},
|
||||||
|
@ -77,12 +60,12 @@ Module.register("compliments", {
|
||||||
*
|
*
|
||||||
* return Number - Random index.
|
* return Number - Random index.
|
||||||
*/
|
*/
|
||||||
randomIndex: function(compliments) {
|
randomIndex: function (compliments) {
|
||||||
if (compliments.length === 1) {
|
if (compliments.length === 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var generate = function() {
|
var generate = function () {
|
||||||
return Math.floor(Math.random() * compliments.length);
|
return Math.floor(Math.random() * compliments.length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,7 +85,7 @@ Module.register("compliments", {
|
||||||
*
|
*
|
||||||
* return compliments Array<String> - Array with compliments for the time of the day.
|
* return compliments Array<String> - Array with compliments for the time of the day.
|
||||||
*/
|
*/
|
||||||
complimentArray: function() {
|
complimentArray: function () {
|
||||||
var hour = moment().hour();
|
var hour = moment().hour();
|
||||||
var date = this.config.mockDate ? this.config.mockDate : moment().format("YYYY-MM-DD");
|
var date = this.config.mockDate ? this.config.mockDate : moment().format("YYYY-MM-DD");
|
||||||
var compliments;
|
var compliments;
|
||||||
|
@ -111,7 +94,7 @@ Module.register("compliments", {
|
||||||
compliments = this.config.compliments.morning.slice(0);
|
compliments = this.config.compliments.morning.slice(0);
|
||||||
} else if (hour >= this.config.afternoonStartTime && hour < this.config.afternoonEndTime && 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);
|
compliments = this.config.compliments.afternoon.slice(0);
|
||||||
} else if(this.config.compliments.hasOwnProperty("evening")) {
|
} else if (this.config.compliments.hasOwnProperty("evening")) {
|
||||||
compliments = this.config.compliments.evening.slice(0);
|
compliments = this.config.compliments.evening.slice(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,13 +120,13 @@ Module.register("compliments", {
|
||||||
/* complimentFile(callback)
|
/* complimentFile(callback)
|
||||||
* Retrieve a file from the local filesystem
|
* Retrieve a file from the local filesystem
|
||||||
*/
|
*/
|
||||||
complimentFile: function(callback) {
|
complimentFile: function (callback) {
|
||||||
var xobj = new XMLHttpRequest(),
|
var xobj = new XMLHttpRequest(),
|
||||||
isRemote = this.config.remoteFile.indexOf("http://") === 0 || this.config.remoteFile.indexOf("https://") === 0,
|
isRemote = this.config.remoteFile.indexOf("http://") === 0 || this.config.remoteFile.indexOf("https://") === 0,
|
||||||
path = isRemote ? this.config.remoteFile : this.file(this.config.remoteFile);
|
path = isRemote ? this.config.remoteFile : this.file(this.config.remoteFile);
|
||||||
xobj.overrideMimeType("application/json");
|
xobj.overrideMimeType("application/json");
|
||||||
xobj.open("GET", path, true);
|
xobj.open("GET", path, true);
|
||||||
xobj.onreadystatechange = function() {
|
xobj.onreadystatechange = function () {
|
||||||
if (xobj.readyState === 4 && xobj.status === 200) {
|
if (xobj.readyState === 4 && xobj.status === 200) {
|
||||||
callback(xobj.responseText);
|
callback(xobj.responseText);
|
||||||
}
|
}
|
||||||
|
@ -156,27 +139,26 @@ Module.register("compliments", {
|
||||||
*
|
*
|
||||||
* return compliment string - A compliment.
|
* return compliment string - A compliment.
|
||||||
*/
|
*/
|
||||||
randomCompliment: function() {
|
randomCompliment: function () {
|
||||||
// get the current time of day compliments list
|
// get the current time of day compliments list
|
||||||
var compliments = this.complimentArray();
|
var compliments = this.complimentArray();
|
||||||
// variable for index to next message to display
|
// variable for index to next message to display
|
||||||
let index = 0;
|
let index = 0;
|
||||||
// are we randomizing
|
// are we randomizing
|
||||||
if(this.config.random){
|
if (this.config.random) {
|
||||||
// yes
|
// yes
|
||||||
index = this.randomIndex(compliments);
|
index = this.randomIndex(compliments);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
// no, sequential
|
// no, sequential
|
||||||
// if doing sequential, don't fall off the end
|
// if doing sequential, don't fall off the end
|
||||||
index = (this.lastIndexUsed >= (compliments.length-1))?0: ++this.lastIndexUsed;
|
index = this.lastIndexUsed >= compliments.length - 1 ? 0 : ++this.lastIndexUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return compliments[index] || "";
|
return compliments[index] || "";
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function() {
|
getDom: function () {
|
||||||
var wrapper = document.createElement("div");
|
var wrapper = document.createElement("div");
|
||||||
wrapper.className = this.config.classes ? this.config.classes : "thin xlarge bright pre-line";
|
wrapper.className = this.config.classes ? this.config.classes : "thin xlarge bright pre-line";
|
||||||
// get the compliment text
|
// get the compliment text
|
||||||
|
@ -186,7 +168,7 @@ Module.register("compliments", {
|
||||||
// create a span to hold it all
|
// create a span to hold it all
|
||||||
var compliment = document.createElement("span");
|
var compliment = document.createElement("span");
|
||||||
// process all the parts of the compliment text
|
// process all the parts of the compliment text
|
||||||
for (var part of parts){
|
for (var part of parts) {
|
||||||
// create a text element for each part
|
// create a text element for each part
|
||||||
compliment.appendChild(document.createTextNode(part));
|
compliment.appendChild(document.createTextNode(part));
|
||||||
// add a break `
|
// add a break `
|
||||||
|
@ -200,7 +182,7 @@ Module.register("compliments", {
|
||||||
},
|
},
|
||||||
|
|
||||||
// From data currentweather set weather type
|
// From data currentweather set weather type
|
||||||
setCurrentWeatherType: function(data) {
|
setCurrentWeatherType: function (data) {
|
||||||
var weatherIconTable = {
|
var weatherIconTable = {
|
||||||
"01d": "day_sunny",
|
"01d": "day_sunny",
|
||||||
"02d": "day_cloudy",
|
"02d": "day_cloudy",
|
||||||
|
@ -225,10 +207,9 @@ Module.register("compliments", {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override notification handler.
|
// Override notification handler.
|
||||||
notificationReceived: function(notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
if (notification === "CURRENTWEATHER_DATA") {
|
if (notification === "CURRENTWEATHER_DATA") {
|
||||||
this.setCurrentWeatherType(payload.data);
|
this.setCurrentWeatherType(payload.data);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Current Weather
|
# Module: Current Weather
|
||||||
|
|
||||||
The `currentweather` module is one of the default modules of the MagicMirror.
|
The `currentweather` module is one of the default modules of the MagicMirror.
|
||||||
This module displays the current weather, including the windspeed, the sunset or sunrise time, the temperature and an icon to display the current conditions.
|
This module displays the current weather, including the windspeed, the sunset or sunrise time, the temperature and an icon to display the current conditions.
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("currentweather",{
|
Module.register("currentweather", {
|
||||||
|
|
||||||
// Default module config.
|
// Default module config.
|
||||||
defaults: {
|
defaults: {
|
||||||
location: false,
|
location: false,
|
||||||
|
@ -63,7 +62,7 @@ Module.register("currentweather",{
|
||||||
"11n": "wi-night-thunderstorm",
|
"11n": "wi-night-thunderstorm",
|
||||||
"13n": "wi-night-snow",
|
"13n": "wi-night-snow",
|
||||||
"50n": "wi-night-alt-cloudy-windy"
|
"50n": "wi-night-alt-cloudy-windy"
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// create a variable for the first upcoming calendar event. Used if no location is specified.
|
// create a variable for the first upcoming calendar event. Used if no location is specified.
|
||||||
|
@ -73,17 +72,17 @@ Module.register("currentweather",{
|
||||||
fetchedLocationName: "",
|
fetchedLocationName: "",
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getScripts: function() {
|
getScripts: function () {
|
||||||
return ["moment.js"];
|
return ["moment.js"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getStyles: function() {
|
getStyles: function () {
|
||||||
return ["weather-icons.css", "currentweather.css"];
|
return ["weather-icons.css", "currentweather.css"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required translations.
|
// Define required translations.
|
||||||
getTranslations: function() {
|
getTranslations: function () {
|
||||||
// The translations for the default modules are defined in the core translation files.
|
// The translations for the default modules are defined in the core translation files.
|
||||||
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
||||||
// If you're trying to build your own module including translations, check out the documentation.
|
// If you're trying to build your own module including translations, check out the documentation.
|
||||||
|
@ -91,7 +90,7 @@ Module.register("currentweather",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define start sequence.
|
// Define start sequence.
|
||||||
start: function() {
|
start: function () {
|
||||||
Log.info("Starting module: " + this.name);
|
Log.info("Starting module: " + this.name);
|
||||||
|
|
||||||
// Set locale.
|
// Set locale.
|
||||||
|
@ -109,13 +108,11 @@ Module.register("currentweather",{
|
||||||
this.feelsLike = null;
|
this.feelsLike = null;
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.scheduleUpdate(this.config.initialLoadDelay);
|
this.scheduleUpdate(this.config.initialLoadDelay);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// add extra information of current weather
|
// add extra information of current weather
|
||||||
// windDirection, humidity, sunrise and sunset
|
// windDirection, humidity, sunrise and sunset
|
||||||
addExtraInfoWeather: function(wrapper) {
|
addExtraInfoWeather: function (wrapper) {
|
||||||
|
|
||||||
var small = document.createElement("div");
|
var small = document.createElement("div");
|
||||||
small.className = "normal medium";
|
small.className = "normal medium";
|
||||||
|
|
||||||
|
@ -130,8 +127,8 @@ Module.register("currentweather",{
|
||||||
if (this.config.showWindDirection) {
|
if (this.config.showWindDirection) {
|
||||||
var windDirection = document.createElement("sup");
|
var windDirection = document.createElement("sup");
|
||||||
if (this.config.showWindDirectionAsArrow) {
|
if (this.config.showWindDirectionAsArrow) {
|
||||||
if(this.windDeg !== null) {
|
if (this.windDeg !== null) {
|
||||||
windDirection.innerHTML = " <i class=\"fa fa-long-arrow-down\" style=\"transform:rotate("+this.windDeg+"deg);\"></i> ";
|
windDirection.innerHTML = ' <i class="fa fa-long-arrow-down" style="transform:rotate(' + this.windDeg + 'deg);"></i> ';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
windDirection.innerHTML = " " + this.translate(this.windDirection);
|
windDirection.innerHTML = " " + this.translate(this.windDirection);
|
||||||
|
@ -170,7 +167,7 @@ Module.register("currentweather",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function() {
|
getDom: function () {
|
||||||
var wrapper = document.createElement("div");
|
var wrapper = document.createElement("div");
|
||||||
wrapper.className = this.config.tableClass;
|
wrapper.className = this.config.tableClass;
|
||||||
|
|
||||||
|
@ -197,8 +194,8 @@ Module.register("currentweather",{
|
||||||
if (this.config.units === "metric" || this.config.units === "imperial") {
|
if (this.config.units === "metric" || this.config.units === "imperial") {
|
||||||
degreeLabel += "°";
|
degreeLabel += "°";
|
||||||
}
|
}
|
||||||
if(this.config.degreeLabel) {
|
if (this.config.degreeLabel) {
|
||||||
switch(this.config.units) {
|
switch (this.config.units) {
|
||||||
case "metric":
|
case "metric":
|
||||||
degreeLabel += "C";
|
degreeLabel += "C";
|
||||||
break;
|
break;
|
||||||
|
@ -250,7 +247,7 @@ Module.register("currentweather",{
|
||||||
|
|
||||||
wrapper.appendChild(large);
|
wrapper.appendChild(large);
|
||||||
|
|
||||||
if (this.config.showFeelsLike && this.config.onlyTemp === false){
|
if (this.config.showFeelsLike && this.config.onlyTemp === false) {
|
||||||
var small = document.createElement("div");
|
var small = document.createElement("div");
|
||||||
small.className = "normal medium";
|
small.className = "normal medium";
|
||||||
|
|
||||||
|
@ -266,7 +263,7 @@ Module.register("currentweather",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override getHeader method.
|
// Override getHeader method.
|
||||||
getHeader: function() {
|
getHeader: function () {
|
||||||
if (this.config.appendLocationNameToHeader && this.data.header !== undefined) {
|
if (this.config.appendLocationNameToHeader && this.data.header !== undefined) {
|
||||||
return this.data.header + " " + this.fetchedLocationName;
|
return this.data.header + " " + this.fetchedLocationName;
|
||||||
}
|
}
|
||||||
|
@ -279,10 +276,10 @@ Module.register("currentweather",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override notification handler.
|
// Override notification handler.
|
||||||
notificationReceived: function(notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
if (notification === "DOM_OBJECTS_CREATED") {
|
if (notification === "DOM_OBJECTS_CREATED") {
|
||||||
if (this.config.appendLocationNameToHeader) {
|
if (this.config.appendLocationNameToHeader) {
|
||||||
this.hide(0, {lockString: this.identifier});
|
this.hide(0, { lockString: this.identifier });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notification === "CALENDAR_EVENTS") {
|
if (notification === "CALENDAR_EVENTS") {
|
||||||
|
@ -314,7 +311,7 @@ Module.register("currentweather",{
|
||||||
* Requests new data from openweather.org.
|
* Requests new data from openweather.org.
|
||||||
* Calls processWeather on succesfull response.
|
* Calls processWeather on succesfull response.
|
||||||
*/
|
*/
|
||||||
updateWeather: function() {
|
updateWeather: function () {
|
||||||
if (this.config.appid === "") {
|
if (this.config.appid === "") {
|
||||||
Log.error("CurrentWeather: APPID not set!");
|
Log.error("CurrentWeather: APPID not set!");
|
||||||
return;
|
return;
|
||||||
|
@ -326,7 +323,7 @@ Module.register("currentweather",{
|
||||||
|
|
||||||
var weatherRequest = new XMLHttpRequest();
|
var weatherRequest = new XMLHttpRequest();
|
||||||
weatherRequest.open("GET", url, true);
|
weatherRequest.open("GET", url, true);
|
||||||
weatherRequest.onreadystatechange = function() {
|
weatherRequest.onreadystatechange = function () {
|
||||||
if (this.readyState === 4) {
|
if (this.readyState === 4) {
|
||||||
if (this.status === 200) {
|
if (this.status === 200) {
|
||||||
self.processWeather(JSON.parse(this.response));
|
self.processWeather(JSON.parse(this.response));
|
||||||
|
@ -340,7 +337,7 @@ Module.register("currentweather",{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
self.scheduleUpdate((self.loaded) ? -1 : self.config.retryDelay);
|
self.scheduleUpdate(self.loaded ? -1 : self.config.retryDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -352,18 +349,18 @@ Module.register("currentweather",{
|
||||||
*
|
*
|
||||||
* return String - URL params.
|
* return String - URL params.
|
||||||
*/
|
*/
|
||||||
getParams: function() {
|
getParams: function () {
|
||||||
var params = "?";
|
var params = "?";
|
||||||
if(this.config.locationID) {
|
if (this.config.locationID) {
|
||||||
params += "id=" + this.config.locationID;
|
params += "id=" + this.config.locationID;
|
||||||
} else if(this.config.location) {
|
} else if (this.config.location) {
|
||||||
params += "q=" + this.config.location;
|
params += "q=" + this.config.location;
|
||||||
} else if (this.firstEvent && this.firstEvent.geo) {
|
} else if (this.firstEvent && this.firstEvent.geo) {
|
||||||
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
||||||
} else if (this.firstEvent && this.firstEvent.location) {
|
} else if (this.firstEvent && this.firstEvent.location) {
|
||||||
params += "q=" + this.firstEvent.location;
|
params += "q=" + this.firstEvent.location;
|
||||||
} else {
|
} else {
|
||||||
this.hide(this.config.animationSpeed, {lockString:this.identifier});
|
this.hide(this.config.animationSpeed, { lockString: this.identifier });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,8 +376,7 @@ Module.register("currentweather",{
|
||||||
*
|
*
|
||||||
* argument data object - Weather information received form openweather.org.
|
* argument data object - Weather information received form openweather.org.
|
||||||
*/
|
*/
|
||||||
processWeather: function(data) {
|
processWeather: function (data) {
|
||||||
|
|
||||||
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -392,7 +388,7 @@ Module.register("currentweather",{
|
||||||
this.fetchedLocationName = data.name;
|
this.fetchedLocationName = data.name;
|
||||||
this.feelsLike = 0;
|
this.feelsLike = 0;
|
||||||
|
|
||||||
if (this.config.useBeaufort){
|
if (this.config.useBeaufort) {
|
||||||
this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
|
this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
|
||||||
} else if (this.config.useKMPHwind) {
|
} else if (this.config.useKMPHwind) {
|
||||||
this.windSpeed = parseFloat((data.wind.speed * 60 * 60) / 1000).toFixed(0);
|
this.windSpeed = parseFloat((data.wind.speed * 60 * 60) / 1000).toFixed(0);
|
||||||
|
@ -404,45 +400,54 @@ Module.register("currentweather",{
|
||||||
var windInMph = parseFloat(data.wind.speed * 2.23694);
|
var windInMph = parseFloat(data.wind.speed * 2.23694);
|
||||||
|
|
||||||
var tempInF = 0;
|
var tempInF = 0;
|
||||||
switch (this.config.units){
|
switch (this.config.units) {
|
||||||
case "metric": tempInF = 1.8 * this.temperature + 32;
|
case "metric":
|
||||||
|
tempInF = 1.8 * this.temperature + 32;
|
||||||
break;
|
break;
|
||||||
case "imperial": tempInF = this.temperature;
|
case "imperial":
|
||||||
|
tempInF = this.temperature;
|
||||||
break;
|
break;
|
||||||
case "default":
|
case "default":
|
||||||
tempInF = 1.8 * (this.temperature - 273.15) + 32;
|
tempInF = 1.8 * (this.temperature - 273.15) + 32;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windInMph > 3 && tempInF < 50){
|
if (windInMph > 3 && tempInF < 50) {
|
||||||
// windchill
|
// 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 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);
|
var windChillInC = (windChillInF - 32) * (5 / 9);
|
||||||
// this.feelsLike = windChillInC.toFixed(0);
|
// this.feelsLike = windChillInC.toFixed(0);
|
||||||
|
|
||||||
switch (this.config.units){
|
switch (this.config.units) {
|
||||||
case "metric": this.feelsLike = windChillInC.toFixed(0);
|
case "metric":
|
||||||
|
this.feelsLike = windChillInC.toFixed(0);
|
||||||
break;
|
break;
|
||||||
case "imperial": this.feelsLike = windChillInF.toFixed(0);
|
case "imperial":
|
||||||
|
this.feelsLike = windChillInF.toFixed(0);
|
||||||
break;
|
break;
|
||||||
case "default":
|
case "default":
|
||||||
this.feelsLike = (windChillInC + 273.15).toFixed(0);
|
this.feelsLike = (windChillInC + 273.15).toFixed(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (tempInF > 80 && this.humidity > 40) {
|
||||||
} else if (tempInF > 80 && this.humidity > 40){
|
|
||||||
// heat index
|
// heat index
|
||||||
var Hindex = -42.379 + 2.04901523*tempInF + 10.14333127*this.humidity
|
var Hindex =
|
||||||
- 0.22475541*tempInF*this.humidity - 6.83783*Math.pow(10,-3)*tempInF*tempInF
|
-42.379 +
|
||||||
- 5.481717*Math.pow(10,-2)*this.humidity*this.humidity
|
2.04901523 * tempInF +
|
||||||
+ 1.22874*Math.pow(10,-3)*tempInF*tempInF*this.humidity
|
10.14333127 * this.humidity -
|
||||||
+ 8.5282*Math.pow(10,-4)*tempInF*this.humidity*this.humidity
|
0.22475541 * tempInF * this.humidity -
|
||||||
- 1.99*Math.pow(10,-6)*tempInF*tempInF*this.humidity*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){
|
switch (this.config.units) {
|
||||||
case "metric": this.feelsLike = parseFloat((Hindex - 32) / 1.8).toFixed(0);
|
case "metric":
|
||||||
|
this.feelsLike = parseFloat((Hindex - 32) / 1.8).toFixed(0);
|
||||||
break;
|
break;
|
||||||
case "imperial": this.feelsLike = Hindex.toFixed(0);
|
case "imperial":
|
||||||
|
this.feelsLike = Hindex.toFixed(0);
|
||||||
break;
|
break;
|
||||||
case "default":
|
case "default":
|
||||||
var tc = parseFloat((Hindex - 32) / 1.8) + 273.15;
|
var tc = parseFloat((Hindex - 32) / 1.8) + 273.15;
|
||||||
|
@ -464,7 +469,7 @@ Module.register("currentweather",{
|
||||||
// The moment().format('h') method has a bug on the Raspberry Pi.
|
// The moment().format('h') method has a bug on the Raspberry Pi.
|
||||||
// So we need to generate the timestring manually.
|
// So we need to generate the timestring manually.
|
||||||
// See issue: https://github.com/MichMich/MagicMirror/issues/181
|
// See issue: https://github.com/MichMich/MagicMirror/issues/181
|
||||||
var sunriseSunsetDateObject = (sunrise < now && sunset > now) ? sunset : sunrise;
|
var sunriseSunsetDateObject = sunrise < now && sunset > now ? sunset : sunrise;
|
||||||
var timeString = moment(sunriseSunsetDateObject).format("HH:mm");
|
var timeString = moment(sunriseSunsetDateObject).format("HH:mm");
|
||||||
if (this.config.timeFormat !== 24) {
|
if (this.config.timeFormat !== 24) {
|
||||||
//var hours = sunriseSunsetDateObject.getHours() % 12 || 12;
|
//var hours = sunriseSunsetDateObject.getHours() % 12 || 12;
|
||||||
|
@ -483,12 +488,12 @@ Module.register("currentweather",{
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sunriseSunsetTime = timeString;
|
this.sunriseSunsetTime = timeString;
|
||||||
this.sunriseSunsetIcon = (sunrise < now && sunset > now) ? "wi-sunset" : "wi-sunrise";
|
this.sunriseSunsetIcon = sunrise < now && sunset > now ? "wi-sunset" : "wi-sunrise";
|
||||||
|
|
||||||
this.show(this.config.animationSpeed, {lockString:this.identifier});
|
this.show(this.config.animationSpeed, { lockString: this.identifier });
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
this.updateDom(this.config.animationSpeed);
|
this.updateDom(this.config.animationSpeed);
|
||||||
this.sendNotification("CURRENTWEATHER_DATA", {data: data});
|
this.sendNotification("CURRENTWEATHER_DATA", { data: data });
|
||||||
},
|
},
|
||||||
|
|
||||||
/* scheduleUpdate()
|
/* scheduleUpdate()
|
||||||
|
@ -496,14 +501,14 @@ Module.register("currentweather",{
|
||||||
*
|
*
|
||||||
* argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
|
* argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
|
||||||
*/
|
*/
|
||||||
scheduleUpdate: function(delay) {
|
scheduleUpdate: function (delay) {
|
||||||
var nextLoad = this.config.updateInterval;
|
var nextLoad = this.config.updateInterval;
|
||||||
if (typeof delay !== "undefined" && delay >= 0) {
|
if (typeof delay !== "undefined" && delay >= 0) {
|
||||||
nextLoad = delay;
|
nextLoad = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
self.updateWeather();
|
self.updateWeather();
|
||||||
}, nextLoad);
|
}, nextLoad);
|
||||||
},
|
},
|
||||||
|
@ -519,8 +524,8 @@ Module.register("currentweather",{
|
||||||
*
|
*
|
||||||
* return number - Windspeed in beaufort.
|
* return number - Windspeed in beaufort.
|
||||||
*/
|
*/
|
||||||
ms2Beaufort: function(ms) {
|
ms2Beaufort: function (ms) {
|
||||||
var kmh = ms * 60 * 60 / 1000;
|
var kmh = (ms * 60 * 60) / 1000;
|
||||||
var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
||||||
for (var beaufort in speeds) {
|
for (var beaufort in speeds) {
|
||||||
var speed = speeds[beaufort];
|
var speed = speeds[beaufort];
|
||||||
|
@ -531,8 +536,8 @@ Module.register("currentweather",{
|
||||||
return 12;
|
return 12;
|
||||||
},
|
},
|
||||||
|
|
||||||
deg2Cardinal: function(deg) {
|
deg2Cardinal: function (deg) {
|
||||||
if (deg>11.25 && deg<=33.75){
|
if (deg > 11.25 && deg <= 33.75) {
|
||||||
return "NNE";
|
return "NNE";
|
||||||
} else if (deg > 33.75 && deg <= 56.25) {
|
} else if (deg > 33.75 && deg <= 56.25) {
|
||||||
return "NE";
|
return "NE";
|
||||||
|
@ -574,9 +579,8 @@ Module.register("currentweather",{
|
||||||
*
|
*
|
||||||
* return string - Rounded Temperature.
|
* return string - Rounded Temperature.
|
||||||
*/
|
*/
|
||||||
roundValue: function(temperature) {
|
roundValue: function (temperature) {
|
||||||
var decimals = this.config.roundTemp ? 0 : 1;
|
var decimals = this.config.roundTemp ? 0 : 1;
|
||||||
return parseFloat(temperature).toFixed(decimals);
|
return parseFloat(temperature).toFixed(decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,18 +7,9 @@
|
||||||
|
|
||||||
// Modules listed below can be loaded without the 'default/' prefix. Omitting the default folder name.
|
// Modules listed below can be loaded without the 'default/' prefix. Omitting the default folder name.
|
||||||
|
|
||||||
var defaultModules = [
|
var defaultModules = ["alert", "calendar", "clock", "compliments", "currentweather", "helloworld", "newsfeed", "weatherforecast", "updatenotification", "weather"];
|
||||||
"alert",
|
|
||||||
"calendar",
|
|
||||||
"clock",
|
|
||||||
"compliments",
|
|
||||||
"currentweather",
|
|
||||||
"helloworld",
|
|
||||||
"newsfeed",
|
|
||||||
"weatherforecast",
|
|
||||||
"updatenotification",
|
|
||||||
"weather"
|
|
||||||
];
|
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = defaultModules;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = defaultModules;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Hello World
|
# Module: Hello World
|
||||||
|
|
||||||
The `helloworld` module is one of the default modules of the MagicMirror. It is a simple way to display a static text on the mirror.
|
The `helloworld` module is one of the default modules of the MagicMirror. It is a simple way to display a static text on the mirror.
|
||||||
|
|
||||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/helloworld.html).
|
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/helloworld.html).
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("helloworld",{
|
Module.register("helloworld", {
|
||||||
|
|
||||||
// Default module config.
|
// Default module config.
|
||||||
defaults: {
|
defaults: {
|
||||||
text: "Hello World!"
|
text: "Hello World!"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Module: News Feed
|
# 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. Scrolling through news headlines happens time-based (````updateInterval````), but can also be controlled by sending news feed specific notifications to the module.
|
The `newsfeed` module is one of the default modules of the MagicMirror.
|
||||||
|
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.
|
||||||
|
|
||||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/newsfeed.html).
|
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/newsfeed.html).
|
||||||
|
|
|
@ -17,7 +17,7 @@ var iconv = require("iconv-lite");
|
||||||
* attribute logFeedWarnings boolean - Log warnings when there is an error parsing a news article.
|
* attribute logFeedWarnings boolean - Log warnings when there is an error parsing a news article.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
var Fetcher = function (url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (reloadInterval < 1000) {
|
if (reloadInterval < 1000) {
|
||||||
reloadInterval = 1000;
|
reloadInterval = 1000;
|
||||||
|
@ -26,8 +26,8 @@ var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
var reloadTimer = null;
|
var reloadTimer = null;
|
||||||
var items = [];
|
var items = [];
|
||||||
|
|
||||||
var fetchFailedCallback = function() {};
|
var fetchFailedCallback = function () {};
|
||||||
var itemsReceivedCallback = function() {};
|
var itemsReceivedCallback = function () {};
|
||||||
|
|
||||||
/* private methods */
|
/* private methods */
|
||||||
|
|
||||||
|
@ -35,32 +35,29 @@ var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
* Request the new items.
|
* Request the new items.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fetchNews = function() {
|
var fetchNews = function () {
|
||||||
clearTimeout(reloadTimer);
|
clearTimeout(reloadTimer);
|
||||||
reloadTimer = null;
|
reloadTimer = null;
|
||||||
items = [];
|
items = [];
|
||||||
|
|
||||||
var parser = new FeedMe();
|
var parser = new FeedMe();
|
||||||
|
|
||||||
parser.on("item", function(item) {
|
parser.on("item", function (item) {
|
||||||
|
|
||||||
var title = item.title;
|
var title = item.title;
|
||||||
var description = item.description || item.summary || item.content || "";
|
var description = item.description || item.summary || item.content || "";
|
||||||
var pubdate = item.pubdate || item.published || item.updated || item["dc:date"];
|
var pubdate = item.pubdate || item.published || item.updated || item["dc:date"];
|
||||||
var url = item.url || item.link || "";
|
var url = item.url || item.link || "";
|
||||||
|
|
||||||
if (title && pubdate) {
|
if (title && pubdate) {
|
||||||
|
var regex = /(<([^>]+)>)/gi;
|
||||||
var regex = /(<([^>]+)>)/ig;
|
|
||||||
description = description.toString().replace(regex, "");
|
description = description.toString().replace(regex, "");
|
||||||
|
|
||||||
items.push({
|
items.push({
|
||||||
title: title,
|
title: title,
|
||||||
description: description,
|
description: description,
|
||||||
pubdate: pubdate,
|
pubdate: pubdate,
|
||||||
url: url,
|
url: url
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (logFeedWarnings) {
|
} else if (logFeedWarnings) {
|
||||||
console.log("Can't parse feed item:");
|
console.log("Can't parse feed item:");
|
||||||
console.log(item);
|
console.log(item);
|
||||||
|
@ -70,39 +67,37 @@ var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.on("end", function() {
|
parser.on("end", function () {
|
||||||
//console.log("end parsing - " + url);
|
//console.log("end parsing - " + url);
|
||||||
self.broadcastItems();
|
self.broadcastItems();
|
||||||
scheduleTimer();
|
scheduleTimer();
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.on("error", function(error) {
|
parser.on("error", function (error) {
|
||||||
fetchFailedCallback(self, error);
|
fetchFailedCallback(self, error);
|
||||||
scheduleTimer();
|
scheduleTimer();
|
||||||
});
|
});
|
||||||
|
|
||||||
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
||||||
var headers = {"User-Agent": "Mozilla/5.0 (Node.js "+ nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)",
|
var 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" };
|
||||||
"Cache-Control": "max-age=0, no-cache, no-store, must-revalidate",
|
|
||||||
"Pragma": "no-cache"};
|
|
||||||
|
|
||||||
request({uri: url, encoding: null, headers: headers})
|
request({ uri: url, encoding: null, headers: headers })
|
||||||
.on("error", function(error) {
|
.on("error", function (error) {
|
||||||
fetchFailedCallback(self, error);
|
fetchFailedCallback(self, error);
|
||||||
scheduleTimer();
|
scheduleTimer();
|
||||||
})
|
})
|
||||||
.pipe(iconv.decodeStream(encoding)).pipe(parser);
|
.pipe(iconv.decodeStream(encoding))
|
||||||
|
.pipe(parser);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* scheduleTimer()
|
/* scheduleTimer()
|
||||||
* Schedule the timer for the next update.
|
* Schedule the timer for the next update.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var scheduleTimer = function() {
|
var scheduleTimer = function () {
|
||||||
//console.log('Schedule update timer.');
|
//console.log('Schedule update timer.');
|
||||||
clearTimeout(reloadTimer);
|
clearTimeout(reloadTimer);
|
||||||
reloadTimer = setTimeout(function() {
|
reloadTimer = setTimeout(function () {
|
||||||
fetchNews();
|
fetchNews();
|
||||||
}, reloadInterval);
|
}, reloadInterval);
|
||||||
};
|
};
|
||||||
|
@ -114,7 +109,7 @@ var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
*
|
*
|
||||||
* attribute interval number - Interval for the update in milliseconds.
|
* attribute interval number - Interval for the update in milliseconds.
|
||||||
*/
|
*/
|
||||||
this.setReloadInterval = function(interval) {
|
this.setReloadInterval = function (interval) {
|
||||||
if (interval > 1000 && interval < reloadInterval) {
|
if (interval > 1000 && interval < reloadInterval) {
|
||||||
reloadInterval = interval;
|
reloadInterval = interval;
|
||||||
}
|
}
|
||||||
|
@ -123,14 +118,14 @@ var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
/* startFetch()
|
/* startFetch()
|
||||||
* Initiate fetchNews();
|
* Initiate fetchNews();
|
||||||
*/
|
*/
|
||||||
this.startFetch = function() {
|
this.startFetch = function () {
|
||||||
fetchNews();
|
fetchNews();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* broadcastItems()
|
/* broadcastItems()
|
||||||
* Broadcast the existing items.
|
* Broadcast the existing items.
|
||||||
*/
|
*/
|
||||||
this.broadcastItems = function() {
|
this.broadcastItems = function () {
|
||||||
if (items.length <= 0) {
|
if (items.length <= 0) {
|
||||||
//console.log('No items to broadcast yet.');
|
//console.log('No items to broadcast yet.');
|
||||||
return;
|
return;
|
||||||
|
@ -139,19 +134,19 @@ var Fetcher = function(url, reloadInterval, encoding, logFeedWarnings) {
|
||||||
itemsReceivedCallback(self);
|
itemsReceivedCallback(self);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onReceive = function(callback) {
|
this.onReceive = function (callback) {
|
||||||
itemsReceivedCallback = callback;
|
itemsReceivedCallback = callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onError = function(callback) {
|
this.onError = function (callback) {
|
||||||
fetchFailedCallback = callback;
|
fetchFailedCallback = callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.url = function() {
|
this.url = function () {
|
||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.items = function() {
|
this.items = function () {
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("newsfeed",{
|
Module.register("newsfeed", {
|
||||||
|
|
||||||
// Default module config.
|
// Default module config.
|
||||||
defaults: {
|
defaults: {
|
||||||
feeds: [
|
feeds: [
|
||||||
|
@ -41,12 +40,12 @@ Module.register("newsfeed",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getScripts: function() {
|
getScripts: function () {
|
||||||
return ["moment.js"];
|
return ["moment.js"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required translations.
|
// Define required translations.
|
||||||
getTranslations: function() {
|
getTranslations: function () {
|
||||||
// The translations for the default modules are defined in the core translation files.
|
// The translations for the default modules are defined in the core translation files.
|
||||||
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
||||||
// If you're trying to build your own module including translations, check out the documentation.
|
// If you're trying to build your own module including translations, check out the documentation.
|
||||||
|
@ -54,7 +53,7 @@ Module.register("newsfeed",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define start sequence.
|
// Define start sequence.
|
||||||
start: function() {
|
start: function () {
|
||||||
Log.info("Starting module: " + this.name);
|
Log.info("Starting module: " + this.name);
|
||||||
|
|
||||||
// Set locale.
|
// Set locale.
|
||||||
|
@ -71,7 +70,7 @@ Module.register("newsfeed",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override socket notification handler.
|
// Override socket notification handler.
|
||||||
socketNotificationReceived: function(notification, payload) {
|
socketNotificationReceived: function (notification, payload) {
|
||||||
if (notification === "NEWS_ITEMS") {
|
if (notification === "NEWS_ITEMS") {
|
||||||
this.generateFeed(payload);
|
this.generateFeed(payload);
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ Module.register("newsfeed",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function() {
|
getDom: function () {
|
||||||
var wrapper = document.createElement("div");
|
var wrapper = document.createElement("div");
|
||||||
|
|
||||||
if (this.config.feedUrl) {
|
if (this.config.feedUrl) {
|
||||||
|
@ -98,7 +97,6 @@ Module.register("newsfeed",{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.newsItems.length > 0) {
|
if (this.newsItems.length > 0) {
|
||||||
|
|
||||||
// this.config.showFullArticle is a run-time configuration, triggered by optional notifications
|
// this.config.showFullArticle is a run-time configuration, triggered by optional notifications
|
||||||
if (!this.config.showFullArticle && (this.config.showSourceTitle || this.config.showPublishDate)) {
|
if (!this.config.showFullArticle && (this.config.showSourceTitle || this.config.showPublishDate)) {
|
||||||
var sourceAndTimestamp = document.createElement("div");
|
var sourceAndTimestamp = document.createElement("div");
|
||||||
|
@ -113,7 +111,7 @@ Module.register("newsfeed",{
|
||||||
if (this.config.showPublishDate) {
|
if (this.config.showPublishDate) {
|
||||||
sourceAndTimestamp.innerHTML += moment(new Date(this.newsItems[this.activeItem].pubdate)).fromNow();
|
sourceAndTimestamp.innerHTML += moment(new Date(this.newsItems[this.activeItem].pubdate)).fromNow();
|
||||||
}
|
}
|
||||||
if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "" || this.config.showPublishDate) {
|
if ((this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "") || this.config.showPublishDate) {
|
||||||
sourceAndTimestamp.innerHTML += ":";
|
sourceAndTimestamp.innerHTML += ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,47 +121,42 @@ Module.register("newsfeed",{
|
||||||
//Remove selected tags from the beginning of rss feed items (title or description)
|
//Remove selected tags from the beginning of rss feed items (title or description)
|
||||||
|
|
||||||
if (this.config.removeStartTags === "title" || this.config.removeStartTags === "both") {
|
if (this.config.removeStartTags === "title" || this.config.removeStartTags === "both") {
|
||||||
|
for (let f = 0; f < this.config.startTags.length; f++) {
|
||||||
for (let f=0; f<this.config.startTags.length;f++) {
|
if (this.newsItems[this.activeItem].title.slice(0, this.config.startTags[f].length) === this.config.startTags[f]) {
|
||||||
if (this.newsItems[this.activeItem].title.slice(0,this.config.startTags[f].length) === this.config.startTags[f]) {
|
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].title.slice(this.config.startTags[f].length, this.newsItems[this.activeItem].title.length);
|
||||||
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].title.slice(this.config.startTags[f].length,this.newsItems[this.activeItem].title.length);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.removeStartTags === "description" || this.config.removeStartTags === "both") {
|
if (this.config.removeStartTags === "description" || this.config.removeStartTags === "both") {
|
||||||
|
|
||||||
if (this.isShowingDescription) {
|
if (this.isShowingDescription) {
|
||||||
for (let f=0; f<this.config.startTags.length;f++) {
|
for (let f = 0; f < this.config.startTags.length; f++) {
|
||||||
if (this.newsItems[this.activeItem].description.slice(0,this.config.startTags[f].length) === this.config.startTags[f]) {
|
if (this.newsItems[this.activeItem].description.slice(0, this.config.startTags[f].length) === this.config.startTags[f]) {
|
||||||
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(this.config.startTags[f].length,this.newsItems[this.activeItem].description.length);
|
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(this.config.startTags[f].length, this.newsItems[this.activeItem].description.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove selected tags from the end of rss feed items (title or description)
|
//Remove selected tags from the end of rss feed items (title or description)
|
||||||
|
|
||||||
if (this.config.removeEndTags) {
|
if (this.config.removeEndTags) {
|
||||||
for (let f=0; f<this.config.endTags.length;f++) {
|
for (let f = 0; f < this.config.endTags.length; f++) {
|
||||||
if (this.newsItems[this.activeItem].title.slice(-this.config.endTags[f].length)===this.config.endTags[f]) {
|
if (this.newsItems[this.activeItem].title.slice(-this.config.endTags[f].length) === this.config.endTags[f]) {
|
||||||
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].title.slice(0,-this.config.endTags[f].length);
|
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].title.slice(0, -this.config.endTags[f].length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isShowingDescription) {
|
if (this.isShowingDescription) {
|
||||||
for (let f=0; f<this.config.endTags.length;f++) {
|
for (let f = 0; f < this.config.endTags.length; f++) {
|
||||||
if (this.newsItems[this.activeItem].description.slice(-this.config.endTags[f].length)===this.config.endTags[f]) {
|
if (this.newsItems[this.activeItem].description.slice(-this.config.endTags[f].length) === this.config.endTags[f]) {
|
||||||
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(0,-this.config.endTags[f].length);
|
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(0, -this.config.endTags[f].length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (!this.config.showFullArticle) {
|
||||||
|
|
||||||
if(!this.config.showFullArticle){
|
|
||||||
var title = document.createElement("div");
|
var title = document.createElement("div");
|
||||||
title.className = "newsfeed-title bright medium light" + (!this.config.wrapTitle ? " no-wrap" : "");
|
title.className = "newsfeed-title bright medium light" + (!this.config.wrapTitle ? " no-wrap" : "");
|
||||||
title.innerHTML = this.newsItems[this.activeItem].title;
|
title.innerHTML = this.newsItems[this.activeItem].title;
|
||||||
|
@ -174,7 +167,7 @@ Module.register("newsfeed",{
|
||||||
var description = document.createElement("div");
|
var description = document.createElement("div");
|
||||||
description.className = "newsfeed-desc small light" + (!this.config.wrapDescription ? " no-wrap" : "");
|
description.className = "newsfeed-desc small light" + (!this.config.wrapDescription ? " no-wrap" : "");
|
||||||
var txtDesc = 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);
|
description.innerHTML = this.config.truncDescription ? (txtDesc.length > this.config.lengthDescription ? txtDesc.substring(0, this.config.lengthDescription) + "..." : txtDesc) : txtDesc;
|
||||||
wrapper.appendChild(description);
|
wrapper.appendChild(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +189,6 @@ Module.register("newsfeed",{
|
||||||
if (this.config.hideLoading) {
|
if (this.config.hideLoading) {
|
||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (this.config.hideLoading) {
|
if (this.config.hideLoading) {
|
||||||
this.hide();
|
this.hide();
|
||||||
|
@ -209,14 +201,14 @@ Module.register("newsfeed",{
|
||||||
return wrapper;
|
return wrapper;
|
||||||
},
|
},
|
||||||
|
|
||||||
getActiveItemURL: function() {
|
getActiveItemURL: function () {
|
||||||
return typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href;
|
return typeof this.newsItems[this.activeItem].url === "string" ? this.newsItems[this.activeItem].url : this.newsItems[this.activeItem].url.href;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* registerFeeds()
|
/* registerFeeds()
|
||||||
* registers the feeds to be used by the backend.
|
* registers the feeds to be used by the backend.
|
||||||
*/
|
*/
|
||||||
registerFeeds: function() {
|
registerFeeds: function () {
|
||||||
for (var f in this.config.feeds) {
|
for (var f in this.config.feeds) {
|
||||||
var feed = this.config.feeds[f];
|
var feed = this.config.feeds[f];
|
||||||
this.sendSocketNotification("ADD_FEED", {
|
this.sendSocketNotification("ADD_FEED", {
|
||||||
|
@ -231,7 +223,7 @@ Module.register("newsfeed",{
|
||||||
*
|
*
|
||||||
* attribute feeds object - An object with feeds returned by the node helper.
|
* attribute feeds object - An object with feeds returned by the node helper.
|
||||||
*/
|
*/
|
||||||
generateFeed: function(feeds) {
|
generateFeed: function (feeds) {
|
||||||
var newsItems = [];
|
var newsItems = [];
|
||||||
for (var feed in feeds) {
|
for (var feed in feeds) {
|
||||||
var feedItems = feeds[feed];
|
var feedItems = feeds[feed];
|
||||||
|
@ -239,24 +231,24 @@ Module.register("newsfeed",{
|
||||||
for (var i in feedItems) {
|
for (var i in feedItems) {
|
||||||
var item = feedItems[i];
|
var item = feedItems[i];
|
||||||
item.sourceTitle = this.titleForFeed(feed);
|
item.sourceTitle = this.titleForFeed(feed);
|
||||||
if (!(this.config.ignoreOldItems && ((Date.now() - new Date(item.pubdate)) > this.config.ignoreOlderThan))) {
|
if (!(this.config.ignoreOldItems && Date.now() - new Date(item.pubdate) > this.config.ignoreOlderThan)) {
|
||||||
newsItems.push(item);
|
newsItems.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newsItems.sort(function(a,b) {
|
newsItems.sort(function (a, b) {
|
||||||
var dateA = new Date(a.pubdate);
|
var dateA = new Date(a.pubdate);
|
||||||
var dateB = new Date(b.pubdate);
|
var dateB = new Date(b.pubdate);
|
||||||
return dateB - dateA;
|
return dateB - dateA;
|
||||||
});
|
});
|
||||||
if(this.config.maxNewsItems > 0) {
|
if (this.config.maxNewsItems > 0) {
|
||||||
newsItems = newsItems.slice(0, this.config.maxNewsItems);
|
newsItems = newsItems.slice(0, this.config.maxNewsItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.config.prohibitedWords.length > 0) {
|
if (this.config.prohibitedWords.length > 0) {
|
||||||
newsItems = newsItems.filter(function(value){
|
newsItems = newsItems.filter(function (value) {
|
||||||
for (var i=0; i < this.config.prohibitedWords.length; i++) {
|
for (var i = 0; i < this.config.prohibitedWords.length; i++) {
|
||||||
if (value["title"].toLowerCase().indexOf(this.config.prohibitedWords[i].toLowerCase()) > -1) {
|
if (value["title"].toLowerCase().indexOf(this.config.prohibitedWords[i].toLowerCase()) > -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -267,8 +259,8 @@ Module.register("newsfeed",{
|
||||||
|
|
||||||
// get updated news items and broadcast them
|
// get updated news items and broadcast them
|
||||||
var updatedItems = [];
|
var updatedItems = [];
|
||||||
newsItems.forEach(value => {
|
newsItems.forEach((value) => {
|
||||||
if (this.newsItems.findIndex(value1 => value1 === value) === -1) {
|
if (this.newsItems.findIndex((value1) => value1 === value) === -1) {
|
||||||
// Add item to updated items list
|
// Add item to updated items list
|
||||||
updatedItems.push(value);
|
updatedItems.push(value);
|
||||||
}
|
}
|
||||||
|
@ -276,7 +268,7 @@ Module.register("newsfeed",{
|
||||||
|
|
||||||
// check if updated items exist, if so and if we should broadcast these updates, then lets do so
|
// check if updated items exist, if so and if we should broadcast these updates, then lets do so
|
||||||
if (this.config.broadcastNewsUpdates && updatedItems.length > 0) {
|
if (this.config.broadcastNewsUpdates && updatedItems.length > 0) {
|
||||||
this.sendNotification("NEWS_FEED_UPDATE", {items: updatedItems});
|
this.sendNotification("NEWS_FEED_UPDATE", { items: updatedItems });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newsItems = newsItems;
|
this.newsItems = newsItems;
|
||||||
|
@ -289,7 +281,7 @@ Module.register("newsfeed",{
|
||||||
*
|
*
|
||||||
* returns bool
|
* returns bool
|
||||||
*/
|
*/
|
||||||
subscribedToFeed: function(feedUrl) {
|
subscribedToFeed: function (feedUrl) {
|
||||||
for (var f in this.config.feeds) {
|
for (var f in this.config.feeds) {
|
||||||
var feed = this.config.feeds[f];
|
var feed = this.config.feeds[f];
|
||||||
if (feed.url === feedUrl) {
|
if (feed.url === feedUrl) {
|
||||||
|
@ -306,7 +298,7 @@ Module.register("newsfeed",{
|
||||||
*
|
*
|
||||||
* returns string
|
* returns string
|
||||||
*/
|
*/
|
||||||
titleForFeed: function(feedUrl) {
|
titleForFeed: function (feedUrl) {
|
||||||
for (var f in this.config.feeds) {
|
for (var f in this.config.feeds) {
|
||||||
var feed = this.config.feeds[f];
|
var feed = this.config.feeds[f];
|
||||||
if (feed.url === feedUrl) {
|
if (feed.url === feedUrl) {
|
||||||
|
@ -319,23 +311,23 @@ Module.register("newsfeed",{
|
||||||
/* scheduleUpdateInterval()
|
/* scheduleUpdateInterval()
|
||||||
* Schedule visual update.
|
* Schedule visual update.
|
||||||
*/
|
*/
|
||||||
scheduleUpdateInterval: function() {
|
scheduleUpdateInterval: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.updateDom(self.config.animationSpeed);
|
self.updateDom(self.config.animationSpeed);
|
||||||
|
|
||||||
// Broadcast NewsFeed if needed
|
// Broadcast NewsFeed if needed
|
||||||
if (self.config.broadcastNewsFeeds) {
|
if (self.config.broadcastNewsFeeds) {
|
||||||
self.sendNotification("NEWS_FEED", {items: self.newsItems});
|
self.sendNotification("NEWS_FEED", { items: self.newsItems });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.timer = setInterval(function() {
|
this.timer = setInterval(function () {
|
||||||
self.activeItem++;
|
self.activeItem++;
|
||||||
self.updateDom(self.config.animationSpeed);
|
self.updateDom(self.config.animationSpeed);
|
||||||
|
|
||||||
// Broadcast NewsFeed if needed
|
// Broadcast NewsFeed if needed
|
||||||
if (self.config.broadcastNewsFeeds) {
|
if (self.config.broadcastNewsFeeds) {
|
||||||
self.sendNotification("NEWS_FEED", {items: self.newsItems});
|
self.sendNotification("NEWS_FEED", { items: self.newsItems });
|
||||||
}
|
}
|
||||||
}, this.config.updateInterval);
|
}, this.config.updateInterval);
|
||||||
},
|
},
|
||||||
|
@ -347,25 +339,25 @@ Module.register("newsfeed",{
|
||||||
*
|
*
|
||||||
* return string - Capitalized output string.
|
* return string - Capitalized output string.
|
||||||
*/
|
*/
|
||||||
capitalizeFirstLetter: function(string) {
|
capitalizeFirstLetter: function (string) {
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
},
|
},
|
||||||
|
|
||||||
resetDescrOrFullArticleAndTimer: function() {
|
resetDescrOrFullArticleAndTimer: function () {
|
||||||
this.isShowingDescription = this.config.showDescription;
|
this.isShowingDescription = this.config.showDescription;
|
||||||
this.config.showFullArticle = false;
|
this.config.showFullArticle = false;
|
||||||
this.scrollPosition = 0;
|
this.scrollPosition = 0;
|
||||||
// reset bottom bar alignment
|
// reset bottom bar alignment
|
||||||
document.getElementsByClassName("region bottom bar")[0].style.bottom = "0";
|
document.getElementsByClassName("region bottom bar")[0].style.bottom = "0";
|
||||||
document.getElementsByClassName("region bottom bar")[0].style.top = "inherit";
|
document.getElementsByClassName("region bottom bar")[0].style.top = "inherit";
|
||||||
if(!this.timer){
|
if (!this.timer) {
|
||||||
this.scheduleUpdateInterval();
|
this.scheduleUpdateInterval();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
notificationReceived: function(notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
var before = this.activeItem;
|
var before = this.activeItem;
|
||||||
if(notification === "ARTICLE_NEXT"){
|
if (notification === "ARTICLE_NEXT") {
|
||||||
this.activeItem++;
|
this.activeItem++;
|
||||||
if (this.activeItem >= this.newsItems.length) {
|
if (this.activeItem >= this.newsItems.length) {
|
||||||
this.activeItem = 0;
|
this.activeItem = 0;
|
||||||
|
@ -373,7 +365,7 @@ Module.register("newsfeed",{
|
||||||
this.resetDescrOrFullArticleAndTimer();
|
this.resetDescrOrFullArticleAndTimer();
|
||||||
Log.info(this.name + " - going from article #" + before + " to #" + this.activeItem + " (of " + this.newsItems.length + ")");
|
Log.info(this.name + " - going from article #" + before + " to #" + this.activeItem + " (of " + this.newsItems.length + ")");
|
||||||
this.updateDom(100);
|
this.updateDom(100);
|
||||||
} else if(notification === "ARTICLE_PREVIOUS"){
|
} else if (notification === "ARTICLE_PREVIOUS") {
|
||||||
this.activeItem--;
|
this.activeItem--;
|
||||||
if (this.activeItem < 0) {
|
if (this.activeItem < 0) {
|
||||||
this.activeItem = this.newsItems.length - 1;
|
this.activeItem = this.newsItems.length - 1;
|
||||||
|
@ -383,36 +375,35 @@ Module.register("newsfeed",{
|
||||||
this.updateDom(100);
|
this.updateDom(100);
|
||||||
}
|
}
|
||||||
// if "more details" is received the first time: show article summary, on second time show full article
|
// if "more details" is received the first time: show article summary, on second time show full article
|
||||||
else if(notification === "ARTICLE_MORE_DETAILS"){
|
else if (notification === "ARTICLE_MORE_DETAILS") {
|
||||||
// full article is already showing, so scrolling down
|
// full article is already showing, so scrolling down
|
||||||
if(this.config.showFullArticle === true){
|
if (this.config.showFullArticle === true) {
|
||||||
this.scrollPosition += this.config.scrollLength;
|
this.scrollPosition += this.config.scrollLength;
|
||||||
window.scrollTo(0, this.scrollPosition);
|
window.scrollTo(0, this.scrollPosition);
|
||||||
Log.info(this.name + " - scrolling down");
|
Log.info(this.name + " - scrolling down");
|
||||||
Log.info(this.name + " - ARTICLE_MORE_DETAILS, scroll position: " + this.config.scrollLength);
|
Log.info(this.name + " - ARTICLE_MORE_DETAILS, scroll position: " + this.config.scrollLength);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.showFullArticle();
|
this.showFullArticle();
|
||||||
}
|
}
|
||||||
} else if(notification === "ARTICLE_SCROLL_UP"){
|
} else if (notification === "ARTICLE_SCROLL_UP") {
|
||||||
if(this.config.showFullArticle === true){
|
if (this.config.showFullArticle === true) {
|
||||||
this.scrollPosition -= this.config.scrollLength;
|
this.scrollPosition -= this.config.scrollLength;
|
||||||
window.scrollTo(0, this.scrollPosition);
|
window.scrollTo(0, this.scrollPosition);
|
||||||
Log.info(this.name + " - scrolling up");
|
Log.info(this.name + " - scrolling up");
|
||||||
Log.info(this.name + " - ARTICLE_SCROLL_UP, scroll position: " + this.config.scrollLength);
|
Log.info(this.name + " - ARTICLE_SCROLL_UP, scroll position: " + this.config.scrollLength);
|
||||||
}
|
}
|
||||||
} else if(notification === "ARTICLE_LESS_DETAILS"){
|
} else if (notification === "ARTICLE_LESS_DETAILS") {
|
||||||
this.resetDescrOrFullArticleAndTimer();
|
this.resetDescrOrFullArticleAndTimer();
|
||||||
Log.info(this.name + " - showing only article titles again");
|
Log.info(this.name + " - showing only article titles again");
|
||||||
this.updateDom(100);
|
this.updateDom(100);
|
||||||
} else if (notification === "ARTICLE_TOGGLE_FULL"){
|
} else if (notification === "ARTICLE_TOGGLE_FULL") {
|
||||||
if (this.config.showFullArticle){
|
if (this.config.showFullArticle) {
|
||||||
this.activeItem++;
|
this.activeItem++;
|
||||||
this.resetDescrOrFullArticleAndTimer();
|
this.resetDescrOrFullArticleAndTimer();
|
||||||
} else {
|
} else {
|
||||||
this.showFullArticle();
|
this.showFullArticle();
|
||||||
}
|
}
|
||||||
} else if (notification === "ARTICLE_INFO_REQUEST"){
|
} else if (notification === "ARTICLE_INFO_REQUEST") {
|
||||||
this.sendNotification("ARTICLE_INFO_RESPONSE", {
|
this.sendNotification("ARTICLE_INFO_RESPONSE", {
|
||||||
title: this.newsItems[this.activeItem].title,
|
title: this.newsItems[this.activeItem].title,
|
||||||
source: this.newsItems[this.activeItem].sourceTitle,
|
source: this.newsItems[this.activeItem].sourceTitle,
|
||||||
|
@ -423,11 +414,11 @@ Module.register("newsfeed",{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showFullArticle: function() {
|
showFullArticle: function () {
|
||||||
this.isShowingDescription = !this.isShowingDescription;
|
this.isShowingDescription = !this.isShowingDescription;
|
||||||
this.config.showFullArticle = !this.isShowingDescription;
|
this.config.showFullArticle = !this.isShowingDescription;
|
||||||
// make bottom bar align to top to allow scrolling
|
// make bottom bar align to top to allow scrolling
|
||||||
if(this.config.showFullArticle === true){
|
if (this.config.showFullArticle === true) {
|
||||||
document.getElementsByClassName("region bottom bar")[0].style.bottom = "inherit";
|
document.getElementsByClassName("region bottom bar")[0].style.bottom = "inherit";
|
||||||
document.getElementsByClassName("region bottom bar")[0].style.top = "-90px";
|
document.getElementsByClassName("region bottom bar")[0].style.top = "-90px";
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ var Fetcher = require("./fetcher.js");
|
||||||
|
|
||||||
module.exports = NodeHelper.create({
|
module.exports = NodeHelper.create({
|
||||||
// Subclass start method.
|
// Subclass start method.
|
||||||
start: function() {
|
start: function () {
|
||||||
console.log("Starting module: " + this.name);
|
console.log("Starting module: " + this.name);
|
||||||
this.fetchers = [];
|
this.fetchers = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Subclass socketNotificationReceived received.
|
// Subclass socketNotificationReceived received.
|
||||||
socketNotificationReceived: function(notification, payload) {
|
socketNotificationReceived: function (notification, payload) {
|
||||||
if (notification === "ADD_FEED") {
|
if (notification === "ADD_FEED") {
|
||||||
this.createFetcher(payload.feed, payload.config);
|
this.createFetcher(payload.feed, payload.config);
|
||||||
return;
|
return;
|
||||||
|
@ -31,7 +31,7 @@ module.exports = NodeHelper.create({
|
||||||
* attribute feed object - A feed object.
|
* attribute feed object - A feed object.
|
||||||
* attribute config object - A configuration object containing reload interval in milliseconds.
|
* attribute config object - A configuration object containing reload interval in milliseconds.
|
||||||
*/
|
*/
|
||||||
createFetcher: function(feed, config) {
|
createFetcher: function (feed, config) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var url = feed.url || "";
|
var url = feed.url || "";
|
||||||
|
@ -48,11 +48,11 @@ module.exports = NodeHelper.create({
|
||||||
console.log("Create new news fetcher for url: " + url + " - Interval: " + reloadInterval);
|
console.log("Create new news fetcher for url: " + url + " - Interval: " + reloadInterval);
|
||||||
fetcher = new Fetcher(url, reloadInterval, encoding, config.logFeedWarnings);
|
fetcher = new Fetcher(url, reloadInterval, encoding, config.logFeedWarnings);
|
||||||
|
|
||||||
fetcher.onReceive(function(fetcher) {
|
fetcher.onReceive(function (fetcher) {
|
||||||
self.broadcastFeeds();
|
self.broadcastFeeds();
|
||||||
});
|
});
|
||||||
|
|
||||||
fetcher.onError(function(fetcher, error) {
|
fetcher.onError(function (fetcher, error) {
|
||||||
self.sendSocketNotification("FETCH_ERROR", {
|
self.sendSocketNotification("FETCH_ERROR", {
|
||||||
url: fetcher.url(),
|
url: fetcher.url(),
|
||||||
error: error
|
error: error
|
||||||
|
@ -74,7 +74,7 @@ module.exports = NodeHelper.create({
|
||||||
* Creates an object with all feed items of the different registered feeds,
|
* Creates an object with all feed items of the different registered feeds,
|
||||||
* and broadcasts these using sendSocketNotification.
|
* and broadcasts these using sendSocketNotification.
|
||||||
*/
|
*/
|
||||||
broadcastFeeds: function() {
|
broadcastFeeds: function () {
|
||||||
var feeds = {};
|
var feeds = {};
|
||||||
for (var f in this.fetchers) {
|
for (var f in this.fetchers) {
|
||||||
feeds[f] = this.fetchers[f].items();
|
feeds[f] = this.fetchers[f].items();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Update Notification
|
# Module: Update Notification
|
||||||
|
|
||||||
The `updatenotification` module is one of the default modules of the MagicMirror.
|
The `updatenotification` module is one of the default modules of the MagicMirror.
|
||||||
This will display a message whenever a new version of the MagicMirror application is available.
|
This will display a message whenever a new version of the MagicMirror application is available.
|
||||||
|
|
||||||
|
|
|
@ -6,21 +6,18 @@ var defaultModules = require(__dirname + "/../defaultmodules.js");
|
||||||
var NodeHelper = require("node_helper");
|
var NodeHelper = require("node_helper");
|
||||||
|
|
||||||
module.exports = NodeHelper.create({
|
module.exports = NodeHelper.create({
|
||||||
|
|
||||||
config: {},
|
config: {},
|
||||||
|
|
||||||
updateTimer: null,
|
updateTimer: null,
|
||||||
updateProcessStarted: false,
|
updateProcessStarted: false,
|
||||||
|
|
||||||
start: function () {
|
start: function () {},
|
||||||
},
|
|
||||||
|
|
||||||
configureModules: function(modules) {
|
|
||||||
|
|
||||||
|
configureModules: function (modules) {
|
||||||
// Push MagicMirror itself , biggest chance it'll show up last in UI and isn't overwritten
|
// Push MagicMirror itself , biggest chance it'll show up last in UI and isn't overwritten
|
||||||
// others will be added in front
|
// others will be added in front
|
||||||
// this method returns promises so we can't wait for every one to resolve before continuing
|
// this method returns promises so we can't wait for every one to resolve before continuing
|
||||||
simpleGits.push({"module": "default", "git": SimpleGit(path.normalize(__dirname + "/../../../"))});
|
simpleGits.push({ module: "default", git: SimpleGit(path.normalize(__dirname + "/../../../")) });
|
||||||
|
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
|
||||||
|
@ -33,7 +30,7 @@ module.exports = NodeHelper.create({
|
||||||
//console.log("checking git for module="+moduleName)
|
//console.log("checking git for module="+moduleName)
|
||||||
let stat = fs.statSync(path.join(moduleFolder, ".git"));
|
let stat = fs.statSync(path.join(moduleFolder, ".git"));
|
||||||
promises.push(this.resolveRemote(moduleName, moduleFolder));
|
promises.push(this.resolveRemote(moduleName, moduleFolder));
|
||||||
} catch(err) {
|
} catch (err) {
|
||||||
// Error when directory .git doesn't exist
|
// Error when directory .git doesn't exist
|
||||||
// This module is not managed with git, skip
|
// This module is not managed with git, skip
|
||||||
continue;
|
continue;
|
||||||
|
@ -47,7 +44,7 @@ module.exports = NodeHelper.create({
|
||||||
socketNotificationReceived: function (notification, payload) {
|
socketNotificationReceived: function (notification, payload) {
|
||||||
if (notification === "CONFIG") {
|
if (notification === "CONFIG") {
|
||||||
this.config = payload;
|
this.config = payload;
|
||||||
} else if(notification === "MODULES") {
|
} else if (notification === "MODULES") {
|
||||||
// if this is the 1st time thru the update check process
|
// if this is the 1st time thru the update check process
|
||||||
if (!this.updateProcessStarted) {
|
if (!this.updateProcessStarted) {
|
||||||
this.updateProcessStarted = true;
|
this.updateProcessStarted = true;
|
||||||
|
@ -56,7 +53,7 @@ module.exports = NodeHelper.create({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
resolveRemote: function(moduleName, moduleFolder) {
|
resolveRemote: function (moduleName, moduleFolder) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var git = SimpleGit(moduleFolder);
|
var git = SimpleGit(moduleFolder);
|
||||||
git.getRemotes(true, (err, remotes) => {
|
git.getRemotes(true, (err, remotes) => {
|
||||||
|
@ -65,19 +62,19 @@ module.exports = NodeHelper.create({
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
// Folder has .git and has at least one git remote, watch this folder
|
// Folder has .git and has at least one git remote, watch this folder
|
||||||
simpleGits.unshift({"module": moduleName, "git": git});
|
simpleGits.unshift({ module: moduleName, git: git });
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
performFetch: function() {
|
performFetch: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
simpleGits.forEach((sg) => {
|
simpleGits.forEach((sg) => {
|
||||||
sg.git.fetch().status((err, data) => {
|
sg.git.fetch().status((err, data) => {
|
||||||
data.module = sg.module;
|
data.module = sg.module;
|
||||||
if (!err) {
|
if (!err) {
|
||||||
sg.git.log({"-1": null}, (err, data2) => {
|
sg.git.log({ "-1": null }, (err, data2) => {
|
||||||
if (!err && data2.latest && "hash" in data2.latest) {
|
if (!err && data2.latest && "hash" in data2.latest) {
|
||||||
data.hash = data2.latest.hash;
|
data.hash = data2.latest.hash;
|
||||||
self.sendSocketNotification("STATUS", data);
|
self.sendSocketNotification("STATUS", data);
|
||||||
|
@ -90,19 +87,19 @@ module.exports = NodeHelper.create({
|
||||||
this.scheduleNextFetch(this.config.updateInterval);
|
this.scheduleNextFetch(this.config.updateInterval);
|
||||||
},
|
},
|
||||||
|
|
||||||
scheduleNextFetch: function(delay) {
|
scheduleNextFetch: function (delay) {
|
||||||
if (delay < 60 * 1000) {
|
if (delay < 60 * 1000) {
|
||||||
delay = 60 * 1000;
|
delay = 60 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
clearTimeout(this.updateTimer);
|
clearTimeout(this.updateTimer);
|
||||||
this.updateTimer = setTimeout(function() {
|
this.updateTimer = setTimeout(function () {
|
||||||
self.performFetch();
|
self.performFetch();
|
||||||
}, delay);
|
}, delay);
|
||||||
},
|
},
|
||||||
|
|
||||||
ignoreUpdateChecking: function(moduleName) {
|
ignoreUpdateChecking: function (moduleName) {
|
||||||
// Should not check for updates for default modules
|
// Should not check for updates for default modules
|
||||||
if (defaultModules.indexOf(moduleName) >= 0) {
|
if (defaultModules.indexOf(moduleName) >= 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -116,5 +113,4 @@ module.exports = NodeHelper.create({
|
||||||
// The rest of the modules that passes should check for updates
|
// The rest of the modules that passes should check for updates
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("updatenotification", {
|
Module.register("updatenotification", {
|
||||||
|
|
||||||
defaults: {
|
defaults: {
|
||||||
updateInterval: 10 * 60 * 1000, // every 10 minutes
|
updateInterval: 10 * 60 * 1000, // every 10 minutes
|
||||||
refreshInterval: 24 * 60 * 60 * 1000, // one day
|
refreshInterval: 24 * 60 * 60 * 1000, // one day
|
||||||
|
@ -18,7 +17,10 @@ Module.register("updatenotification", {
|
||||||
start: function () {
|
start: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
Log.log("Start updatenotification");
|
Log.log("Start updatenotification");
|
||||||
setInterval( () => { self.moduleList = {};self.updateDom(2); } , self.config.refreshInterval);
|
setInterval(() => {
|
||||||
|
self.moduleList = {};
|
||||||
|
self.updateDom(2);
|
||||||
|
}, self.config.refreshInterval);
|
||||||
},
|
},
|
||||||
|
|
||||||
notificationReceived: function (notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
|
@ -39,16 +41,15 @@ Module.register("updatenotification", {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (payload && payload.behind > 0) {
|
if (payload && payload.behind > 0) {
|
||||||
// if we haven't seen info for this module
|
// if we haven't seen info for this module
|
||||||
if(this.moduleList[payload.module] === undefined){
|
if (this.moduleList[payload.module] === undefined) {
|
||||||
// save it
|
// save it
|
||||||
this.moduleList[payload.module]=payload;
|
this.moduleList[payload.module] = payload;
|
||||||
self.updateDom(2);
|
self.updateDom(2);
|
||||||
}
|
}
|
||||||
//self.show(1000, { lockString: self.identifier });
|
//self.show(1000, { lockString: self.identifier });
|
||||||
|
} else if (payload && payload.behind === 0) {
|
||||||
} else if (payload && payload.behind === 0){
|
|
||||||
// if the module WAS in the list, but shouldn't be
|
// if the module WAS in the list, but shouldn't be
|
||||||
if(this.moduleList[payload.module] !== undefined){
|
if (this.moduleList[payload.module] !== undefined) {
|
||||||
// remove it
|
// remove it
|
||||||
delete this.moduleList[payload.module];
|
delete this.moduleList[payload.module];
|
||||||
self.updateDom(2);
|
self.updateDom(2);
|
||||||
|
@ -56,23 +57,18 @@ Module.register("updatenotification", {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
diffLink: function(module, text) {
|
diffLink: function (module, text) {
|
||||||
var localRef = module.hash;
|
var localRef = module.hash;
|
||||||
var remoteRef = module.tracking.replace(/.*\//, "");
|
var remoteRef = module.tracking.replace(/.*\//, "");
|
||||||
return "<a href=\"https://github.com/MichMich/MagicMirror/compare/"+localRef+"..."+remoteRef+"\" "+
|
return '<a href="https://github.com/MichMich/MagicMirror/compare/' + localRef + "..." + remoteRef + '" ' + 'class="xsmall dimmed" ' + 'style="text-decoration: none;" ' + 'target="_blank" >' + text + "</a>";
|
||||||
"class=\"xsmall dimmed\" "+
|
|
||||||
"style=\"text-decoration: none;\" "+
|
|
||||||
"target=\"_blank\" >" +
|
|
||||||
text +
|
|
||||||
"</a>";
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function () {
|
getDom: function () {
|
||||||
var wrapper = document.createElement("div");
|
var wrapper = document.createElement("div");
|
||||||
if(this.suspended === false){
|
if (this.suspended === false) {
|
||||||
// process the hash of module info found
|
// process the hash of module info found
|
||||||
for(var key of Object.keys(this.moduleList)){
|
for (var key of Object.keys(this.moduleList)) {
|
||||||
let m = this.moduleList[key];
|
let m = this.moduleList[key];
|
||||||
|
|
||||||
var message = document.createElement("div");
|
var message = document.createElement("div");
|
||||||
|
@ -93,7 +89,7 @@ Module.register("updatenotification", {
|
||||||
var text = document.createElement("span");
|
var text = document.createElement("span");
|
||||||
if (m.module === "default") {
|
if (m.module === "default") {
|
||||||
text.innerHTML = this.translate("UPDATE_NOTIFICATION");
|
text.innerHTML = this.translate("UPDATE_NOTIFICATION");
|
||||||
subtextHtml = this.diffLink(m,subtextHtml);
|
subtextHtml = this.diffLink(m, subtextHtml);
|
||||||
} else {
|
} else {
|
||||||
text.innerHTML = this.translate("UPDATE_NOTIFICATION_MODULE", {
|
text.innerHTML = this.translate("UPDATE_NOTIFICATION_MODULE", {
|
||||||
MODULE_NAME: m.module
|
MODULE_NAME: m.module
|
||||||
|
@ -112,11 +108,11 @@ Module.register("updatenotification", {
|
||||||
return wrapper;
|
return wrapper;
|
||||||
},
|
},
|
||||||
|
|
||||||
suspend: function() {
|
suspend: function () {
|
||||||
this.suspended=true;
|
this.suspended = true;
|
||||||
},
|
},
|
||||||
resume: function() {
|
resume: function () {
|
||||||
this.suspended=false;
|
this.suspended = false;
|
||||||
this.updateDom(2);
|
this.updateDom(2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ Table of Contents:
|
||||||
|
|
||||||
This is the script in which the weather provider will be defined. In its most simple form, the weather provider must implement the following:
|
This is the script in which the weather provider will be defined. In its most simple form, the weather provider must implement the following:
|
||||||
|
|
||||||
````javascript
|
```javascript
|
||||||
WeatherProvider.register("yourprovider", {
|
WeatherProvider.register("yourprovider", {
|
||||||
providerName: "YourProvider",
|
providerName: "YourProvider",
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ WeatherProvider.register("yourprovider", {
|
||||||
|
|
||||||
fetchWeatherForecast() {}
|
fetchWeatherForecast() {}
|
||||||
});
|
});
|
||||||
````
|
```
|
||||||
|
|
||||||
### Weather provider methods to implement
|
### Weather provider methods to implement
|
||||||
|
|
||||||
|
@ -90,15 +90,15 @@ A convenience function to make requests. It returns a promise.
|
||||||
### WeatherObject
|
### WeatherObject
|
||||||
|
|
||||||
| Property | Type | Value/Unit |
|
| Property | Type | Value/Unit |
|
||||||
| --- | --- | --- |
|
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
|
||||||
| units | `string` | Gets initialized with the constructor. <br> Possible values: `metric`, `imperial` |
|
| units | `string` | Gets initialized with the constructor. <br> Possible values: `metric`, `imperial` |
|
||||||
| tempUnits | `string` | Gets initialized with the constructor. <br> Possible values: `metric`, `imperial` |
|
| tempUnits | `string` | Gets initialized with the constructor. <br> Possible values: `metric`, `imperial` |
|
||||||
| windUnits | `string` | Gets initialized with the constructor. <br> Possible values: `metric`, `imperial` |
|
| windUnits | `string` | Gets initialized with the constructor. <br> Possible values: `metric`, `imperial` |
|
||||||
| date | `object` | [Moment.js](https://momentjs.com/) object of the time/date. |
|
| date | `object` | [Moment.js](https://momentjs.com/) object of the time/date. |
|
||||||
| windSpeed |`number` | Metric: `meter/second` <br> Imperial: `miles/hour` |
|
| windSpeed | `number` | Metric: `meter/second` <br> Imperial: `miles/hour` |
|
||||||
| windDirection |`number` | Direction of the wind in degrees. |
|
| windDirection | `number` | Direction of the wind in degrees. |
|
||||||
| sunrise |`object` | [Moment.js](https://momentjs.com/) object of sunrise. |
|
| sunrise | `object` | [Moment.js](https://momentjs.com/) object of sunrise. |
|
||||||
| sunset |`object` | [Moment.js](https://momentjs.com/) object of sunset. |
|
| sunset | `object` | [Moment.js](https://momentjs.com/) object of sunset. |
|
||||||
| temperature | `number` | Current temperature |
|
| temperature | `number` | Current temperature |
|
||||||
| minTemperature | `number` | Lowest temperature of the day. |
|
| minTemperature | `number` | Lowest temperature of the day. |
|
||||||
| maxTemperature | `number` | Highest temperature of the day. |
|
| maxTemperature | `number` | Highest temperature of the day. |
|
||||||
|
|
|
@ -22,15 +22,16 @@ WeatherProvider.register("darksky", {
|
||||||
|
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if(!data || !data.currently || typeof data.currently.temperature === "undefined") {
|
if (!data || !data.currently || typeof data.currently.temperature === "undefined") {
|
||||||
// No usable data?
|
// No usable data?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentWeather = this.generateWeatherDayFromCurrentWeather(data);
|
const currentWeather = this.generateWeatherDayFromCurrentWeather(data);
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
}).catch(function(request) {
|
})
|
||||||
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -38,15 +39,16 @@ WeatherProvider.register("darksky", {
|
||||||
|
|
||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if(!data || !data.daily || !data.daily.data.length) {
|
if (!data || !data.daily || !data.daily.data.length) {
|
||||||
// No usable data?
|
// No usable data?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
|
const forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
}).catch(function(request) {
|
})
|
||||||
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -109,12 +111,12 @@ WeatherProvider.register("darksky", {
|
||||||
const weatherTypes = {
|
const weatherTypes = {
|
||||||
"clear-day": "day-sunny",
|
"clear-day": "day-sunny",
|
||||||
"clear-night": "night-clear",
|
"clear-night": "night-clear",
|
||||||
"rain": "rain",
|
rain: "rain",
|
||||||
"snow": "snow",
|
snow: "snow",
|
||||||
"sleet": "snow",
|
sleet: "snow",
|
||||||
"wind": "wind",
|
wind: "wind",
|
||||||
"fog": "fog",
|
fog: "fog",
|
||||||
"cloudy": "cloudy",
|
cloudy: "cloudy",
|
||||||
"partly-cloudy-day": "day-cloudy",
|
"partly-cloudy-day": "day-cloudy",
|
||||||
"partly-cloudy-night": "night-cloudy"
|
"partly-cloudy-night": "night-cloudy"
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
* This class is the blueprint for a weather provider.
|
* This class is the blueprint for a weather provider.
|
||||||
*/
|
*/
|
||||||
WeatherProvider.register("openweathermap", {
|
WeatherProvider.register("openweathermap", {
|
||||||
|
|
||||||
// Set the name of the provider.
|
// Set the name of the provider.
|
||||||
// This isn't strictly necessary, since it will fallback to the provider identifier
|
// This isn't strictly necessary, since it will fallback to the provider identifier
|
||||||
// But for debugging (and future alerts) it would be nice to have the real name.
|
// But for debugging (and future alerts) it would be nice to have the real name.
|
||||||
|
@ -18,7 +17,7 @@ WeatherProvider.register("openweathermap", {
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -30,7 +29,7 @@ WeatherProvider.register("openweathermap", {
|
||||||
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -39,7 +38,7 @@ WeatherProvider.register("openweathermap", {
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if (!data || !data.list || !data.list.length) {
|
if (!data || !data.list || !data.list.length) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -51,7 +50,7 @@ WeatherProvider.register("openweathermap", {
|
||||||
const forecast = this.generateWeatherObjectsFromForecast(data.list);
|
const forecast = this.generateWeatherObjectsFromForecast(data.list);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -86,7 +85,6 @@ WeatherProvider.register("openweathermap", {
|
||||||
* Generate WeatherObjects based on forecast information
|
* Generate WeatherObjects based on forecast information
|
||||||
*/
|
*/
|
||||||
generateWeatherObjectsFromForecast(forecasts) {
|
generateWeatherObjectsFromForecast(forecasts) {
|
||||||
|
|
||||||
if (this.config.weatherEndpoint === "/forecast") {
|
if (this.config.weatherEndpoint === "/forecast") {
|
||||||
return this.fetchForecastHourly(forecasts);
|
return this.fetchForecastHourly(forecasts);
|
||||||
} else if (this.config.weatherEndpoint === "/forecast/daily") {
|
} else if (this.config.weatherEndpoint === "/forecast/daily") {
|
||||||
|
@ -113,7 +111,6 @@ WeatherProvider.register("openweathermap", {
|
||||||
let weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
|
let weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
|
||||||
|
|
||||||
for (const forecast of forecasts) {
|
for (const forecast of forecasts) {
|
||||||
|
|
||||||
if (date !== moment(forecast.dt, "X").format("YYYY-MM-DD")) {
|
if (date !== moment(forecast.dt, "X").format("YYYY-MM-DD")) {
|
||||||
// calculate minimum/maximum temperature, specify rain amount
|
// calculate minimum/maximum temperature, specify rain amount
|
||||||
weather.minTemperature = Math.min.apply(null, minTemp);
|
weather.minTemperature = Math.min.apply(null, minTemp);
|
||||||
|
@ -139,7 +136,6 @@ WeatherProvider.register("openweathermap", {
|
||||||
|
|
||||||
// If the first value of today is later than 17:00, we have an icon at least!
|
// If the first value of today is later than 17:00, we have an icon at least!
|
||||||
weather.weatherType = this.convertWeatherType(forecast.weather[0].icon);
|
weather.weatherType = this.convertWeatherType(forecast.weather[0].icon);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moment(forecast.dt, "X").format("H") >= 8 && moment(forecast.dt, "X").format("H") <= 17) {
|
if (moment(forecast.dt, "X").format("H") >= 8 && moment(forecast.dt, "X").format("H") <= 17) {
|
||||||
|
@ -260,16 +256,16 @@ WeatherProvider.register("openweathermap", {
|
||||||
*/
|
*/
|
||||||
getParams() {
|
getParams() {
|
||||||
let params = "?";
|
let params = "?";
|
||||||
if(this.config.locationID) {
|
if (this.config.locationID) {
|
||||||
params += "id=" + this.config.locationID;
|
params += "id=" + this.config.locationID;
|
||||||
} else if(this.config.location) {
|
} else if (this.config.location) {
|
||||||
params += "q=" + this.config.location;
|
params += "q=" + this.config.location;
|
||||||
} else if (this.firstEvent && this.firstEvent.geo) {
|
} else if (this.firstEvent && this.firstEvent.geo) {
|
||||||
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
||||||
} else if (this.firstEvent && this.firstEvent.location) {
|
} else if (this.firstEvent && this.firstEvent.location) {
|
||||||
params += "q=" + this.firstEvent.location;
|
params += "q=" + this.firstEvent.location;
|
||||||
} else {
|
} else {
|
||||||
this.hide(this.config.animationSpeed, {lockString:this.identifier});
|
this.hide(this.config.animationSpeed, { lockString: this.identifier });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
* This class is a provider for UK Met Office Datapoint.
|
* This class is a provider for UK Met Office Datapoint.
|
||||||
*/
|
*/
|
||||||
WeatherProvider.register("ukmetoffice", {
|
WeatherProvider.register("ukmetoffice", {
|
||||||
|
|
||||||
// Set the name of the provider.
|
// Set the name of the provider.
|
||||||
// This isn't strictly necessary, since it will fallback to the provider identifier
|
// This isn't strictly necessary, since it will fallback to the provider identifier
|
||||||
// But for debugging (and future alerts) it would be nice to have the real name.
|
// But for debugging (and future alerts) it would be nice to have the real name.
|
||||||
|
@ -23,7 +22,7 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl("3hourly"))
|
this.fetchData(this.getUrl("3hourly"))
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) {
|
if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -35,7 +34,7 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -44,7 +43,7 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl("daily"))
|
this.fetchData(this.getUrl("daily"))
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) {
|
if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -56,7 +55,7 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
const forecast = this.generateWeatherObjectsFromForecast(data);
|
const forecast = this.generateWeatherObjectsFromForecast(data);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -83,18 +82,17 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
|
|
||||||
// loop round each of the (5) periods, look for today (the first period may be yesterday)
|
// loop round each of the (5) periods, look for today (the first period may be yesterday)
|
||||||
for (var i in currentWeatherData.SiteRep.DV.Location.Period) {
|
for (var i in currentWeatherData.SiteRep.DV.Location.Period) {
|
||||||
let periodDate = moment.utc(currentWeatherData.SiteRep.DV.Location.Period[i].value.substr(0,10), "YYYY-MM-DD");
|
let periodDate = moment.utc(currentWeatherData.SiteRep.DV.Location.Period[i].value.substr(0, 10), "YYYY-MM-DD");
|
||||||
|
|
||||||
// ignore if period is before today
|
// ignore if period is before today
|
||||||
if (periodDate.isSameOrAfter(moment.utc().startOf("day"))) {
|
if (periodDate.isSameOrAfter(moment.utc().startOf("day"))) {
|
||||||
|
|
||||||
// check this is the period we want, after today the diff will be -ve
|
// check this is the period we want, after today the diff will be -ve
|
||||||
if (moment().diff(periodDate, "minutes") > 0) {
|
if (moment().diff(periodDate, "minutes") > 0) {
|
||||||
// loop round the reports looking for the one we are in
|
// loop round the reports looking for the one we are in
|
||||||
// $ value specifies the time in minutes-of-the-day: 0, 180, 360,...1260
|
// $ value specifies the time in minutes-of-the-day: 0, 180, 360,...1260
|
||||||
for (var j in currentWeatherData.SiteRep.DV.Location.Period[i].Rep){
|
for (var j in currentWeatherData.SiteRep.DV.Location.Period[i].Rep) {
|
||||||
let p = currentWeatherData.SiteRep.DV.Location.Period[i].Rep[j].$;
|
let p = currentWeatherData.SiteRep.DV.Location.Period[i].Rep[j].$;
|
||||||
if (timeInMins >= p && timeInMins-180 < p) {
|
if (timeInMins >= p && timeInMins - 180 < p) {
|
||||||
// finally got the one we want, so populate weather object
|
// finally got the one we want, so populate weather object
|
||||||
currentWeather.humidity = currentWeatherData.SiteRep.DV.Location.Period[i].Rep[j].H;
|
currentWeather.humidity = currentWeatherData.SiteRep.DV.Location.Period[i].Rep[j].H;
|
||||||
currentWeather.temperature = this.convertTemp(currentWeatherData.SiteRep.DV.Location.Period[i].Rep[j].T);
|
currentWeather.temperature = this.convertTemp(currentWeatherData.SiteRep.DV.Location.Period[i].Rep[j].T);
|
||||||
|
@ -121,7 +119,6 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
* Generate WeatherObjects based on forecast information
|
* Generate WeatherObjects based on forecast information
|
||||||
*/
|
*/
|
||||||
generateWeatherObjectsFromForecast(forecasts) {
|
generateWeatherObjectsFromForecast(forecasts) {
|
||||||
|
|
||||||
const days = [];
|
const days = [];
|
||||||
|
|
||||||
// loop round the (5) periods getting the data
|
// loop round the (5) periods getting the data
|
||||||
|
@ -131,12 +128,12 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
|
|
||||||
// data times are always UTC
|
// data times are always UTC
|
||||||
const dateStr = forecasts.SiteRep.DV.Location.Period[j].value;
|
const dateStr = forecasts.SiteRep.DV.Location.Period[j].value;
|
||||||
let periodDate = moment.utc(dateStr.substr(0,10), "YYYY-MM-DD");
|
let periodDate = moment.utc(dateStr.substr(0, 10), "YYYY-MM-DD");
|
||||||
|
|
||||||
// ignore if period is before today
|
// ignore if period is before today
|
||||||
if (periodDate.isSameOrAfter(moment.utc().startOf("day"))) {
|
if (periodDate.isSameOrAfter(moment.utc().startOf("day"))) {
|
||||||
// populate the weather object
|
// populate the weather object
|
||||||
weather.date = moment.utc(dateStr.substr(0,10), "YYYY-MM-DD");
|
weather.date = moment.utc(dateStr.substr(0, 10), "YYYY-MM-DD");
|
||||||
weather.minTemperature = this.convertTemp(forecasts.SiteRep.DV.Location.Period[j].Rep[1].Nm);
|
weather.minTemperature = this.convertTemp(forecasts.SiteRep.DV.Location.Period[j].Rep[1].Nm);
|
||||||
weather.maxTemperature = this.convertTemp(forecasts.SiteRep.DV.Location.Period[j].Rep[0].Dm);
|
weather.maxTemperature = this.convertTemp(forecasts.SiteRep.DV.Location.Period[j].Rep[0].Dm);
|
||||||
weather.weatherType = this.convertWeatherType(forecasts.SiteRep.DV.Location.Period[j].Rep[0].W);
|
weather.weatherType = this.convertWeatherType(forecasts.SiteRep.DV.Location.Period[j].Rep[0].W);
|
||||||
|
@ -207,7 +204,7 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
* Convert temp (from degrees C) if required
|
* Convert temp (from degrees C) if required
|
||||||
*/
|
*/
|
||||||
convertTemp(tempInC) {
|
convertTemp(tempInC) {
|
||||||
return this.tempUnits === "imperial" ? tempInC * 9 / 5 + 32 : tempInC;
|
return this.tempUnits === "imperial" ? (tempInC * 9) / 5 + 32 : tempInC;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -222,22 +219,22 @@ WeatherProvider.register("ukmetoffice", {
|
||||||
*/
|
*/
|
||||||
convertWindDirection(windDirection) {
|
convertWindDirection(windDirection) {
|
||||||
const windCardinals = {
|
const windCardinals = {
|
||||||
"N": 0,
|
N: 0,
|
||||||
"NNE": 22,
|
NNE: 22,
|
||||||
"NE": 45,
|
NE: 45,
|
||||||
"ENE": 67,
|
ENE: 67,
|
||||||
"E": 90,
|
E: 90,
|
||||||
"ESE": 112,
|
ESE: 112,
|
||||||
"SE": 135,
|
SE: 135,
|
||||||
"SSE": 157,
|
SSE: 157,
|
||||||
"S": 180,
|
S: 180,
|
||||||
"SSW": 202,
|
SSW: 202,
|
||||||
"SW": 225,
|
SW: 225,
|
||||||
"WSW": 247,
|
WSW: 247,
|
||||||
"W": 270,
|
W: 270,
|
||||||
"WNW": 292,
|
WNW: 292,
|
||||||
"NW": 315,
|
NW: 315,
|
||||||
"NNW": 337
|
NNW: 337
|
||||||
};
|
};
|
||||||
|
|
||||||
return windCardinals.hasOwnProperty(windDirection) ? windCardinals[windDirection] : null;
|
return windCardinals.hasOwnProperty(windDirection) ? windCardinals[windDirection] : null;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
* Since it is free, there are some items missing - like sunrise, sunset, humidity, etc.
|
* Since it is free, there are some items missing - like sunrise, sunset, humidity, etc.
|
||||||
*/
|
*/
|
||||||
WeatherProvider.register("weathergov", {
|
WeatherProvider.register("weathergov", {
|
||||||
|
|
||||||
// Set the name of the provider.
|
// Set the name of the provider.
|
||||||
// This isn't strictly necessary, since it will fallback to the provider identifier
|
// This isn't strictly necessary, since it will fallback to the provider identifier
|
||||||
// But for debugging (and future alerts) it would be nice to have the real name.
|
// But for debugging (and future alerts) it would be nice to have the real name.
|
||||||
|
@ -21,7 +20,7 @@ WeatherProvider.register("weathergov", {
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -31,7 +30,7 @@ WeatherProvider.register("weathergov", {
|
||||||
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data.properties.periods[0]);
|
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data.properties.periods[0]);
|
||||||
this.setCurrentWeather(currentWeather);
|
this.setCurrentWeather(currentWeather);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -40,7 +39,7 @@ WeatherProvider.register("weathergov", {
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchWeatherForecast() {
|
fetchWeatherForecast() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) {
|
||||||
// Did not receive usable new data.
|
// Did not receive usable new data.
|
||||||
// Maybe this needs a better check?
|
// Maybe this needs a better check?
|
||||||
|
@ -50,7 +49,7 @@ WeatherProvider.register("weathergov", {
|
||||||
const forecast = this.generateWeatherObjectsFromForecast(data.properties.periods);
|
const forecast = this.generateWeatherObjectsFromForecast(data.properties.periods);
|
||||||
this.setWeatherForecast(forecast);
|
this.setWeatherForecast(forecast);
|
||||||
})
|
})
|
||||||
.catch(function(request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
})
|
})
|
||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
|
@ -105,9 +104,7 @@ WeatherProvider.register("weathergov", {
|
||||||
weather.precipitation = 0;
|
weather.precipitation = 0;
|
||||||
|
|
||||||
for (const forecast of forecasts) {
|
for (const forecast of forecasts) {
|
||||||
|
|
||||||
if (date !== moment(forecast.startTime).format("YYYY-MM-DD")) {
|
if (date !== moment(forecast.startTime).format("YYYY-MM-DD")) {
|
||||||
|
|
||||||
// calculate minimum/maximum temperature, specify rain amount
|
// calculate minimum/maximum temperature, specify rain amount
|
||||||
weather.minTemperature = Math.min.apply(null, minTemp);
|
weather.minTemperature = Math.min.apply(null, minTemp);
|
||||||
weather.maxTemperature = Math.max.apply(null, maxTemp);
|
weather.maxTemperature = Math.max.apply(null, maxTemp);
|
||||||
|
@ -240,22 +237,22 @@ WeatherProvider.register("weathergov", {
|
||||||
*/
|
*/
|
||||||
convertWindDirection(windDirection) {
|
convertWindDirection(windDirection) {
|
||||||
const windCardinals = {
|
const windCardinals = {
|
||||||
"N": 0,
|
N: 0,
|
||||||
"NNE": 22,
|
NNE: 22,
|
||||||
"NE": 45,
|
NE: 45,
|
||||||
"ENE": 67,
|
ENE: 67,
|
||||||
"E": 90,
|
E: 90,
|
||||||
"ESE": 112,
|
ESE: 112,
|
||||||
"SE": 135,
|
SE: 135,
|
||||||
"SSE": 157,
|
SSE: 157,
|
||||||
"S": 180,
|
S: 180,
|
||||||
"SSW": 202,
|
SSW: 202,
|
||||||
"SW": 225,
|
SW: 225,
|
||||||
"WSW": 247,
|
WSW: 247,
|
||||||
"W": 270,
|
W: 270,
|
||||||
"WNW": 292,
|
WNW: 292,
|
||||||
"NW": 315,
|
NW: 315,
|
||||||
"NNW": 337
|
NNW: 337
|
||||||
};
|
};
|
||||||
|
|
||||||
return windCardinals.hasOwnProperty(windDirection) ? windCardinals[windDirection] : null;
|
return windCardinals.hasOwnProperty(windDirection) ? windCardinals[windDirection] : null;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("weather",{
|
Module.register("weather", {
|
||||||
// Default module config.
|
// Default module config.
|
||||||
defaults: {
|
defaults: {
|
||||||
weatherProvider: "openweathermap",
|
weatherProvider: "openweathermap",
|
||||||
|
@ -60,23 +60,17 @@ Module.register("weather",{
|
||||||
weatherProvider: null,
|
weatherProvider: null,
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getStyles: function() {
|
getStyles: function () {
|
||||||
return ["font-awesome.css", "weather-icons.css", "weather.css"];
|
return ["font-awesome.css", "weather-icons.css", "weather.css"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Return the scripts that are necessary for the weather module.
|
// Return the scripts that are necessary for the weather module.
|
||||||
getScripts: function () {
|
getScripts: function () {
|
||||||
return [
|
return ["moment.js", "weatherprovider.js", "weatherobject.js", "suncalc.js", this.file("providers/" + this.config.weatherProvider.toLowerCase() + ".js")];
|
||||||
"moment.js",
|
|
||||||
"weatherprovider.js",
|
|
||||||
"weatherobject.js",
|
|
||||||
"suncalc.js",
|
|
||||||
this.file("providers/" + this.config.weatherProvider.toLowerCase() + ".js")
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override getHeader method.
|
// Override getHeader method.
|
||||||
getHeader: function() {
|
getHeader: function () {
|
||||||
if (this.config.appendLocationNameToHeader && this.data.header !== undefined && this.weatherProvider) {
|
if (this.config.appendLocationNameToHeader && this.data.header !== undefined && this.weatherProvider) {
|
||||||
return this.data.header + " " + this.weatherProvider.fetchedLocation();
|
return this.data.header + " " + this.weatherProvider.fetchedLocation();
|
||||||
}
|
}
|
||||||
|
@ -102,7 +96,7 @@ Module.register("weather",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override notification handler.
|
// Override notification handler.
|
||||||
notificationReceived: function(notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
if (notification === "CALENDAR_EVENTS") {
|
if (notification === "CALENDAR_EVENTS") {
|
||||||
var senderClasses = sender.data.classes.toLowerCase().split(" ");
|
var senderClasses = sender.data.classes.toLowerCase().split(" ");
|
||||||
if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) {
|
if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) {
|
||||||
|
@ -145,13 +139,13 @@ Module.register("weather",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// What to do when the weather provider has new information available?
|
// What to do when the weather provider has new information available?
|
||||||
updateAvailable: function() {
|
updateAvailable: function () {
|
||||||
Log.log("New weather information available.");
|
Log.log("New weather information available.");
|
||||||
this.updateDom(0);
|
this.updateDom(0);
|
||||||
this.scheduleUpdate();
|
this.scheduleUpdate();
|
||||||
},
|
},
|
||||||
|
|
||||||
scheduleUpdate: function(delay = null) {
|
scheduleUpdate: function (delay = null) {
|
||||||
var nextLoad = this.config.updateInterval;
|
var nextLoad = this.config.updateInterval;
|
||||||
if (delay !== null && delay >= 0) {
|
if (delay !== null && delay >= 0) {
|
||||||
nextLoad = delay;
|
nextLoad = delay;
|
||||||
|
@ -166,13 +160,15 @@ Module.register("weather",{
|
||||||
}, nextLoad);
|
}, nextLoad);
|
||||||
},
|
},
|
||||||
|
|
||||||
roundValue: function(temperature) {
|
roundValue: function (temperature) {
|
||||||
var decimals = this.config.roundTemp ? 0 : 1;
|
var decimals = this.config.roundTemp ? 0 : 1;
|
||||||
return parseFloat(temperature).toFixed(decimals);
|
return parseFloat(temperature).toFixed(decimals);
|
||||||
},
|
},
|
||||||
|
|
||||||
addFilters() {
|
addFilters() {
|
||||||
this.nunjucksEnvironment().addFilter("formatTime", function(date) {
|
this.nunjucksEnvironment().addFilter(
|
||||||
|
"formatTime",
|
||||||
|
function (date) {
|
||||||
date = moment(date);
|
date = moment(date);
|
||||||
|
|
||||||
if (this.config.timeFormat !== 24) {
|
if (this.config.timeFormat !== 24) {
|
||||||
|
@ -188,9 +184,12 @@ Module.register("weather",{
|
||||||
}
|
}
|
||||||
|
|
||||||
return date.format("HH:mm");
|
return date.format("HH:mm");
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
this.nunjucksEnvironment().addFilter("unit", function (value, type) {
|
this.nunjucksEnvironment().addFilter(
|
||||||
|
"unit",
|
||||||
|
function (value, type) {
|
||||||
if (type === "temperature") {
|
if (type === "temperature") {
|
||||||
if (this.config.tempUnits === "metric" || this.config.tempUnits === "imperial") {
|
if (this.config.tempUnits === "metric" || this.config.tempUnits === "imperial") {
|
||||||
value += "°";
|
value += "°";
|
||||||
|
@ -219,21 +218,33 @@ Module.register("weather",{
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
this.nunjucksEnvironment().addFilter("roundValue", function(value) {
|
this.nunjucksEnvironment().addFilter(
|
||||||
|
"roundValue",
|
||||||
|
function (value) {
|
||||||
return this.roundValue(value);
|
return this.roundValue(value);
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
this.nunjucksEnvironment().addFilter("decimalSymbol", function(value) {
|
this.nunjucksEnvironment().addFilter(
|
||||||
|
"decimalSymbol",
|
||||||
|
function (value) {
|
||||||
return value.toString().replace(/\./g, this.config.decimalSymbol);
|
return value.toString().replace(/\./g, this.config.decimalSymbol);
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
this.nunjucksEnvironment().addFilter("calcNumSteps", function(forecast) {
|
this.nunjucksEnvironment().addFilter(
|
||||||
|
"calcNumSteps",
|
||||||
|
function (forecast) {
|
||||||
return Math.min(forecast.length, this.config.maxNumberOfDays);
|
return Math.min(forecast.length, this.config.maxNumberOfDays);
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
this.nunjucksEnvironment().addFilter("opacity", function(currentStep, numSteps) {
|
this.nunjucksEnvironment().addFilter(
|
||||||
|
"opacity",
|
||||||
|
function (currentStep, numSteps) {
|
||||||
if (this.config.fade && this.config.fadePoint < 1) {
|
if (this.config.fade && this.config.fadePoint < 1) {
|
||||||
if (this.config.fadePoint < 0) {
|
if (this.config.fadePoint < 0) {
|
||||||
this.config.fadePoint = 0;
|
this.config.fadePoint = 0;
|
||||||
|
@ -248,6 +259,7 @@ Module.register("weather",{
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
*/
|
*/
|
||||||
class WeatherObject {
|
class WeatherObject {
|
||||||
constructor(units, tempUnits, windUnits) {
|
constructor(units, tempUnits, windUnits) {
|
||||||
|
|
||||||
this.units = units;
|
this.units = units;
|
||||||
this.tempUnits = tempUnits;
|
this.tempUnits = tempUnits;
|
||||||
this.windUnits = windUnits;
|
this.windUnits = windUnits;
|
||||||
|
@ -29,11 +28,10 @@ class WeatherObject {
|
||||||
this.snow = null;
|
this.snow = null;
|
||||||
this.precipitation = null;
|
this.precipitation = null;
|
||||||
this.feelsLikeTemp = null;
|
this.feelsLikeTemp = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cardinalWindDirection() {
|
cardinalWindDirection() {
|
||||||
if (this.windDirection > 11.25 && this.windDirection <= 33.75){
|
if (this.windDirection > 11.25 && this.windDirection <= 33.75) {
|
||||||
return "NNE";
|
return "NNE";
|
||||||
} else if (this.windDirection > 33.75 && this.windDirection <= 56.25) {
|
} else if (this.windDirection > 33.75 && this.windDirection <= 56.25) {
|
||||||
return "NE";
|
return "NE";
|
||||||
|
@ -69,7 +67,7 @@ class WeatherObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
beaufortWindSpeed() {
|
beaufortWindSpeed() {
|
||||||
const windInKmh = (this.windUnits === "imperial") ? this.windSpeed * 1.609344 : this.windSpeed * 60 * 60 / 1000;
|
const windInKmh = this.windUnits === "imperial" ? this.windSpeed * 1.609344 : (this.windSpeed * 60 * 60) / 1000;
|
||||||
const speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
const speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
||||||
for (const [index, speed] of speeds.entries()) {
|
for (const [index, speed] of speeds.entries()) {
|
||||||
if (speed > windInKmh) {
|
if (speed > windInKmh) {
|
||||||
|
@ -87,21 +85,25 @@ class WeatherObject {
|
||||||
if (this.feelsLikeTemp) {
|
if (this.feelsLikeTemp) {
|
||||||
return this.feelsLikeTemp;
|
return this.feelsLikeTemp;
|
||||||
}
|
}
|
||||||
const windInMph = (this.windUnits === "imperial") ? this.windSpeed : this.windSpeed * 2.23694;
|
const windInMph = this.windUnits === "imperial" ? this.windSpeed : this.windSpeed * 2.23694;
|
||||||
const tempInF = this.tempUnits === "imperial" ? this.temperature : this.temperature * 9 / 5 + 32;
|
const tempInF = this.tempUnits === "imperial" ? this.temperature : (this.temperature * 9) / 5 + 32;
|
||||||
let feelsLike = tempInF;
|
let feelsLike = tempInF;
|
||||||
|
|
||||||
if (windInMph > 3 && tempInF < 50) {
|
if (windInMph > 3 && tempInF < 50) {
|
||||||
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
|
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
|
||||||
} else if (tempInF > 80 && this.humidity > 40) {
|
} else if (tempInF > 80 && this.humidity > 40) {
|
||||||
feelsLike = -42.379 + 2.04901523 * tempInF + 10.14333127 * this.humidity
|
feelsLike =
|
||||||
- 0.22475541 * tempInF * this.humidity - 6.83783 * Math.pow(10, -3) * tempInF * tempInF
|
-42.379 +
|
||||||
- 5.481717 * Math.pow(10, -2) * this.humidity * this.humidity
|
2.04901523 * tempInF +
|
||||||
+ 1.22874 * Math.pow(10, -3) * tempInF * tempInF * this.humidity
|
10.14333127 * this.humidity -
|
||||||
+ 8.5282 * Math.pow(10, -4) * tempInF * this.humidity * this.humidity
|
0.22475541 * tempInF * this.humidity -
|
||||||
- 1.99 * Math.pow(10, -6) * tempInF * tempInF * this.humidity * 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.tempUnits === "imperial" ? feelsLike : (feelsLike - 32) * 5 / 9;
|
return this.tempUnits === "imperial" ? feelsLike : ((feelsLike - 32) * 5) / 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,77 +28,77 @@ var WeatherProvider = Class.extend({
|
||||||
// All the following methods can be overwritten, although most are good as they are.
|
// All the following methods can be overwritten, although most are good as they are.
|
||||||
|
|
||||||
// Called when a weather provider is initialized.
|
// Called when a weather provider is initialized.
|
||||||
init: function(config) {
|
init: function (config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
Log.info(`Weather provider: ${this.providerName} initialized.`);
|
Log.info(`Weather provider: ${this.providerName} initialized.`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called to set the config, this config is the same as the weather module's config.
|
// Called to set the config, this config is the same as the weather module's config.
|
||||||
setConfig: function(config) {
|
setConfig: function (config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
Log.info(`Weather provider: ${this.providerName} config set.`, this.config);
|
Log.info(`Weather provider: ${this.providerName} config set.`, this.config);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called when the weather provider is about to start.
|
// Called when the weather provider is about to start.
|
||||||
start: function() {
|
start: function () {
|
||||||
Log.info(`Weather provider: ${this.providerName} started.`);
|
Log.info(`Weather provider: ${this.providerName} started.`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// This method should start the API request to fetch the current weather.
|
// This method should start the API request to fetch the current weather.
|
||||||
// This method should definitely be overwritten in the provider.
|
// This method should definitely be overwritten in the provider.
|
||||||
fetchCurrentWeather: function() {
|
fetchCurrentWeather: function () {
|
||||||
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchCurrentWeather method.`);
|
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchCurrentWeather method.`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// This method should start the API request to fetch the weather forecast.
|
// This method should start the API request to fetch the weather forecast.
|
||||||
// This method should definitely be overwritten in the provider.
|
// This method should definitely be overwritten in the provider.
|
||||||
fetchWeatherForecast: function() {
|
fetchWeatherForecast: function () {
|
||||||
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchWeatherForecast method.`);
|
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchWeatherForecast method.`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// This returns a WeatherDay object for the current weather.
|
// This returns a WeatherDay object for the current weather.
|
||||||
currentWeather: function() {
|
currentWeather: function () {
|
||||||
return this.currentWeatherObject;
|
return this.currentWeatherObject;
|
||||||
},
|
},
|
||||||
|
|
||||||
// This returns an array of WeatherDay objects for the weather forecast.
|
// This returns an array of WeatherDay objects for the weather forecast.
|
||||||
weatherForecast: function() {
|
weatherForecast: function () {
|
||||||
return this.weatherForecastArray;
|
return this.weatherForecastArray;
|
||||||
},
|
},
|
||||||
|
|
||||||
// This returns the name of the fetched location or an empty string.
|
// This returns the name of the fetched location or an empty string.
|
||||||
fetchedLocation: function() {
|
fetchedLocation: function () {
|
||||||
return this.fetchedLocationName || "";
|
return this.fetchedLocationName || "";
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the currentWeather and notify the delegate that new information is available.
|
// Set the currentWeather and notify the delegate that new information is available.
|
||||||
setCurrentWeather: function(currentWeatherObject) {
|
setCurrentWeather: function (currentWeatherObject) {
|
||||||
// We should check here if we are passing a WeatherDay
|
// We should check here if we are passing a WeatherDay
|
||||||
this.currentWeatherObject = currentWeatherObject;
|
this.currentWeatherObject = currentWeatherObject;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the weatherForecastArray and notify the delegate that new information is available.
|
// Set the weatherForecastArray and notify the delegate that new information is available.
|
||||||
setWeatherForecast: function(weatherForecastArray) {
|
setWeatherForecast: function (weatherForecastArray) {
|
||||||
// We should check here if we are passing a WeatherDay
|
// We should check here if we are passing a WeatherDay
|
||||||
this.weatherForecastArray = weatherForecastArray;
|
this.weatherForecastArray = weatherForecastArray;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the fetched location name.
|
// Set the fetched location name.
|
||||||
setFetchedLocation: function(name) {
|
setFetchedLocation: function (name) {
|
||||||
this.fetchedLocationName = name;
|
this.fetchedLocationName = name;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Notify the delegate that new weather is available.
|
// Notify the delegate that new weather is available.
|
||||||
updateAvailable: function() {
|
updateAvailable: function () {
|
||||||
this.delegate.updateAvailable(this);
|
this.delegate.updateAvailable(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
// A convenience function to make requests. It returns a promise.
|
// A convenience function to make requests. It returns a promise.
|
||||||
fetchData: function(url, method = "GET", data = null) {
|
fetchData: function (url, method = "GET", data = null) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.open(method, url, true);
|
request.open(method, url, true);
|
||||||
request.onreadystatechange = function() {
|
request.onreadystatechange = function () {
|
||||||
if (this.readyState === 4) {
|
if (this.readyState === 4) {
|
||||||
if (this.status === 200) {
|
if (this.status === 200) {
|
||||||
resolve(JSON.parse(this.response));
|
resolve(JSON.parse(this.response));
|
||||||
|
@ -120,14 +120,14 @@ WeatherProvider.providers = [];
|
||||||
/**
|
/**
|
||||||
* Static method to register a new weather provider.
|
* Static method to register a new weather provider.
|
||||||
*/
|
*/
|
||||||
WeatherProvider.register = function(providerIdentifier, providerDetails) {
|
WeatherProvider.register = function (providerIdentifier, providerDetails) {
|
||||||
WeatherProvider.providers[providerIdentifier.toLowerCase()] = WeatherProvider.extend(providerDetails);
|
WeatherProvider.providers[providerIdentifier.toLowerCase()] = WeatherProvider.extend(providerDetails);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method to initialize a new weather provider.
|
* Static method to initialize a new weather provider.
|
||||||
*/
|
*/
|
||||||
WeatherProvider.initialize = function(providerIdentifier, delegate) {
|
WeatherProvider.initialize = function (providerIdentifier, delegate) {
|
||||||
providerIdentifier = providerIdentifier.toLowerCase();
|
providerIdentifier = providerIdentifier.toLowerCase();
|
||||||
|
|
||||||
var provider = new WeatherProvider.providers[providerIdentifier]();
|
var provider = new WeatherProvider.providers[providerIdentifier]();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Module: Weather Forecast
|
# Module: Weather Forecast
|
||||||
|
|
||||||
The `weatherforecast` module is one of the default modules of the MagicMirror.
|
The `weatherforecast` module is one of the default modules of the MagicMirror.
|
||||||
This module displays the weather forecast for the coming week, including an an icon to display the current conditions, the minimum temperature and the maximum temperature.
|
This module displays the weather forecast for the coming week, including an an icon to display the current conditions, the minimum temperature and the maximum temperature.
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
Module.register("weatherforecast",{
|
Module.register("weatherforecast", {
|
||||||
|
|
||||||
// Default module config.
|
// Default module config.
|
||||||
defaults: {
|
defaults: {
|
||||||
location: false,
|
location: false,
|
||||||
|
@ -56,7 +55,7 @@ Module.register("weatherforecast",{
|
||||||
"11n": "wi-night-thunderstorm",
|
"11n": "wi-night-thunderstorm",
|
||||||
"13n": "wi-night-snow",
|
"13n": "wi-night-snow",
|
||||||
"50n": "wi-night-alt-cloudy-windy"
|
"50n": "wi-night-alt-cloudy-windy"
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// create a variable for the first upcoming calendar event. Used if no location is specified.
|
// create a variable for the first upcoming calendar event. Used if no location is specified.
|
||||||
|
@ -66,17 +65,17 @@ Module.register("weatherforecast",{
|
||||||
fetchedLocationName: "",
|
fetchedLocationName: "",
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getScripts: function() {
|
getScripts: function () {
|
||||||
return ["moment.js"];
|
return ["moment.js"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getStyles: function() {
|
getStyles: function () {
|
||||||
return ["weather-icons.css", "weatherforecast.css"];
|
return ["weather-icons.css", "weatherforecast.css"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required translations.
|
// Define required translations.
|
||||||
getTranslations: function() {
|
getTranslations: function () {
|
||||||
// The translations for the default modules are defined in the core translation files.
|
// The translations for the default modules are defined in the core translation files.
|
||||||
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
||||||
// If you're trying to build your own module including translations, check out the documentation.
|
// If you're trying to build your own module including translations, check out the documentation.
|
||||||
|
@ -84,7 +83,7 @@ Module.register("weatherforecast",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define start sequence.
|
// Define start sequence.
|
||||||
start: function() {
|
start: function () {
|
||||||
Log.info("Starting module: " + this.name);
|
Log.info("Starting module: " + this.name);
|
||||||
|
|
||||||
// Set locale.
|
// Set locale.
|
||||||
|
@ -95,11 +94,10 @@ Module.register("weatherforecast",{
|
||||||
this.scheduleUpdate(this.config.initialLoadDelay);
|
this.scheduleUpdate(this.config.initialLoadDelay);
|
||||||
|
|
||||||
this.updateTimer = null;
|
this.updateTimer = null;
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override dom generator.
|
// Override dom generator.
|
||||||
getDom: function() {
|
getDom: function () {
|
||||||
var wrapper = document.createElement("div");
|
var wrapper = document.createElement("div");
|
||||||
|
|
||||||
if (this.config.appid === "") {
|
if (this.config.appid === "") {
|
||||||
|
@ -143,8 +141,8 @@ Module.register("weatherforecast",{
|
||||||
if (this.config.units === "metric" || this.config.units === "imperial") {
|
if (this.config.units === "metric" || this.config.units === "imperial") {
|
||||||
degreeLabel += "°";
|
degreeLabel += "°";
|
||||||
}
|
}
|
||||||
if(this.config.scale) {
|
if (this.config.scale) {
|
||||||
switch(this.config.units) {
|
switch (this.config.units) {
|
||||||
case "metric":
|
case "metric":
|
||||||
degreeLabel += "C";
|
degreeLabel += "C";
|
||||||
break;
|
break;
|
||||||
|
@ -176,7 +174,7 @@ Module.register("weatherforecast",{
|
||||||
if (isNaN(forecast.rain)) {
|
if (isNaN(forecast.rain)) {
|
||||||
rainCell.innerHTML = "";
|
rainCell.innerHTML = "";
|
||||||
} else {
|
} else {
|
||||||
if(config.units !== "imperial") {
|
if (config.units !== "imperial") {
|
||||||
rainCell.innerHTML = parseFloat(forecast.rain).toFixed(1).replace(".", this.config.decimalSymbol) + " mm";
|
rainCell.innerHTML = parseFloat(forecast.rain).toFixed(1).replace(".", this.config.decimalSymbol) + " mm";
|
||||||
} else {
|
} else {
|
||||||
rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2).replace(".", this.config.decimalSymbol) + " in";
|
rainCell.innerHTML = (parseFloat(forecast.rain) / 25.4).toFixed(2).replace(".", this.config.decimalSymbol) + " in";
|
||||||
|
@ -194,7 +192,7 @@ Module.register("weatherforecast",{
|
||||||
var steps = this.forecast.length - startingPoint;
|
var steps = this.forecast.length - startingPoint;
|
||||||
if (f >= startingPoint) {
|
if (f >= startingPoint) {
|
||||||
var currentStep = f - startingPoint;
|
var currentStep = f - startingPoint;
|
||||||
row.style.opacity = 1 - (1 / steps * currentStep);
|
row.style.opacity = 1 - (1 / steps) * currentStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,7 +201,7 @@ Module.register("weatherforecast",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override getHeader method.
|
// Override getHeader method.
|
||||||
getHeader: function() {
|
getHeader: function () {
|
||||||
if (this.config.appendLocationNameToHeader) {
|
if (this.config.appendLocationNameToHeader) {
|
||||||
return this.data.header + " " + this.fetchedLocationName;
|
return this.data.header + " " + this.fetchedLocationName;
|
||||||
}
|
}
|
||||||
|
@ -212,10 +210,10 @@ Module.register("weatherforecast",{
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override notification handler.
|
// Override notification handler.
|
||||||
notificationReceived: function(notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
if (notification === "DOM_OBJECTS_CREATED") {
|
if (notification === "DOM_OBJECTS_CREATED") {
|
||||||
if (this.config.appendLocationNameToHeader) {
|
if (this.config.appendLocationNameToHeader) {
|
||||||
this.hide(0, {lockString: this.identifier});
|
this.hide(0, { lockString: this.identifier });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notification === "CALENDAR_EVENTS") {
|
if (notification === "CALENDAR_EVENTS") {
|
||||||
|
@ -239,7 +237,7 @@ Module.register("weatherforecast",{
|
||||||
* Requests new data from openweather.org.
|
* Requests new data from openweather.org.
|
||||||
* Calls processWeather on successful response.
|
* Calls processWeather on successful response.
|
||||||
*/
|
*/
|
||||||
updateWeather: function() {
|
updateWeather: function () {
|
||||||
if (this.config.appid === "") {
|
if (this.config.appid === "") {
|
||||||
Log.error("WeatherForecast: APPID not set!");
|
Log.error("WeatherForecast: APPID not set!");
|
||||||
return;
|
return;
|
||||||
|
@ -251,7 +249,7 @@ Module.register("weatherforecast",{
|
||||||
|
|
||||||
var weatherRequest = new XMLHttpRequest();
|
var weatherRequest = new XMLHttpRequest();
|
||||||
weatherRequest.open("GET", url, true);
|
weatherRequest.open("GET", url, true);
|
||||||
weatherRequest.onreadystatechange = function() {
|
weatherRequest.onreadystatechange = function () {
|
||||||
if (this.readyState === 4) {
|
if (this.readyState === 4) {
|
||||||
if (this.status === 200) {
|
if (this.status === 200) {
|
||||||
self.processWeather(JSON.parse(this.response));
|
self.processWeather(JSON.parse(this.response));
|
||||||
|
@ -269,7 +267,7 @@ Module.register("weatherforecast",{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
self.scheduleUpdate((self.loaded) ? -1 : self.config.retryDelay);
|
self.scheduleUpdate(self.loaded ? -1 : self.config.retryDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -281,18 +279,18 @@ Module.register("weatherforecast",{
|
||||||
*
|
*
|
||||||
* return String - URL params.
|
* return String - URL params.
|
||||||
*/
|
*/
|
||||||
getParams: function() {
|
getParams: function () {
|
||||||
var params = "?";
|
var params = "?";
|
||||||
if(this.config.locationID) {
|
if (this.config.locationID) {
|
||||||
params += "id=" + this.config.locationID;
|
params += "id=" + this.config.locationID;
|
||||||
} else if(this.config.location) {
|
} else if (this.config.location) {
|
||||||
params += "q=" + this.config.location;
|
params += "q=" + this.config.location;
|
||||||
} else if (this.firstEvent && this.firstEvent.geo) {
|
} else if (this.firstEvent && this.firstEvent.geo) {
|
||||||
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
||||||
} else if (this.firstEvent && this.firstEvent.location) {
|
} else if (this.firstEvent && this.firstEvent.location) {
|
||||||
params += "q=" + this.firstEvent.location;
|
params += "q=" + this.firstEvent.location;
|
||||||
} else {
|
} else {
|
||||||
this.hide(this.config.animationSpeed, {lockString:this.identifier});
|
this.hide(this.config.animationSpeed, { lockString: this.identifier });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,9 +308,9 @@ Module.register("weatherforecast",{
|
||||||
* from openweather.org
|
* from openweather.org
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
parserDataWeather: function(data) {
|
parserDataWeather: function (data) {
|
||||||
if (data.hasOwnProperty("main")) {
|
if (data.hasOwnProperty("main")) {
|
||||||
data["temp"] = {"min": data.main.temp_min, "max": data.main.temp_max};
|
data["temp"] = { min: data.main.temp_min, max: data.main.temp_max };
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
@ -322,7 +320,7 @@ Module.register("weatherforecast",{
|
||||||
*
|
*
|
||||||
* argument data object - Weather information received form openweather.org.
|
* argument data object - Weather information received form openweather.org.
|
||||||
*/
|
*/
|
||||||
processWeather: function(data) {
|
processWeather: function (data) {
|
||||||
this.fetchedLocationName = data.city.name + ", " + data.city.country;
|
this.fetchedLocationName = data.city.name + ", " + data.city.country;
|
||||||
|
|
||||||
this.forecast = [];
|
this.forecast = [];
|
||||||
|
@ -330,13 +328,12 @@ Module.register("weatherforecast",{
|
||||||
var forecastData = {};
|
var forecastData = {};
|
||||||
|
|
||||||
for (var i = 0, count = data.list.length; i < count; i++) {
|
for (var i = 0, count = data.list.length; i < count; i++) {
|
||||||
|
|
||||||
var forecast = data.list[i];
|
var forecast = data.list[i];
|
||||||
this.parserDataWeather(forecast); // hack issue #1017
|
this.parserDataWeather(forecast); // hack issue #1017
|
||||||
|
|
||||||
var day;
|
var day;
|
||||||
var hour;
|
var hour;
|
||||||
if(forecast.dt_txt) {
|
if (forecast.dt_txt) {
|
||||||
day = moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss").format("ddd");
|
day = moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss").format("ddd");
|
||||||
hour = moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss").format("H");
|
hour = moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss").format("H");
|
||||||
} else {
|
} else {
|
||||||
|
@ -375,7 +372,7 @@ Module.register("weatherforecast",{
|
||||||
}
|
}
|
||||||
|
|
||||||
//Log.log(this.forecast);
|
//Log.log(this.forecast);
|
||||||
this.show(this.config.animationSpeed, {lockString:this.identifier});
|
this.show(this.config.animationSpeed, { lockString: this.identifier });
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
this.updateDom(this.config.animationSpeed);
|
this.updateDom(this.config.animationSpeed);
|
||||||
},
|
},
|
||||||
|
@ -385,7 +382,7 @@ Module.register("weatherforecast",{
|
||||||
*
|
*
|
||||||
* argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
|
* argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
|
||||||
*/
|
*/
|
||||||
scheduleUpdate: function(delay) {
|
scheduleUpdate: function (delay) {
|
||||||
var nextLoad = this.config.updateInterval;
|
var nextLoad = this.config.updateInterval;
|
||||||
if (typeof delay !== "undefined" && delay >= 0) {
|
if (typeof delay !== "undefined" && delay >= 0) {
|
||||||
nextLoad = delay;
|
nextLoad = delay;
|
||||||
|
@ -393,7 +390,7 @@ Module.register("weatherforecast",{
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
clearTimeout(this.updateTimer);
|
clearTimeout(this.updateTimer);
|
||||||
this.updateTimer = setTimeout(function() {
|
this.updateTimer = setTimeout(function () {
|
||||||
self.updateWeather();
|
self.updateWeather();
|
||||||
}, nextLoad);
|
}, nextLoad);
|
||||||
},
|
},
|
||||||
|
@ -409,8 +406,8 @@ Module.register("weatherforecast",{
|
||||||
*
|
*
|
||||||
* return number - Windspeed in beaufort.
|
* return number - Windspeed in beaufort.
|
||||||
*/
|
*/
|
||||||
ms2Beaufort: function(ms) {
|
ms2Beaufort: function (ms) {
|
||||||
var kmh = ms * 60 * 60 / 1000;
|
var kmh = (ms * 60 * 60) / 1000;
|
||||||
var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
||||||
for (var beaufort in speeds) {
|
for (var beaufort in speeds) {
|
||||||
var speed = speeds[beaufort];
|
var speed = speeds[beaufort];
|
||||||
|
@ -428,7 +425,7 @@ Module.register("weatherforecast",{
|
||||||
*
|
*
|
||||||
* return string - Rounded Temperature.
|
* return string - Rounded Temperature.
|
||||||
*/
|
*/
|
||||||
roundValue: function(temperature) {
|
roundValue: function (temperature) {
|
||||||
var decimals = this.config.roundTemp ? 0 : 1;
|
var decimals = this.config.roundTemp ? 0 : 1;
|
||||||
return parseFloat(temperature).toFixed(decimals);
|
return parseFloat(temperature).toFixed(decimals);
|
||||||
},
|
},
|
||||||
|
@ -440,16 +437,16 @@ Module.register("weatherforecast",{
|
||||||
* That object has a property "3h" which contains the amount of rain since the previous forecast in the list.
|
* That object has a property "3h" which contains the amount of rain since the previous forecast in the list.
|
||||||
* This code finds all forecasts that is for the same day and sums the amount of rain and returns that.
|
* This code finds all forecasts that is for the same day and sums the amount of rain and returns that.
|
||||||
*/
|
*/
|
||||||
processRain: function(forecast, allForecasts) {
|
processRain: function (forecast, allForecasts) {
|
||||||
//If the amount of rain actually is a number, return it
|
//If the amount of rain actually is a number, return it
|
||||||
if (!isNaN(forecast.rain)) {
|
if (!isNaN(forecast.rain)) {
|
||||||
return forecast.rain;
|
return forecast.rain;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Find all forecasts that is for the same day
|
//Find all forecasts that is for the same day
|
||||||
var checkDateTime = (forecast.dt_txt) ? moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss") : moment(forecast.dt, "X");
|
var checkDateTime = forecast.dt_txt ? moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss") : moment(forecast.dt, "X");
|
||||||
var daysForecasts = allForecasts.filter(function(item) {
|
var daysForecasts = allForecasts.filter(function (item) {
|
||||||
var itemDateTime = (item.dt_txt) ? moment(item.dt_txt, "YYYY-MM-DD hh:mm:ss") : moment(item.dt, "X");
|
var itemDateTime = item.dt_txt ? moment(item.dt_txt, "YYYY-MM-DD hh:mm:ss") : moment(item.dt, "X");
|
||||||
return itemDateTime.isSame(checkDateTime, "day") && item.rain instanceof Object;
|
return itemDateTime.isSame(checkDateTime, "day") && item.rain instanceof Object;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -459,9 +456,11 @@ Module.register("weatherforecast",{
|
||||||
}
|
}
|
||||||
|
|
||||||
//Summarize all the rain from the matching days
|
//Summarize all the rain from the matching days
|
||||||
return daysForecasts.map(function(item) {
|
return daysForecasts
|
||||||
|
.map(function (item) {
|
||||||
return Object.values(item.rain)[0];
|
return Object.values(item.rain)[0];
|
||||||
}).reduce(function(a, b) {
|
})
|
||||||
|
.reduce(function (a, b) {
|
||||||
return a + b;
|
return a + b;
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
var app = require("../js/app.js");
|
var app = require("../js/app.js");
|
||||||
app.start(function(config) {
|
app.start(function (config) {
|
||||||
var bindAddress = config.address ? config.address : "localhost";
|
var bindAddress = config.address ? config.address : "localhost";
|
||||||
var httpType = config.useHttps ? "https" : "http";
|
var httpType = config.useHttps ? "https" : "http";
|
||||||
console.log("\nReady to go! Please point your browser to: " + httpType + "://" + bindAddress + ":" + config.port);
|
console.log("\nReady to go! Please point your browser to: " + httpType + "://" + bindAddress + ":" + config.port);
|
||||||
|
|
|
@ -13,13 +13,14 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: []
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,13 +13,14 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: []
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -38,4 +38,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -39,4 +39,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -34,4 +34,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -41,4 +41,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -36,4 +36,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -26,4 +26,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -26,4 +26,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -29,4 +29,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -29,4 +29,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -29,4 +29,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -26,4 +26,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -26,4 +26,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -29,4 +29,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -32,4 +32,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -27,7 +27,6 @@ var config = {
|
||||||
afternoon: [],
|
afternoon: [],
|
||||||
evening: [],
|
evening: [],
|
||||||
anytime: ["Anytime here"]
|
anytime: ["Anytime here"]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,4 +34,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ let config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -28,9 +28,7 @@ let config = {
|
||||||
morning: [],
|
morning: [],
|
||||||
afternoon: [],
|
afternoon: [],
|
||||||
evening: [],
|
evening: [],
|
||||||
"....-01-01": [
|
"....-01-01": ["Happy new year!"]
|
||||||
"Happy new year!"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,4 +36,6 @@ let config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -24,7 +24,6 @@ var config = {
|
||||||
config: {
|
config: {
|
||||||
compliments: {
|
compliments: {
|
||||||
anytime: ["Anytime here"]
|
anytime: ["Anytime here"]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,4 +31,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -23,15 +23,9 @@ var config = {
|
||||||
position: "middle_center",
|
position: "middle_center",
|
||||||
config: {
|
config: {
|
||||||
compliments: {
|
compliments: {
|
||||||
morning: [
|
morning: ["Hi", "Good Morning", "Morning test"],
|
||||||
"Hi", "Good Morning", "Morning test"
|
afternoon: ["Hello", "Good Afternoon", "Afternoon test"],
|
||||||
],
|
evening: ["Hello There", "Good Evening", "Evening test"]
|
||||||
afternoon: [
|
|
||||||
"Hello", "Good Afternoon", "Afternoon test"
|
|
||||||
],
|
|
||||||
evening: [
|
|
||||||
"Hello There", "Good Evening", "Evening test"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,4 +33,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -29,4 +29,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -26,4 +26,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,13 +13,12 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
|
|
||||||
module: "newsfeed",
|
module: "newsfeed",
|
||||||
position: "bottom_bar",
|
position: "bottom_bar",
|
||||||
config: {
|
config: {
|
||||||
|
@ -27,7 +26,7 @@ var config = {
|
||||||
{
|
{
|
||||||
title: "Rodrigo Ramirez Blog",
|
title: "Rodrigo Ramirez Blog",
|
||||||
url: "http://localhost:8080/tests/configs/data/feed_test_rodrigoramirez.xml"
|
url: "http://localhost:8080/tests/configs/data/feed_test_rodrigoramirez.xml"
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,4 +34,6 @@ var config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -15,16 +15,14 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
// Using exotic content. This is why dont accept go to JSON configuration file
|
// Using exotic content. This is why dont accept go to JSON configuration file
|
||||||
(function() {
|
(function () {
|
||||||
var positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third",
|
var positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];
|
||||||
"middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right",
|
|
||||||
"bottom_bar", "fullscreen_above", "fullscreen_below"];
|
|
||||||
var modules = Array();
|
var modules = Array();
|
||||||
for (var idx in positions) {
|
for (var idx in positions) {
|
||||||
modules.push({
|
modules.push({
|
||||||
|
@ -36,7 +34,9 @@ var config = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return modules;
|
return modules;
|
||||||
})(),
|
})()
|
||||||
};
|
};
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ let config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -32,4 +32,6 @@ let config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ let config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -37,4 +37,6 @@ let config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ let config = {
|
||||||
units: "imperial",
|
units: "imperial",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -34,4 +34,6 @@ let config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ let config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -34,4 +34,6 @@ let config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ let config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -37,4 +37,6 @@ let config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,13 +13,14 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: []
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,13 +13,14 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
modules: [
|
modules: []
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -13,11 +13,12 @@ var config = {
|
||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
if (typeof module !== "undefined") {module.exports = config;}
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ const expect = require("chai").expect;
|
||||||
const describe = global.describe;
|
const describe = global.describe;
|
||||||
const it = global.it;
|
const it = global.it;
|
||||||
|
|
||||||
describe("Development console tests", function() {
|
describe("Development console tests", function () {
|
||||||
// FIXME: This tests fail and crash another tests
|
// FIXME: This tests fail and crash another tests
|
||||||
// Suspect problem with window focus
|
// Suspect problem with window focus
|
||||||
return false;
|
return false;
|
||||||
|
@ -14,47 +14,47 @@ describe("Development console tests", function() {
|
||||||
|
|
||||||
var app = null;
|
var app = null;
|
||||||
|
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/env.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/env.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Without 'dev' commandline argument", function() {
|
describe("Without 'dev' commandline argument", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
return helpers
|
return helpers
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function() {
|
after(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not open dev console when absent", function() {
|
it("should not open dev console when absent", function () {
|
||||||
return expect(app.browserWindow.isDevToolsOpened()).to.eventually.equal(false);
|
return expect(app.browserWindow.isDevToolsOpened()).to.eventually.equal(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("With 'dev' commandline argument", function() {
|
describe("With 'dev' commandline argument", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
return helpers
|
return helpers
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js", "dev"]
|
args: ["js/electron.js", "dev"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function() {
|
after(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should open dev console when provided", function() {
|
it("should open dev console when provided", function () {
|
||||||
return expect(app.browserWindow.isDevToolsOpened()).to.eventually.equal(true);
|
return expect(app.browserWindow.isDevToolsOpened()).to.eventually.equal(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,32 +7,33 @@ const it = global.it;
|
||||||
const beforeEach = global.beforeEach;
|
const beforeEach = global.beforeEach;
|
||||||
const afterEach = global.afterEach;
|
const afterEach = global.afterEach;
|
||||||
|
|
||||||
describe("Electron app environment", function() {
|
describe("Electron app environment", function () {
|
||||||
helpers.setupTimeout(this);
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
var app = null;
|
var app = null;
|
||||||
|
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/env.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/env.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function () {
|
||||||
return helpers
|
return helpers
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should open a browserwindow", function() {
|
it("should open a browserwindow", function () {
|
||||||
return app.client
|
return (
|
||||||
|
app.client
|
||||||
.waitUntilWindowLoaded()
|
.waitUntilWindowLoaded()
|
||||||
// .browserWindow.focus()
|
// .browserWindow.focus()
|
||||||
.getWindowCount()
|
.getWindowCount()
|
||||||
|
@ -48,18 +49,19 @@ describe("Electron app environment", function() {
|
||||||
.should.eventually.have.property("height")
|
.should.eventually.have.property("height")
|
||||||
.and.be.above(0)
|
.and.be.above(0)
|
||||||
.browserWindow.getTitle()
|
.browserWindow.getTitle()
|
||||||
.should.eventually.equal("MagicMirror²");
|
.should.eventually.equal("MagicMirror²")
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("get request from http://localhost:8080 should return 200", function(done) {
|
it("get request from http://localhost:8080 should return 200", function (done) {
|
||||||
request.get("http://localhost:8080", function(err, res, body) {
|
request.get("http://localhost:8080", function (err, res, body) {
|
||||||
expect(res.statusCode).to.equal(200);
|
expect(res.statusCode).to.equal(200);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("get request from http://localhost:8080/nothing should return 404", function(done) {
|
it("get request from http://localhost:8080/nothing should return 404", function (done) {
|
||||||
request.get("http://localhost:8080/nothing", function(err, res, body) {
|
request.get("http://localhost:8080/nothing", function (err, res, body) {
|
||||||
expect(res.statusCode).to.equal(404);
|
expect(res.statusCode).to.equal(404);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const forEach = require("mocha-each");
|
||||||
|
|
||||||
const describe = global.describe;
|
const describe = global.describe;
|
||||||
|
|
||||||
describe("All font files from roboto.css should be downloadable", function() {
|
describe("All font files from roboto.css should be downloadable", function () {
|
||||||
helpers.setupTimeout(this);
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
var app;
|
var app;
|
||||||
|
@ -21,7 +21,7 @@ describe("All font files from roboto.css should be downloadable", function() {
|
||||||
match = regex.exec(fileContent);
|
match = regex.exec(fileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/without_modules.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/without_modules.js";
|
||||||
|
|
||||||
|
@ -29,18 +29,18 @@ describe("All font files from roboto.css should be downloadable", function() {
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function() {
|
after(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
forEach(fontFiles).it("should return 200 HTTP code for file '%s'", (fontFile, done) => {
|
forEach(fontFiles).it("should return 200 HTTP code for file '%s'", (fontFile, done) => {
|
||||||
var fontUrl = "http://localhost:8080/fonts/" + fontFile;
|
var fontUrl = "http://localhost:8080/fonts/" + fontFile;
|
||||||
request.get(fontUrl, function(err, res, body) {
|
request.get(fontUrl, function (err, res, body) {
|
||||||
expect(res.statusCode).to.equal(200);
|
expect(res.statusCode).to.equal(200);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Application = require("spectron").Application;
|
const Application = require("spectron").Application;
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
|
@ -14,12 +14,12 @@ const chai = require("chai");
|
||||||
const chaiAsPromised = require("chai-as-promised");
|
const chaiAsPromised = require("chai-as-promised");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
global.before(function() {
|
global.before(function () {
|
||||||
chai.should();
|
chai.should();
|
||||||
chai.use(chaiAsPromised);
|
chai.use(chaiAsPromised);
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.getElectronPath = function() {
|
exports.getElectronPath = function () {
|
||||||
var electronPath = path.join(__dirname, "..", "..", "node_modules", ".bin", "electron");
|
var electronPath = path.join(__dirname, "..", "..", "node_modules", ".bin", "electron");
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
electronPath += ".cmd";
|
electronPath += ".cmd";
|
||||||
|
@ -28,7 +28,7 @@ exports.getElectronPath = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set timeout - if this is run within Travis, increase timeout
|
// Set timeout - if this is run within Travis, increase timeout
|
||||||
exports.setupTimeout = function(test) {
|
exports.setupTimeout = function (test) {
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
test.timeout(30000);
|
test.timeout(30000);
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,26 +36,26 @@ exports.setupTimeout = function(test) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.startApplication = function(options) {
|
exports.startApplication = function (options) {
|
||||||
options.path = exports.getElectronPath();
|
options.path = exports.getElectronPath();
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
options.startTimeout = 30000;
|
options.startTimeout = 30000;
|
||||||
}
|
}
|
||||||
|
|
||||||
var app = new Application(options);
|
var app = new Application(options);
|
||||||
return app.start().then(function() {
|
return app.start().then(function () {
|
||||||
assert.equal(app.isRunning(), true);
|
assert.equal(app.isRunning(), true);
|
||||||
chaiAsPromised.transferPromiseness = app.transferPromiseness;
|
chaiAsPromised.transferPromiseness = app.transferPromiseness;
|
||||||
return app;
|
return app;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.stopApplication = function(app) {
|
exports.stopApplication = function (app) {
|
||||||
if (!app || !app.isRunning()) {
|
if (!app || !app.isRunning()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return app.stop().then(function() {
|
return app.stop().then(function () {
|
||||||
assert.equal(app.isRunning(), false);
|
assert.equal(app.isRunning(), false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,9 +13,13 @@ describe("ipWhitelist directive configuration", function () {
|
||||||
var app = null;
|
var app = null;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
return helpers.startApplication({
|
return helpers
|
||||||
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
}).then(function (startedApp) { app = startedApp; });
|
})
|
||||||
|
.then(function (startedApp) {
|
||||||
|
app = startedApp;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
@ -47,5 +51,4 @@ describe("ipWhitelist directive configuration", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,96 +6,96 @@ const it = global.it;
|
||||||
const beforeEach = global.beforeEach;
|
const beforeEach = global.beforeEach;
|
||||||
const afterEach = global.afterEach;
|
const afterEach = global.afterEach;
|
||||||
|
|
||||||
describe("Calendar module", function() {
|
describe("Calendar module", function () {
|
||||||
helpers.setupTimeout(this);
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
var app = null;
|
var app = null;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function () {
|
||||||
return helpers
|
return helpers
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Default configuration", function() {
|
describe("Default configuration", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/default.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/default.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should return TestEvents", function() {
|
it("Should return TestEvents", function () {
|
||||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Basic auth", function() {
|
describe("Basic auth", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
serverBasicAuth.listen(8010);
|
serverBasicAuth.listen(8010);
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/basic-auth.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/basic-auth.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function(done) {
|
after(function (done) {
|
||||||
serverBasicAuth.close(done());
|
serverBasicAuth.close(done());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should return TestEvents", function() {
|
it("Should return TestEvents", function () {
|
||||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Basic auth by default", function() {
|
describe("Basic auth by default", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
serverBasicAuth.listen(8011);
|
serverBasicAuth.listen(8011);
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/auth-default.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/auth-default.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function(done) {
|
after(function (done) {
|
||||||
serverBasicAuth.close(done());
|
serverBasicAuth.close(done());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should return TestEvents", function() {
|
it("Should return TestEvents", function () {
|
||||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Basic auth backward compatibility configuration: DEPRECATED", function() {
|
describe("Basic auth backward compatibility configuration: DEPRECATED", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
serverBasicAuth.listen(8012);
|
serverBasicAuth.listen(8012);
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/old-basic-auth.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/old-basic-auth.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function(done) {
|
after(function (done) {
|
||||||
serverBasicAuth.close(done());
|
serverBasicAuth.close(done());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should return TestEvents", function() {
|
it("Should return TestEvents", function () {
|
||||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Fail Basic auth", function() {
|
describe("Fail Basic auth", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
serverBasicAuth.listen(8020);
|
serverBasicAuth.listen(8020);
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/fail-basic-auth.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/fail-basic-auth.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function(done) {
|
after(function (done) {
|
||||||
serverBasicAuth.close(done());
|
serverBasicAuth.close(done());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should return No upcoming events", function() {
|
it("Should return No upcoming events", function () {
|
||||||
return app.client.waitUntilTextExists(".calendar", "No upcoming events.", 10000);
|
return app.client.waitUntilTextExists(".calendar", "No upcoming events.", 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,81 +5,80 @@ const it = global.it;
|
||||||
const beforeEach = global.beforeEach;
|
const beforeEach = global.beforeEach;
|
||||||
const afterEach = global.afterEach;
|
const afterEach = global.afterEach;
|
||||||
|
|
||||||
describe("Clock set to spanish language module", function() {
|
describe("Clock set to spanish language module", function () {
|
||||||
helpers.setupTimeout(this);
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
var app = null;
|
var app = null;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function () {
|
||||||
return helpers
|
return helpers
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with default 24hr clock config", function() {
|
describe("with default 24hr clock config", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_24hr.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_24hr.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows date with correct format", function() {
|
it("shows date with correct format", function () {
|
||||||
const dateRegex = /^(?:lunes|martes|miércoles|jueves|viernes|sábado|domingo), \d{1,2} de (?:enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre) de \d{4}$/;
|
const dateRegex = /^(?:lunes|martes|miércoles|jueves|viernes|sábado|domingo), \d{1,2} de (?:enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre) de \d{4}$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows time in 24hr format", function() {
|
it("shows time in 24hr format", function () {
|
||||||
const timeRegex = /^(?:2[0-3]|[01]\d):[0-5]\d[0-5]\d$/;
|
const timeRegex = /^(?:2[0-3]|[01]\d):[0-5]\d[0-5]\d$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with default 12hr clock config", function() {
|
describe("with default 12hr clock config", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_12hr.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_12hr.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows date with correct format", function() {
|
it("shows date with correct format", function () {
|
||||||
const dateRegex = /^(?:lunes|martes|miércoles|jueves|viernes|sábado|domingo), \d{1,2} de (?:enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre) de \d{4}$/;
|
const dateRegex = /^(?:lunes|martes|miércoles|jueves|viernes|sábado|domingo), \d{1,2} de (?:enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre) de \d{4}$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows time in 12hr format", function() {
|
it("shows time in 12hr format", function () {
|
||||||
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[ap]m$/;
|
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[ap]m$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with showPeriodUpper config enabled", function() {
|
describe("with showPeriodUpper config enabled", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_showPeriodUpper.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_showPeriodUpper.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows 12hr time with upper case AM/PM", function() {
|
it("shows 12hr time with upper case AM/PM", function () {
|
||||||
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[AP]M$/;
|
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[AP]M$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with showWeek config enabled", function() {
|
describe("with showWeek config enabled", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_showWeek.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_showWeek.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows week with correct format", function() {
|
it("shows week with correct format", function () {
|
||||||
const weekRegex = /^Semana [0-9]{1,2}$/;
|
const weekRegex = /^Semana [0-9]{1,2}$/;
|
||||||
return app.client.waitUntilWindowLoaded()
|
return app.client.waitUntilWindowLoaded().getText(".clock .week").should.eventually.match(weekRegex);
|
||||||
.getText(".clock .week").should.eventually.match(weekRegex);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,95 +5,95 @@ const it = global.it;
|
||||||
const beforeEach = global.beforeEach;
|
const beforeEach = global.beforeEach;
|
||||||
const afterEach = global.afterEach;
|
const afterEach = global.afterEach;
|
||||||
|
|
||||||
describe("Clock module", function() {
|
describe("Clock module", function () {
|
||||||
helpers.setupTimeout(this);
|
helpers.setupTimeout(this);
|
||||||
|
|
||||||
var app = null;
|
var app = null;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function () {
|
||||||
return helpers
|
return helpers
|
||||||
.startApplication({
|
.startApplication({
|
||||||
args: ["js/electron.js"]
|
args: ["js/electron.js"]
|
||||||
})
|
})
|
||||||
.then(function(startedApp) {
|
.then(function (startedApp) {
|
||||||
app = startedApp;
|
app = startedApp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function () {
|
||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with default 24hr clock config", function() {
|
describe("with default 24hr clock config", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_24hr.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_24hr.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows date with correct format", function() {
|
it("shows date with correct format", function () {
|
||||||
const dateRegex = /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4}$/;
|
const dateRegex = /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4}$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows time in 24hr format", function() {
|
it("shows time in 24hr format", function () {
|
||||||
const timeRegex = /^(?:2[0-3]|[01]\d):[0-5]\d[0-5]\d$/;
|
const timeRegex = /^(?:2[0-3]|[01]\d):[0-5]\d[0-5]\d$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with default 12hr clock config", function() {
|
describe("with default 12hr clock config", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_12hr.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_12hr.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows date with correct format", function() {
|
it("shows date with correct format", function () {
|
||||||
const dateRegex = /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4}$/;
|
const dateRegex = /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4}$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows time in 12hr format", function() {
|
it("shows time in 12hr format", function () {
|
||||||
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[ap]m$/;
|
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[ap]m$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with showPeriodUpper config enabled", function() {
|
describe("with showPeriodUpper config enabled", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_showPeriodUpper.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_showPeriodUpper.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows 12hr time with upper case AM/PM", function() {
|
it("shows 12hr time with upper case AM/PM", function () {
|
||||||
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[AP]M$/;
|
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[AP]M$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with displaySeconds config disabled", function() {
|
describe("with displaySeconds config disabled", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_displaySeconds_false.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_displaySeconds_false.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows 12hr time without seconds am/pm", function() {
|
it("shows 12hr time without seconds am/pm", function () {
|
||||||
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[ap]m$/;
|
const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[ap]m$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("with showWeek config enabled", function() {
|
describe("with showWeek config enabled", function () {
|
||||||
before(function() {
|
before(function () {
|
||||||
// Set config sample for use in test
|
// Set config sample for use in test
|
||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_showWeek.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/clock_showWeek.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows week with correct format", function() {
|
it("shows week with correct format", function () {
|
||||||
const weekRegex = /^Week [0-9]{1,2}$/;
|
const weekRegex = /^Week [0-9]{1,2}$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .week").should.eventually.match(weekRegex);
|
return app.client.waitUntilWindowLoaded().getText(".clock .week").should.eventually.match(weekRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows week with correct number of week of year", function() {
|
it("shows week with correct number of week of year", function () {
|
||||||
it("FIXME: if the day is a sunday this not match");
|
it("FIXME: if the day is a sunday this not match");
|
||||||
// const currentWeekNumber = require("current-week-number")();
|
// const currentWeekNumber = require("current-week-number")();
|
||||||
// const weekToShow = "Week " + currentWeekNumber;
|
// const weekToShow = "Week " + currentWeekNumber;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue