mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-07-03 14:26:07 +00:00
Merge branch 'master' of https://github.com/MystaraTheGreat/MagicMirror
This commit is contained in:
commit
b72556b9a9
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@ -6,6 +6,8 @@ If you're not sure if it's a real bug or if it's just you, please open a topic o
|
|||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
A common problem is that your config file could be invalid. Please run in your MagicMirror directory: `npm run config:check` and see if it reports an error.
|
||||||
|
|
||||||
## 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:
|
||||||
@ -23,9 +25,9 @@ If you are facing an issue or found a bug while running MagicMirror inside a Doc
|
|||||||
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/4, Windows, Mac, Linux, System V UNIX).
|
||||||
|
|
||||||
**Node Version**: Make sure it's version 8 or later.
|
**Node Version**: Make sure it's version 10 or later.
|
||||||
|
|
||||||
**MagicMirror Version**: Please let us now which version of MagicMirror you are running. It can be found in the `package.log` file.
|
**MagicMirror Version**: Please let us now which version of MagicMirror you are running. It can be found in the `package.log` file.
|
||||||
|
|
||||||
|
24
.github/workflows/codecov-test-suites.yml
vendored
Normal file
24
.github/workflows/codecov-test-suites.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# This workflow runs the automated test and uploads the coverage results to codecov.io
|
||||||
|
|
||||||
|
name: "Run Codecov Tests"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master, develop ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master, develop ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-and-upload-coverage-report:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
Xvfb :99 -screen 0 1024x768x16 &
|
||||||
|
export DISPLAY=:99
|
||||||
|
npm ci
|
||||||
|
npm run test:coverage
|
||||||
|
- uses: codecov/codecov-action@v1
|
||||||
|
with:
|
||||||
|
file: ./coverage/lcov.info
|
||||||
|
fail_ci_if_error: true
|
4
.github/workflows/enforce-changelog.yml
vendored
4
.github/workflows/enforce-changelog.yml
vendored
@ -1,10 +1,12 @@
|
|||||||
|
# This workflow enforces the update of a changelog file on every pull request
|
||||||
|
|
||||||
name: "Enforce Changelog"
|
name: "Enforce Changelog"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
|
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Enforces the update of a changelog file on every pull request
|
|
||||||
check:
|
check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
5
.github/workflows/node-ci.js.yml
vendored
5
.github/workflows/node-ci.js.yml
vendored
@ -1,7 +1,7 @@
|
|||||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
name: Automated Tests
|
name: "Run Automated Tests"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -11,13 +11,10 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [10.x, 12.x, 14.x]
|
node-version: [10.x, 12.x, 14.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
48
CHANGELOG.md
48
CHANGELOG.md
@ -5,11 +5,54 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|||||||
|
|
||||||
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror²
|
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror²
|
||||||
|
|
||||||
## [2.14.1] - 2021-03-07
|
## [2.15.0] - Unreleased (Develop Branch)
|
||||||
|
|
||||||
|
_This release is scheduled to be released on 2021-04-01._
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- @MystaraTheGreat added hiddenOnStartup flag to module config (#2475)
|
- Added GitHub workflows for automated testing and changelog enforcement.
|
||||||
|
- Added CodeCov badge to Readme.
|
||||||
|
- Added CURRENTWEATHER_TYPE notification to currentweather and weather module, use it in compliments module.
|
||||||
|
- Added `start:dev` command to the npm scripts for starting electron with devTools open.
|
||||||
|
- Added logging when using deprecated modules weatherforecast or currentweather.
|
||||||
|
- Portuguese translations for "MODULE_CONFIG_CHANGED" and PRECIP.
|
||||||
|
- Respect parameter ColoredSymbolOnly also for custom events
|
||||||
|
- Added a new parameter to hide time portion on relative times
|
||||||
|
- `module.show` has now the option for a callback on error.
|
||||||
|
- Added locale to sample config file
|
||||||
|
- Added support for self-signed certificates for the default calendar module (#466)
|
||||||
|
- Added hiddenOnStartup flag to module config (#2475)
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Updated markdown files.
|
||||||
|
- Cleaned up old code on server side.
|
||||||
|
- Convert `-0` to `0` when displaying temperature.
|
||||||
|
- Code cleanup for FEELS like and added {DEGREE} placeholder for FEELSLIKE for each language
|
||||||
|
- Converted newsfeed module to use templates.
|
||||||
|
- Update documentation and help screen about invalid config files.
|
||||||
|
- Moving weather provider specific code and configuration into each provider and making hourly part of the interface.
|
||||||
|
- Bump electron to v11 and enable contextIsolation.
|
||||||
|
- Dont update the DOM when a module is not displayed.
|
||||||
|
- Cleaned up jsdoc and tests.
|
||||||
|
- Exposed logger as node module for easier access for 3rd party modules
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed danger.js library.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Added default log levels to stop calendar log spamming.
|
||||||
|
- Fix socket.io cors errors, see [breaking change since socket.io v3](https://socket.io/docs/v3/handling-cors/)
|
||||||
|
- Fix Issue with weather forecast icons due to fixed day start and end time (#2221)
|
||||||
|
- Fix empty directory for each module's main javascript file in the inspector
|
||||||
|
- Fix Issue with weather forecast icons unit tests with different timezones (#2221)
|
||||||
|
- Fix issue with unencoded characters in translated strings when using nunjuck template (`Loading …` as an example)
|
||||||
|
- Fix socket.io backward compatibility with socket v2 clients
|
||||||
|
- 3rd party module language loading if language is English
|
||||||
|
- Fix e2e tests after spectron update
|
||||||
|
|
||||||
## [2.14.0] - 2021-01-01
|
## [2.14.0] - 2021-01-01
|
||||||
|
|
||||||
@ -31,7 +74,6 @@ Special thanks to the following contributors: @Alvinger, @AndyPoms, @ashishtank,
|
|||||||
- Calendar: new options "limitDays" and "coloredEvents".
|
- Calendar: new options "limitDays" and "coloredEvents".
|
||||||
- Added new option "limitDays" - limit the number of discreet days displayed.
|
- Added new option "limitDays" - limit the number of discreet days displayed.
|
||||||
- Added new option "customEvents" - use custom symbol/color based on keyword in event title.
|
- Added new option "customEvents" - use custom symbol/color based on keyword in event title.
|
||||||
- Added GitHub workflows for automated testing and changelog enforcement.
|
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
|
|
||||||
Copyright © 2016-2020 Michael Teeuw
|
Copyright © 2016-2021 Michael Teeuw
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||

|

|
||||||
|
|
||||||
<p align="center">
|
<p style="text-align: center">
|
||||||
<a href="https://david-dm.org/MichMich/MagicMirror"><img src="https://david-dm.org/MichMich/MagicMirror.svg" alt="Dependency Status"></a>
|
<a href="https://david-dm.org/MichMich/MagicMirror"><img src="https://david-dm.org/MichMich/MagicMirror.svg" alt="Dependency Status"></a>
|
||||||
<a href="https://david-dm.org/MichMich/MagicMirror#info=devDependencies"><img src="https://david-dm.org/MichMich/MagicMirror/dev-status.svg" alt="devDependency Status"></a>
|
<a href="https://david-dm.org/MichMich/MagicMirror#info=devDependencies"><img src="https://david-dm.org/MichMich/MagicMirror/dev-status.svg" alt="devDependency Status"></a>
|
||||||
<a href="https://bestpractices.coreinfrastructure.org/projects/347"><img src="https://bestpractices.coreinfrastructure.org/projects/347/badge"></a>
|
<a href="https://bestpractices.coreinfrastructure.org/projects/347"><img src="https://bestpractices.coreinfrastructure.org/projects/347/badge" alt="CLI Best Practices"></a>
|
||||||
|
<a href="https://codecov.io/gh/MichMich/MagicMirror"><img src="https://codecov.io/gh/MichMich/MagicMirror/branch/master/graph/badge.svg?token=LEG1KitZR6"/></a>
|
||||||
<a href="https://choosealicense.com/licenses/mit"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
|
<a href="https://choosealicense.com/licenses/mit"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
|
||||||
<a href="https://github.com/MichMich/MagicMirror/actions?query=workflow%3A%22Automated+Tests%22"><img src="https://github.com/MichMich/MagicMirror/workflows/Automated%20Tests/badge.svg" alt="Tests"></a>
|
<a href="https://github.com/MichMich/MagicMirror/actions?query=workflow%3A%22Automated+Tests%22"><img src="https://github.com/MichMich/MagicMirror/workflows/Automated%20Tests/badge.svg" alt="Tests"></a>
|
||||||
</p>
|
</p>
|
||||||
@ -38,7 +39,6 @@ If we receive enough donations we might even be able to free up some working hou
|
|||||||
|
|
||||||
To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.
|
To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.
|
||||||
|
|
||||||
<p align="center">
|
<p style="text-align: center">
|
||||||
<br>
|
|
||||||
<a href="https://forum.magicmirror.builders/topic/728/magicmirror-is-voted-number-1-in-the-magpi-top-50"><img src="https://magicmirror.builders/img/magpi-best-watermark-custom.png" width="150" alt="MagPi Top 50"></a>
|
<a href="https://forum.magicmirror.builders/topic/728/magicmirror-is-voted-number-1-in-the-magpi-top-50"><img src="https://magicmirror.builders/img/magpi-best-watermark-custom.png" width="150" alt="MagPi Top 50"></a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
*
|
*
|
||||||
* @param {string} key key to look for at the command line
|
* @param {string} key key to look for at the command line
|
||||||
* @param {string} defaultValue value if no key is given at the command line
|
* @param {string} defaultValue value if no key is given at the command line
|
||||||
*
|
|
||||||
* @returns {string} the value of the parameter
|
* @returns {string} the value of the parameter
|
||||||
*/
|
*/
|
||||||
function getCommandLineParameter(key, defaultValue = undefined) {
|
function getCommandLineParameter(key, defaultValue = undefined) {
|
||||||
@ -36,7 +35,6 @@
|
|||||||
* Gets the config from the specified server url
|
* Gets the config from the specified server url
|
||||||
*
|
*
|
||||||
* @param {string} url location where the server is running.
|
* @param {string} url location where the server is running.
|
||||||
*
|
|
||||||
* @returns {Promise} the config
|
* @returns {Promise} the config
|
||||||
*/
|
*/
|
||||||
function getServerConfig(url) {
|
function getServerConfig(url) {
|
||||||
@ -66,7 +64,7 @@
|
|||||||
/**
|
/**
|
||||||
* Print a message to the console in case of errors
|
* Print a message to the console in case of errors
|
||||||
*
|
*
|
||||||
* @param {string} [message] error message to print
|
* @param {string} message error message to print
|
||||||
* @param {number} code error code for the exit call
|
* @param {number} code error code for the exit call
|
||||||
*/
|
*/
|
||||||
function fail(message, code = 1) {
|
function fail(message, code = 1) {
|
||||||
|
@ -28,6 +28,7 @@ var config = {
|
|||||||
httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true
|
httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true
|
||||||
|
|
||||||
language: "en",
|
language: "en",
|
||||||
|
locale: "en-US",
|
||||||
logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging
|
logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging
|
||||||
timeFormat: 24,
|
timeFormat: 24,
|
||||||
units: "metric",
|
units: "metric",
|
||||||
@ -66,22 +67,26 @@ var config = {
|
|||||||
position: "lower_third"
|
position: "lower_third"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
module: "currentweather",
|
module: "weather",
|
||||||
position: "top_right",
|
position: "top_right",
|
||||||
config: {
|
config: {
|
||||||
|
weatherProvider: "openweathermap",
|
||||||
|
type: "current",
|
||||||
location: "New York",
|
location: "New York",
|
||||||
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
||||||
appid: "YOUR_OPENWEATHER_API_KEY"
|
apiKey: "YOUR_OPENWEATHER_API_KEY"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
module: "weatherforecast",
|
module: "weather",
|
||||||
position: "top_right",
|
position: "top_right",
|
||||||
header: "Weather Forecast",
|
header: "Weather Forecast",
|
||||||
config: {
|
config: {
|
||||||
|
weatherProvider: "openweathermap",
|
||||||
|
type: "forecast",
|
||||||
location: "New York",
|
location: "New York",
|
||||||
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
||||||
appid: "YOUR_OPENWEATHER_API_KEY"
|
apiKey: "YOUR_OPENWEATHER_API_KEY"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
import { danger, fail, warn } from "danger";
|
|
||||||
|
|
||||||
// Check if the CHANGELOG.md file has been edited
|
|
||||||
// Fail the build and post a comment reminding submitters to do so if it wasn't changed
|
|
||||||
if (!danger.git.modified_files.includes("CHANGELOG.md")) {
|
|
||||||
warn("Please include an updated `CHANGELOG.md` file.<br>This way we can keep track of all the contributions.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the PR request is send to the master branch.
|
|
||||||
// This should only be done by MichMich.
|
|
||||||
if (danger.github.pr.base.ref === "master" && danger.github.pr.user.login !== "MichMich") {
|
|
||||||
// Check if the PR body or title includes the text: #accepted.
|
|
||||||
// If not, the PR will fail.
|
|
||||||
if ((danger.github.pr.body + danger.github.pr.title).includes("#accepted")) {
|
|
||||||
fail("Please send all your pull requests to the `develop` branch.<br>Pull requests on the `master` branch will not be accepted.");
|
|
||||||
}
|
|
||||||
}
|
|
130
js/app.js
130
js/app.js
@ -4,22 +4,23 @@
|
|||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var fs = require("fs");
|
|
||||||
var path = require("path");
|
|
||||||
var Log = require(__dirname + "/logger.js");
|
|
||||||
var Server = require(__dirname + "/server.js");
|
|
||||||
var Utils = require(__dirname + "/utils.js");
|
|
||||||
var defaultModules = require(__dirname + "/../modules/default/defaultmodules.js");
|
|
||||||
|
|
||||||
// Alias modules mentioned in package.js under _moduleAliases.
|
// Alias modules mentioned in package.js under _moduleAliases.
|
||||||
require("module-alias/register");
|
require("module-alias/register");
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const Log = require("logger");
|
||||||
|
const Server = require(`${__dirname}/server`);
|
||||||
|
const Utils = require(`${__dirname}/utils`);
|
||||||
|
const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`);
|
||||||
|
|
||||||
// Get version number.
|
// Get version number.
|
||||||
global.version = JSON.parse(fs.readFileSync("package.json", "utf8")).version;
|
global.version = require(`${__dirname}/../package.json`).version;
|
||||||
Log.log("Starting MagicMirror: v" + global.version);
|
Log.log("Starting MagicMirror: v" + global.version);
|
||||||
|
|
||||||
// global absolute root path
|
// global absolute root path
|
||||||
global.root_path = path.resolve(__dirname + "/../");
|
global.root_path = path.resolve(`${__dirname}/../`);
|
||||||
|
|
||||||
if (process.env.MM_CONFIG_FILE) {
|
if (process.env.MM_CONFIG_FILE) {
|
||||||
global.configuration_file = process.env.MM_CONFIG_FILE;
|
global.configuration_file = process.env.MM_CONFIG_FILE;
|
||||||
@ -45,8 +46,8 @@ process.on("uncaughtException", function (err) {
|
|||||||
*
|
*
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
var App = function () {
|
function App() {
|
||||||
var nodeHelpers = [];
|
let nodeHelpers = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the config file. Combines it with the defaults, and runs the
|
* Loads the config file. Combines it with the defaults, and runs the
|
||||||
@ -54,34 +55,31 @@ var App = function () {
|
|||||||
*
|
*
|
||||||
* @param {Function} callback Function to be called after loading the config
|
* @param {Function} callback Function to be called after loading the config
|
||||||
*/
|
*/
|
||||||
var loadConfig = function (callback) {
|
function loadConfig(callback) {
|
||||||
Log.log("Loading config ...");
|
Log.log("Loading config ...");
|
||||||
var defaults = require(__dirname + "/defaults.js");
|
const defaults = require(`${__dirname}/defaults`);
|
||||||
|
|
||||||
// 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");
|
const configFilename = path.resolve(global.configuration_file || `${global.root_path}/config/config.js`);
|
||||||
if (typeof global.configuration_file !== "undefined") {
|
|
||||||
configFilename = path.resolve(global.configuration_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.accessSync(configFilename, fs.F_OK);
|
fs.accessSync(configFilename, fs.F_OK);
|
||||||
var c = require(configFilename);
|
const c = require(configFilename);
|
||||||
checkDeprecatedOptions(c);
|
checkDeprecatedOptions(c);
|
||||||
var config = Object.assign(defaults, c);
|
const config = Object.assign(defaults, c);
|
||||||
callback(config);
|
callback(config);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === "ENOENT") {
|
if (e.code === "ENOENT") {
|
||||||
Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
|
Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
|
||||||
} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
|
} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
|
||||||
Log.error(Utils.colors.error("WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: " + e.stack));
|
Log.error(Utils.colors.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`));
|
||||||
} else {
|
} else {
|
||||||
Log.error(Utils.colors.error("WARNING! Could not load config file. Starting with default configuration. Error found: " + e));
|
Log.error(Utils.colors.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`));
|
||||||
}
|
}
|
||||||
callback(defaults);
|
callback(defaults);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the config for deprecated options and throws a warning in the logs
|
* Checks the config for deprecated options and throws a warning in the logs
|
||||||
@ -89,21 +87,15 @@ var App = function () {
|
|||||||
*
|
*
|
||||||
* @param {object} userConfig The user config
|
* @param {object} userConfig The user config
|
||||||
*/
|
*/
|
||||||
var checkDeprecatedOptions = function (userConfig) {
|
function checkDeprecatedOptions(userConfig) {
|
||||||
var deprecated = require(global.root_path + "/js/deprecated.js");
|
const deprecated = require(`${global.root_path}/js/deprecated`);
|
||||||
var deprecatedOptions = deprecated.configs;
|
const deprecatedOptions = deprecated.configs;
|
||||||
|
|
||||||
var usedDeprecated = [];
|
const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option));
|
||||||
|
|
||||||
deprecatedOptions.forEach(function (option) {
|
|
||||||
if (userConfig.hasOwnProperty(option)) {
|
|
||||||
usedDeprecated.push(option);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (usedDeprecated.length > 0) {
|
if (usedDeprecated.length > 0) {
|
||||||
Log.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."));
|
Log.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.`));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a specific module.
|
* Loads a specific module.
|
||||||
@ -111,35 +103,35 @@ var App = function () {
|
|||||||
* @param {string} module The name of the module (including subpath).
|
* @param {string} module The name of the module (including subpath).
|
||||||
* @param {Function} callback Function to be called after loading
|
* @param {Function} callback Function to be called after loading
|
||||||
*/
|
*/
|
||||||
var loadModule = function (module, callback) {
|
function loadModule(module, callback) {
|
||||||
var elements = module.split("/");
|
const elements = module.split("/");
|
||||||
var moduleName = elements[elements.length - 1];
|
const moduleName = elements[elements.length - 1];
|
||||||
var moduleFolder = __dirname + "/../modules/" + module;
|
let moduleFolder = `${__dirname}/../modules/${module}`;
|
||||||
|
|
||||||
if (defaultModules.indexOf(moduleName) !== -1) {
|
if (defaultModules.includes(moduleName)) {
|
||||||
moduleFolder = __dirname + "/../modules/default/" + module;
|
moduleFolder = `${__dirname}/../modules/default/${module}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
var helperPath = moduleFolder + "/node_helper.js";
|
const helperPath = `${moduleFolder}/node_helper.js`;
|
||||||
|
|
||||||
var loadModule = true;
|
let loadHelper = true;
|
||||||
try {
|
try {
|
||||||
fs.accessSync(helperPath, fs.R_OK);
|
fs.accessSync(helperPath, fs.R_OK);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
loadModule = false;
|
loadHelper = false;
|
||||||
Log.log("No helper found for module: " + moduleName + ".");
|
Log.log(`No helper found for module: ${moduleName}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadModule) {
|
if (loadHelper) {
|
||||||
var Module = require(helperPath);
|
const Module = require(helperPath);
|
||||||
var m = new Module();
|
let m = new Module();
|
||||||
|
|
||||||
if (m.requiresVersion) {
|
if (m.requiresVersion) {
|
||||||
Log.log("Check MagicMirror version for node helper '" + moduleName + "' - Minimum version: " + m.requiresVersion + " - Current version: " + global.version);
|
Log.log(`Check MagicMirror version for node helper '${moduleName}' - Minimum version: ${m.requiresVersion} - Current version: ${global.version}`);
|
||||||
if (cmpVersions(global.version, m.requiresVersion) >= 0) {
|
if (cmpVersions(global.version, m.requiresVersion) >= 0) {
|
||||||
Log.log("Version is ok!");
|
Log.log("Version is ok!");
|
||||||
} else {
|
} else {
|
||||||
Log.log("Version is incorrect. Skip module: '" + moduleName + "'");
|
Log.warn(`Version is incorrect. Skip module: '${moduleName}'`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +144,7 @@ var App = function () {
|
|||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all modules.
|
* Loads all modules.
|
||||||
@ -160,12 +152,15 @@ var App = function () {
|
|||||||
* @param {Module[]} modules All modules to be loaded
|
* @param {Module[]} modules All modules to be loaded
|
||||||
* @param {Function} callback Function to be called after loading
|
* @param {Function} callback Function to be called after loading
|
||||||
*/
|
*/
|
||||||
var loadModules = function (modules, callback) {
|
function loadModules(modules, callback) {
|
||||||
Log.log("Loading module helpers ...");
|
Log.log("Loading module helpers ...");
|
||||||
|
|
||||||
var loadNextModule = function () {
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function loadNextModule() {
|
||||||
if (modules.length > 0) {
|
if (modules.length > 0) {
|
||||||
var nextModule = modules[0];
|
const nextModule = modules[0];
|
||||||
loadModule(nextModule, function () {
|
loadModule(nextModule, function () {
|
||||||
modules = modules.slice(1);
|
modules = modules.slice(1);
|
||||||
loadNextModule();
|
loadNextModule();
|
||||||
@ -175,10 +170,10 @@ var App = function () {
|
|||||||
Log.log("All module helpers loaded.");
|
Log.log("All module helpers loaded.");
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
loadNextModule();
|
loadNextModule();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare two semantic version numbers and return the difference.
|
* Compare two semantic version numbers and return the difference.
|
||||||
@ -190,11 +185,11 @@ var App = function () {
|
|||||||
* number if a is smaller and 0 if they are the same
|
* number if a is smaller and 0 if they are the same
|
||||||
*/
|
*/
|
||||||
function cmpVersions(a, b) {
|
function cmpVersions(a, b) {
|
||||||
var i, diff;
|
let i, diff;
|
||||||
var regExStrip0 = /(\.0+)+$/;
|
const regExStrip0 = /(\.0+)+$/;
|
||||||
var segmentsA = a.replace(regExStrip0, "").split(".");
|
const segmentsA = a.replace(regExStrip0, "").split(".");
|
||||||
var segmentsB = b.replace(regExStrip0, "").split(".");
|
const segmentsB = b.replace(regExStrip0, "").split(".");
|
||||||
var l = Math.min(segmentsA.length, segmentsB.length);
|
const l = Math.min(segmentsA.length, segmentsB.length);
|
||||||
|
|
||||||
for (i = 0; i < l; i++) {
|
for (i = 0; i < l; i++) {
|
||||||
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
|
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
|
||||||
@ -219,21 +214,19 @@ var App = function () {
|
|||||||
|
|
||||||
Log.setLogLevel(config.logLevel);
|
Log.setLogLevel(config.logLevel);
|
||||||
|
|
||||||
var modules = [];
|
let modules = [];
|
||||||
|
|
||||||
for (var m in config.modules) {
|
for (const module of config.modules) {
|
||||||
var module = config.modules[m];
|
if (!modules.includes(module.module) && !module.disabled) {
|
||||||
if (modules.indexOf(module.module) === -1 && !module.disabled) {
|
|
||||||
modules.push(module.module);
|
modules.push(module.module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadModules(modules, function () {
|
loadModules(modules, function () {
|
||||||
var server = new Server(config, function (app, io) {
|
const server = new Server(config, function (app, io) {
|
||||||
Log.log("Server started ...");
|
Log.log("Server started ...");
|
||||||
|
|
||||||
for (var h in nodeHelpers) {
|
for (let nodeHelper of nodeHelpers) {
|
||||||
var nodeHelper = nodeHelpers[h];
|
|
||||||
nodeHelper.setExpressApp(app);
|
nodeHelper.setExpressApp(app);
|
||||||
nodeHelper.setSocketIO(io);
|
nodeHelper.setSocketIO(io);
|
||||||
nodeHelper.start();
|
nodeHelper.start();
|
||||||
@ -256,8 +249,7 @@ var App = function () {
|
|||||||
* Added to fix #1056
|
* Added to fix #1056
|
||||||
*/
|
*/
|
||||||
this.stop = function () {
|
this.stop = function () {
|
||||||
for (var h in nodeHelpers) {
|
for (const nodeHelper of nodeHelpers) {
|
||||||
var nodeHelper = nodeHelpers[h];
|
|
||||||
if (typeof nodeHelper.stop === "function") {
|
if (typeof nodeHelper.stop === "function") {
|
||||||
nodeHelper.stop();
|
nodeHelper.stop();
|
||||||
}
|
}
|
||||||
@ -292,6 +284,6 @@ var App = function () {
|
|||||||
this.stop();
|
this.stop();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = new App();
|
module.exports = new App();
|
||||||
|
@ -11,9 +11,9 @@ const linter = new Linter();
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
|
||||||
const rootPath = path.resolve(__dirname + "/../");
|
const rootPath = path.resolve(`${__dirname}/../`);
|
||||||
const Log = require(rootPath + "/js/logger.js");
|
const Log = require(`${rootPath}/js/logger.js`);
|
||||||
const Utils = require(rootPath + "/js/utils.js");
|
const Utils = require(`${rootPath}/js/utils.js`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string with path of configuration file.
|
* Returns a string with path of configuration file.
|
||||||
@ -23,11 +23,7 @@ const Utils = require(rootPath + "/js/utils.js");
|
|||||||
*/
|
*/
|
||||||
function getConfigFile() {
|
function getConfigFile() {
|
||||||
// FIXME: This function should be in core. Do you want refactor me ;) ?, be good!
|
// FIXME: This function should be in core. Do you want refactor me ;) ?, be good!
|
||||||
let configFileName = path.resolve(rootPath + "/config/config.js");
|
return path.resolve(process.env.MM_CONFIG_FILE || `${rootPath}/config/config.js`);
|
||||||
if (process.env.MM_CONFIG_FILE) {
|
|
||||||
configFileName = path.resolve(process.env.MM_CONFIG_FILE);
|
|
||||||
}
|
|
||||||
return configFileName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,21 +50,18 @@ function checkConfigFile() {
|
|||||||
Log.info(Utils.colors.info("Checking file... "), configFileName);
|
Log.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) {
|
const configFile = fs.readFileSync(configFileName, "utf-8");
|
||||||
if (err) {
|
|
||||||
throw err;
|
const errors = linter.verify(configFile);
|
||||||
}
|
if (errors.length === 0) {
|
||||||
const messages = linter.verify(data);
|
|
||||||
if (messages.length === 0) {
|
|
||||||
Log.info(Utils.colors.pass("Your configuration file doesn't contain syntax errors :)"));
|
Log.info(Utils.colors.pass("Your configuration file doesn't contain syntax errors :)"));
|
||||||
} else {
|
} else {
|
||||||
Log.error(Utils.colors.error("Your configuration file contains syntax errors :("));
|
Log.error(Utils.colors.error("Your configuration file contains syntax errors :("));
|
||||||
// In case the there errors show messages and return
|
|
||||||
messages.forEach((error) => {
|
for (const error of errors) {
|
||||||
Log.error("Line", error.line, "col", error.column, error.message);
|
Log.error(`Line ${error.line} column ${error.column}: ${error.message}`);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkConfigFile();
|
checkConfigFile();
|
||||||
|
@ -20,6 +20,7 @@ var defaults = {
|
|||||||
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
language: "en",
|
language: "en",
|
||||||
|
logLevel: ["INFO", "LOG", "WARN", "ERROR"],
|
||||||
timeFormat: 24,
|
timeFormat: 24,
|
||||||
units: "metric",
|
units: "metric",
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
@ -42,7 +43,7 @@ var defaults = {
|
|||||||
module: "helloworld",
|
module: "helloworld",
|
||||||
position: "middle_center",
|
position: "middle_center",
|
||||||
config: {
|
config: {
|
||||||
text: "Please create a config file."
|
text: "Please create a config file or check the existing one for errors."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -58,7 +59,7 @@ var defaults = {
|
|||||||
position: "middle_center",
|
position: "middle_center",
|
||||||
classes: "xsmall",
|
classes: "xsmall",
|
||||||
config: {
|
config: {
|
||||||
text: "If you get this message while your config file is already<br>created, your config file probably contains an error.<br>Use a JavaScript linter to validate your file."
|
text: "If you get this message while your config file is already created,<br>" + "it probably contains an error. To validate your config file run in your MagicMirror directory<br>" + "<pre>npm run config:check</pre>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -6,11 +6,6 @@
|
|||||||
* Olex S. original idea this deprecated option
|
* Olex S. original idea this deprecated option
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var deprecated = {
|
module.exports = {
|
||||||
configs: ["kioskmode"]
|
configs: ["kioskmode"]
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
|
||||||
if (typeof module !== "undefined") {
|
|
||||||
module.exports = deprecated;
|
|
||||||
}
|
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
const electron = require("electron");
|
const electron = require("electron");
|
||||||
const core = require("./app.js");
|
const core = require("./app.js");
|
||||||
const Log = require("./logger.js");
|
const Log = require("logger");
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
var config = process.env.config ? JSON.parse(process.env.config) : {};
|
let config = process.env.config ? JSON.parse(process.env.config) : {};
|
||||||
// Module to control application life.
|
// Module to control application life.
|
||||||
const app = electron.app;
|
const app = electron.app;
|
||||||
// Module to create native browser window.
|
// Module to create native browser window.
|
||||||
@ -20,13 +20,14 @@ let mainWindow;
|
|||||||
*/
|
*/
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
app.commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required");
|
app.commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required");
|
||||||
var electronOptionsDefaults = {
|
let electronOptionsDefaults = {
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
darkTheme: true,
|
darkTheme: true,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
|
contextIsolation: true,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
zoomFactor: config.zoom
|
zoomFactor: config.zoom
|
||||||
},
|
},
|
||||||
@ -42,7 +43,7 @@ function createWindow() {
|
|||||||
electronOptionsDefaults.autoHideMenuBar = true;
|
electronOptionsDefaults.autoHideMenuBar = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var electronOptions = Object.assign({}, electronOptionsDefaults, config.electronOptions);
|
const electronOptions = Object.assign({}, electronOptionsDefaults, config.electronOptions);
|
||||||
|
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
mainWindow = new BrowserWindow(electronOptions);
|
mainWindow = new BrowserWindow(electronOptions);
|
||||||
@ -50,14 +51,14 @@ function createWindow() {
|
|||||||
// and load the index.html of the app.
|
// and load the index.html of the app.
|
||||||
// If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost
|
// If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost
|
||||||
|
|
||||||
var prefix;
|
let prefix;
|
||||||
if (config["tls"] !== null && config["tls"]) {
|
if (config["tls"] !== null && config["tls"]) {
|
||||||
prefix = "https://";
|
prefix = "https://";
|
||||||
} else {
|
} else {
|
||||||
prefix = "http://";
|
prefix = "http://";
|
||||||
}
|
}
|
||||||
|
|
||||||
var address = (config.address === void 0) | (config.address === "") ? (config.address = "localhost") : config.address;
|
let address = (config.address === void 0) | (config.address === "") ? (config.address = "localhost") : config.address;
|
||||||
mainWindow.loadURL(`${prefix}${address}:${config.port}`);
|
mainWindow.loadURL(`${prefix}${address}:${config.port}`);
|
||||||
|
|
||||||
// Open the DevTools if run with "npm start dev"
|
// Open the DevTools if run with "npm start dev"
|
||||||
@ -125,7 +126,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].includes(config.address)) {
|
||||||
core.start(function (c) {
|
core.start(function (c) {
|
||||||
config = c;
|
config = c;
|
||||||
});
|
});
|
||||||
|
@ -125,7 +125,7 @@ var Loader = (function () {
|
|||||||
* @param {Function} callback Function called when done.
|
* @param {Function} callback Function called when done.
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
@ -295,6 +295,9 @@ var MM = (function () {
|
|||||||
// Otherwise cancel show action.
|
// Otherwise cancel show action.
|
||||||
if (module.lockStrings.length !== 0 && options.force !== true) {
|
if (module.lockStrings.length !== 0 && options.force !== true) {
|
||||||
Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(","));
|
Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(","));
|
||||||
|
if (typeof options.onError === "function") {
|
||||||
|
options.onError(new Error("LOCK_STRING_ACTIVE"));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +443,6 @@ var MM = (function () {
|
|||||||
* Removes a module instance from the collection.
|
* Removes a module instance from the collection.
|
||||||
*
|
*
|
||||||
* @param {object} module The module instance to remove from the collection.
|
* @param {object} module The module instance to remove from the collection.
|
||||||
*
|
|
||||||
* @returns {Module[]} Filtered collection of modules.
|
* @returns {Module[]} Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var exceptModule = function (module) {
|
var exceptModule = function (module) {
|
||||||
@ -547,6 +549,11 @@ var MM = (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!module.data.position) {
|
||||||
|
Log.warn("module tries to update the DOM without being displayed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Further implementation is done in the private method.
|
// Further implementation is done in the private method.
|
||||||
updateDom(module, speed);
|
updateDom(module, speed);
|
||||||
},
|
},
|
||||||
|
45
js/module.js
45
js/module.js
@ -176,7 +176,7 @@ var Module = Class.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._nunjucksEnvironment.addFilter("translate", function (str, variables) {
|
this._nunjucksEnvironment.addFilter("translate", function (str, variables) {
|
||||||
return self.translate(str, variables);
|
return nunjucks.runtime.markSafe(self.translate(str, variables));
|
||||||
});
|
});
|
||||||
|
|
||||||
return this._nunjucksEnvironment;
|
return this._nunjucksEnvironment;
|
||||||
@ -311,33 +311,33 @@ var Module = Class.extend({
|
|||||||
*
|
*
|
||||||
* @param {Function} callback Function called when done.
|
* @param {Function} callback Function called when done.
|
||||||
*/
|
*/
|
||||||
loadTranslations: function (callback) {
|
loadTranslations(callback) {
|
||||||
var self = this;
|
const translations = this.getTranslations() || {};
|
||||||
var translations = this.getTranslations();
|
const language = config.language.toLowerCase();
|
||||||
var lang = config.language.toLowerCase();
|
|
||||||
|
|
||||||
// The variable `first` will contain the first
|
const languages = Object.keys(translations);
|
||||||
// defined translation after the following line.
|
const fallbackLanguage = languages[0];
|
||||||
for (var first in translations) {
|
|
||||||
break;
|
if (languages.length === 0) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (translations) {
|
const translationFile = translations[language];
|
||||||
var translationFile = translations[lang] || undefined;
|
const translationsFallbackFile = translations[fallbackLanguage];
|
||||||
var translationsFallbackFile = translations[first];
|
|
||||||
|
|
||||||
// If a translation file is set, load it and then also load the fallback translation file.
|
if (!translationFile) {
|
||||||
// Otherwise only load the fallback translation file.
|
Translator.load(this, translationsFallbackFile, true, callback);
|
||||||
if (translationFile !== undefined && translationFile !== translationsFallbackFile) {
|
return;
|
||||||
Translator.load(self, translationFile, false, function () {
|
|
||||||
Translator.load(self, translationsFallbackFile, true, callback);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Translator.load(self, translationsFallbackFile, true, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Translator.load(this, translationFile, false, () => {
|
||||||
|
if (translationFile !== translationsFallbackFile) {
|
||||||
|
Translator.load(this, translationsFallbackFile, true, callback);
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -428,12 +428,11 @@ var Module = Class.extend({
|
|||||||
callback = callback || function () {};
|
callback = callback || function () {};
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var self = this;
|
|
||||||
MM.showModule(
|
MM.showModule(
|
||||||
this,
|
this,
|
||||||
speed,
|
speed,
|
||||||
function () {
|
() => {
|
||||||
self.resume();
|
this.resume();
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
options
|
options
|
||||||
|
@ -5,21 +5,21 @@
|
|||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
const Class = require("./class.js");
|
const Class = require("./class.js");
|
||||||
const Log = require("./logger.js");
|
const Log = require("logger");
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
|
|
||||||
var NodeHelper = Class.extend({
|
const NodeHelper = Class.extend({
|
||||||
init: function () {
|
init() {
|
||||||
Log.log("Initializing new module helper ...");
|
Log.log("Initializing new module helper ...");
|
||||||
},
|
},
|
||||||
|
|
||||||
loaded: function (callback) {
|
loaded(callback) {
|
||||||
Log.log("Module helper loaded: " + this.name);
|
Log.log(`Module helper loaded: ${this.name}`);
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function () {
|
start() {
|
||||||
Log.log("Starting module helper: " + this.name);
|
Log.log(`Starting module helper: ${this.name}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* stop()
|
/* stop()
|
||||||
@ -28,8 +28,8 @@ var NodeHelper = Class.extend({
|
|||||||
* gracefully exit the module.
|
* gracefully exit the module.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
stop: function () {
|
stop() {
|
||||||
Log.log("Stopping module helper: " + this.name);
|
Log.log(`Stopping module helper: ${this.name}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* socketNotificationReceived(notification, payload)
|
/* socketNotificationReceived(notification, payload)
|
||||||
@ -38,8 +38,8 @@ 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(notification, payload) {
|
||||||
Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
|
Log.log(`${this.name} received a socket notification: ${notification} - Payload: ${payload}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* setName(name)
|
/* setName(name)
|
||||||
@ -47,7 +47,7 @@ var NodeHelper = Class.extend({
|
|||||||
*
|
*
|
||||||
* argument name string - Module name.
|
* argument name string - Module name.
|
||||||
*/
|
*/
|
||||||
setName: function (name) {
|
setName(name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ var NodeHelper = Class.extend({
|
|||||||
*
|
*
|
||||||
* argument path string - Module path.
|
* argument path string - Module path.
|
||||||
*/
|
*/
|
||||||
setPath: function (path) {
|
setPath(path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -66,7 +66,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(notification, payload) {
|
||||||
this.io.of(this.name).emit(notification, payload);
|
this.io.of(this.name).emit(notification, payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -76,11 +76,10 @@ var NodeHelper = Class.extend({
|
|||||||
*
|
*
|
||||||
* argument app Express app - The Express app object.
|
* argument app Express app - The Express app object.
|
||||||
*/
|
*/
|
||||||
setExpressApp: function (app) {
|
setExpressApp(app) {
|
||||||
this.expressApp = app;
|
this.expressApp = app;
|
||||||
|
|
||||||
var publicPath = this.path + "/public";
|
app.use(`/${this.name}`, express.static(`${this.path}/public`));
|
||||||
app.use("/" + this.name, express.static(publicPath));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/* setSocketIO(io)
|
/* setSocketIO(io)
|
||||||
@ -89,27 +88,25 @@ var NodeHelper = Class.extend({
|
|||||||
*
|
*
|
||||||
* argument io Socket.io - The Socket io object.
|
* argument io Socket.io - The Socket io object.
|
||||||
*/
|
*/
|
||||||
setSocketIO: function (io) {
|
setSocketIO(io) {
|
||||||
var self = this;
|
this.io = io;
|
||||||
self.io = io;
|
|
||||||
|
|
||||||
Log.log("Connecting socket for: " + this.name);
|
Log.log(`Connecting socket for: ${this.name}`);
|
||||||
var namespace = this.name;
|
|
||||||
io.of(namespace).on("connection", function (socket) {
|
io.of(this.name).on("connection", (socket) => {
|
||||||
// add a catch all event.
|
// add a catch all event.
|
||||||
var onevent = socket.onevent;
|
const onevent = socket.onevent;
|
||||||
socket.onevent = function (packet) {
|
socket.onevent = function (packet) {
|
||||||
var args = packet.data || [];
|
const args = packet.data || [];
|
||||||
onevent.call(this, packet); // original call
|
onevent.call(this, packet); // original call
|
||||||
packet.data = ["*"].concat(args);
|
packet.data = ["*"].concat(args);
|
||||||
onevent.call(this, packet); // additional call to catch-all
|
onevent.call(this, packet); // additional call to catch-all
|
||||||
};
|
};
|
||||||
|
|
||||||
// register catch all.
|
// register catch all.
|
||||||
socket.on("*", function (notification, payload) {
|
socket.on("*", (notification, payload) => {
|
||||||
if (notification !== "*") {
|
if (notification !== "*") {
|
||||||
//Log.log('received message in namespace: ' + namespace);
|
this.socketNotificationReceived(notification, payload);
|
||||||
self.socketNotificationReceived(notification, payload);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -120,7 +117,4 @@ NodeHelper.create = function (moduleDefinition) {
|
|||||||
return NodeHelper.extend(moduleDefinition);
|
return NodeHelper.extend(moduleDefinition);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
module.exports = NodeHelper;
|
||||||
if (typeof module !== "undefined") {
|
|
||||||
module.exports = NodeHelper;
|
|
||||||
}
|
|
||||||
|
61
js/server.js
61
js/server.js
@ -4,25 +4,29 @@
|
|||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var express = require("express");
|
const express = require("express");
|
||||||
var app = require("express")();
|
const app = require("express")();
|
||||||
var path = require("path");
|
const path = require("path");
|
||||||
var ipfilter = require("express-ipfilter").IpFilter;
|
const ipfilter = require("express-ipfilter").IpFilter;
|
||||||
var fs = require("fs");
|
const fs = require("fs");
|
||||||
var helmet = require("helmet");
|
const helmet = require("helmet");
|
||||||
|
|
||||||
var Log = require("./logger.js");
|
const Log = require("logger");
|
||||||
var Utils = require("./utils.js");
|
const Utils = require("./utils.js");
|
||||||
|
|
||||||
var Server = function (config, callback) {
|
/**
|
||||||
var port = config.port;
|
* Server
|
||||||
if (process.env.MM_PORT) {
|
*
|
||||||
port = process.env.MM_PORT;
|
* @param {object} config The MM config
|
||||||
}
|
* @param {Function} callback Function called when done.
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
function Server(config, callback) {
|
||||||
|
const port = process.env.MM_PORT || config.port;
|
||||||
|
|
||||||
var server = null;
|
let server = null;
|
||||||
if (config.useHttps) {
|
if (config.useHttps) {
|
||||||
var options = {
|
const options = {
|
||||||
key: fs.readFileSync(config.httpsPrivateKey),
|
key: fs.readFileSync(config.httpsPrivateKey),
|
||||||
cert: fs.readFileSync(config.httpsCertificate)
|
cert: fs.readFileSync(config.httpsCertificate)
|
||||||
};
|
};
|
||||||
@ -30,18 +34,24 @@ var Server = function (config, callback) {
|
|||||||
} else {
|
} else {
|
||||||
server = require("http").Server(app);
|
server = require("http").Server(app);
|
||||||
}
|
}
|
||||||
var io = require("socket.io")(server);
|
const io = require("socket.io")(server, {
|
||||||
|
cors: {
|
||||||
|
origin: /.*$/,
|
||||||
|
credentials: true
|
||||||
|
},
|
||||||
|
allowEIO3: true
|
||||||
|
});
|
||||||
|
|
||||||
Log.log("Starting server on port " + port + " ... ");
|
Log.log(`Starting server on port ${port} ... `);
|
||||||
|
|
||||||
server.listen(port, config.address ? config.address : "localhost");
|
server.listen(port, config.address || "localhost");
|
||||||
|
|
||||||
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) {
|
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) {
|
||||||
Log.warn(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs"));
|
Log.warn(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) {
|
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();
|
||||||
}
|
}
|
||||||
@ -52,10 +62,9 @@ var Server = function (config, callback) {
|
|||||||
app.use(helmet({ contentSecurityPolicy: false }));
|
app.use(helmet({ contentSecurityPolicy: false }));
|
||||||
|
|
||||||
app.use("/js", express.static(__dirname));
|
app.use("/js", express.static(__dirname));
|
||||||
var directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs"];
|
|
||||||
var directory;
|
const directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs"];
|
||||||
for (var i in directories) {
|
for (const directory of directories) {
|
||||||
directory = directories[i];
|
|
||||||
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +77,10 @@ var Server = function (config, callback) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get("/", function (req, res) {
|
app.get("/", function (req, res) {
|
||||||
var html = fs.readFileSync(path.resolve(global.root_path + "/index.html"), { encoding: "utf8" });
|
let 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";
|
let configFile = "config/config.js";
|
||||||
if (typeof global.configuration_file !== "undefined") {
|
if (typeof global.configuration_file !== "undefined") {
|
||||||
configFile = global.configuration_file;
|
configFile = global.configuration_file;
|
||||||
}
|
}
|
||||||
@ -83,6 +92,6 @@ var Server = function (config, callback) {
|
|||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") {
|
||||||
callback(app, io);
|
callback(app, io);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = Server;
|
module.exports = Server;
|
||||||
|
@ -103,26 +103,19 @@ var Translator = (function () {
|
|||||||
* @param {boolean} isFallback Flag to indicate fallback translations.
|
* @param {boolean} isFallback Flag to indicate fallback translations.
|
||||||
* @param {Function} callback Function called when done.
|
* @param {Function} callback Function called when done.
|
||||||
*/
|
*/
|
||||||
load: function (module, file, isFallback, callback) {
|
load(module, file, isFallback, callback) {
|
||||||
if (!isFallback) {
|
Log.log(`${module.name} - Load translation${isFallback && " fallback"}: ${file}`);
|
||||||
Log.log(module.name + " - Load translation: " + file);
|
|
||||||
} else {
|
if (this.translationsFallback[module.name]) {
|
||||||
Log.log(module.name + " - Load translation fallback: " + file);
|
callback();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
loadJSON(module.file(file), (json) => {
|
||||||
if (!this.translationsFallback[module.name]) {
|
const property = isFallback ? "translationsFallback" : "translations";
|
||||||
loadJSON(module.file(file), function (json) {
|
this[property][module.name] = json;
|
||||||
if (!isFallback) {
|
|
||||||
self.translations[module.name] = json;
|
|
||||||
} else {
|
|
||||||
self.translationsFallback[module.name] = json;
|
|
||||||
}
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
var colors = require("colors/safe");
|
const colors = require("colors/safe");
|
||||||
|
|
||||||
var Utils = {
|
module.exports = {
|
||||||
colors: {
|
colors: {
|
||||||
warn: colors.yellow,
|
warn: colors.yellow,
|
||||||
error: colors.red,
|
error: colors.red,
|
||||||
@ -14,7 +14,3 @@ var Utils = {
|
|||||||
pass: colors.green
|
pass: colors.green
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof module !== "undefined") {
|
|
||||||
module.exports = Utils;
|
|
||||||
}
|
|
||||||
|
@ -36,6 +36,7 @@ Module.register("calendar", {
|
|||||||
fadePoint: 0.25, // Start on 1/4th of the list.
|
fadePoint: 0.25, // Start on 1/4th of the list.
|
||||||
hidePrivate: false,
|
hidePrivate: false,
|
||||||
hideOngoing: false,
|
hideOngoing: false,
|
||||||
|
hideTime: false,
|
||||||
colored: false,
|
colored: false,
|
||||||
coloredSymbolOnly: false,
|
coloredSymbolOnly: false,
|
||||||
customEvents: [], // Array of {keyword: "", symbol: "", color: ""} where Keyword is a regexp and symbol/color are to be applied for matched
|
customEvents: [], // Array of {keyword: "", symbol: "", color: ""} where Keyword is a regexp and symbol/color are to be applied for matched
|
||||||
@ -57,7 +58,8 @@ Module.register("calendar", {
|
|||||||
excludedEvents: [],
|
excludedEvents: [],
|
||||||
sliceMultiDayEvents: false,
|
sliceMultiDayEvents: false,
|
||||||
broadcastPastEvents: false,
|
broadcastPastEvents: false,
|
||||||
nextDaysRelative: false
|
nextDaysRelative: false,
|
||||||
|
selfSignedCert: false
|
||||||
},
|
},
|
||||||
|
|
||||||
requiresVersion: "2.1.0",
|
requiresVersion: "2.1.0",
|
||||||
@ -100,7 +102,8 @@ 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,
|
||||||
|
selfSignedCert: calendar.selfSignedCert
|
||||||
};
|
};
|
||||||
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
|
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
|
||||||
calendarConfig.symbolClass = "";
|
calendarConfig.symbolClass = "";
|
||||||
@ -277,8 +280,11 @@ Module.register("calendar", {
|
|||||||
if (typeof this.config.customEvents[ev].color !== "undefined" && this.config.customEvents[ev].color !== "") {
|
if (typeof this.config.customEvents[ev].color !== "undefined" && this.config.customEvents[ev].color !== "") {
|
||||||
needle = new RegExp(this.config.customEvents[ev].keyword, "gi");
|
needle = new RegExp(this.config.customEvents[ev].keyword, "gi");
|
||||||
if (needle.test(event.title)) {
|
if (needle.test(event.title)) {
|
||||||
|
// Respect parameter ColoredSymbolOnly also for custom events
|
||||||
|
if (!this.config.coloredSymbolOnly) {
|
||||||
eventWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
eventWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
||||||
titleWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
titleWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
||||||
|
}
|
||||||
if (this.config.displaySymbol) {
|
if (this.config.displaySymbol) {
|
||||||
symbolWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
symbolWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
||||||
}
|
}
|
||||||
@ -363,7 +369,17 @@ Module.register("calendar", {
|
|||||||
// Show relative times
|
// Show relative times
|
||||||
if (event.startDate >= now) {
|
if (event.startDate >= now) {
|
||||||
// Use relative time
|
// Use relative time
|
||||||
|
if (!this.config.hideTime) {
|
||||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar());
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar());
|
||||||
|
} else {
|
||||||
|
timeWrapper.innerHTML = this.capFirst(
|
||||||
|
moment(event.startDate, "x").calendar(null, {
|
||||||
|
sameDay: "[" + this.translate("TODAY") + "]",
|
||||||
|
nextDay: "[" + this.translate("TOMORROW") + "]",
|
||||||
|
nextWeek: "dddd"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
if (event.startDate - now < this.config.getRelative * oneHour) {
|
if (event.startDate - now < this.config.getRelative * oneHour) {
|
||||||
// If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
|
// If event is within getRelative hours, 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());
|
||||||
@ -592,7 +608,8 @@ 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,
|
||||||
|
selfSignedCert: calendarConfig.selfSignedCert || this.config.selfSignedCert
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
const Log = require("../../../js/logger.js");
|
const Log = require("logger");
|
||||||
const ical = require("node-ical");
|
const ical = require("node-ical");
|
||||||
const request = require("request");
|
const request = require("request");
|
||||||
|
|
||||||
@ -25,9 +25,10 @@ const moment = require("moment");
|
|||||||
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
|
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
|
||||||
* @param {object} auth The object containing options for authentication against the calendar.
|
* @param {object} auth The object containing options for authentication against the calendar.
|
||||||
* @param {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too
|
* @param {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too
|
||||||
|
* @param {boolean} selfSignedCert If true, the server certificate is not verified against the list of supplied CAs.
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) {
|
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents, selfSignedCert) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
let reloadTimer = null;
|
let reloadTimer = null;
|
||||||
@ -51,6 +52,13 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
gzip: true
|
gzip: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (selfSignedCert) {
|
||||||
|
var agentOptions = {
|
||||||
|
rejectUnauthorized: false
|
||||||
|
};
|
||||||
|
opts.agentOptions = agentOptions;
|
||||||
|
}
|
||||||
|
|
||||||
if (auth) {
|
if (auth) {
|
||||||
if (auth.method === "bearer") {
|
if (auth.method === "bearer") {
|
||||||
opts.auth = {
|
opts.auth = {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
const NodeHelper = require("node_helper");
|
const NodeHelper = require("node_helper");
|
||||||
const validUrl = require("valid-url");
|
const validUrl = require("valid-url");
|
||||||
const CalendarFetcher = require("./calendarfetcher.js");
|
const CalendarFetcher = require("./calendarfetcher.js");
|
||||||
const Log = require("../../../js/logger");
|
const Log = require("logger");
|
||||||
|
|
||||||
module.exports = NodeHelper.create({
|
module.exports = NodeHelper.create({
|
||||||
// Override start method.
|
// Override start method.
|
||||||
@ -19,7 +19,7 @@ module.exports = NodeHelper.create({
|
|||||||
// Override socketNotificationReceived method.
|
// Override socketNotificationReceived method.
|
||||||
socketNotificationReceived: function (notification, payload) {
|
socketNotificationReceived: function (notification, payload) {
|
||||||
if (notification === "ADD_CALENDAR") {
|
if (notification === "ADD_CALENDAR") {
|
||||||
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents, payload.id);
|
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents, payload.selfSignedCert, payload.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -34,9 +34,10 @@ module.exports = NodeHelper.create({
|
|||||||
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
|
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
|
||||||
* @param {object} auth The object containing options for authentication against the calendar.
|
* @param {object} auth The object containing options for authentication against the calendar.
|
||||||
* @param {boolean} broadcastPastEvents If true events from the past maximumNumberOfDays will be included in event broadcasts
|
* @param {boolean} broadcastPastEvents If true events from the past maximumNumberOfDays will be included in event broadcasts
|
||||||
|
* @param {boolean} selfSignedCert If true, the server certificate is not verified against the list of supplied CAs.
|
||||||
* @param {string} identifier ID of the module
|
* @param {string} identifier ID of the module
|
||||||
*/
|
*/
|
||||||
createFetcher: function (url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, identifier) {
|
createFetcher: function (url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert, identifier) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (!validUrl.isUri(url)) {
|
if (!validUrl.isUri(url)) {
|
||||||
@ -47,7 +48,7 @@ module.exports = NodeHelper.create({
|
|||||||
var fetcher;
|
var fetcher;
|
||||||
if (typeof self.fetchers[identifier + url] === "undefined") {
|
if (typeof self.fetchers[identifier + url] === "undefined") {
|
||||||
Log.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval);
|
Log.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, selfSignedCert);
|
||||||
|
|
||||||
fetcher.onReceive(function (fetcher) {
|
fetcher.onReceive(function (fetcher) {
|
||||||
self.sendSocketNotification("CALENDAR_EVENTS", {
|
self.sendSocketNotification("CALENDAR_EVENTS", {
|
||||||
|
@ -182,34 +182,14 @@ Module.register("compliments", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// From data currentweather set weather type
|
// From data currentweather set weather type
|
||||||
setCurrentWeatherType: function (data) {
|
setCurrentWeatherType: function (type) {
|
||||||
var weatherIconTable = {
|
this.currentWeatherType = type;
|
||||||
"01d": "day_sunny",
|
|
||||||
"02d": "day_cloudy",
|
|
||||||
"03d": "cloudy",
|
|
||||||
"04d": "cloudy_windy",
|
|
||||||
"09d": "showers",
|
|
||||||
"10d": "rain",
|
|
||||||
"11d": "thunderstorm",
|
|
||||||
"13d": "snow",
|
|
||||||
"50d": "fog",
|
|
||||||
"01n": "night_clear",
|
|
||||||
"02n": "night_cloudy",
|
|
||||||
"03n": "night_cloudy",
|
|
||||||
"04n": "night_cloudy",
|
|
||||||
"09n": "night_showers",
|
|
||||||
"10n": "night_rain",
|
|
||||||
"11n": "night_thunderstorm",
|
|
||||||
"13n": "night_snow",
|
|
||||||
"50n": "night_alt_cloudy_windy"
|
|
||||||
};
|
|
||||||
this.currentWeatherType = weatherIconTable[data.weather[0].icon];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override notification handler.
|
// Override notification handler.
|
||||||
notificationReceived: function (notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
if (notification === "CURRENTWEATHER_DATA") {
|
if (notification === "CURRENTWEATHER_TYPE") {
|
||||||
this.setCurrentWeatherType(payload.data);
|
this.setCurrentWeatherType(payload.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Module: Current Weather
|
# Module: Current Weather
|
||||||
|
|
||||||
|
> :warning: **This module is deprecated in favor of the [weather](https://docs.magicmirror.builders/modules/weather.html) module.**
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
*
|
*
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
|
*
|
||||||
|
* This module is deprecated. Any additional feature will no longer be merged.
|
||||||
*/
|
*/
|
||||||
Module.register("currentweather", {
|
Module.register("currentweather", {
|
||||||
// Default module config.
|
// Default module config.
|
||||||
@ -47,24 +49,24 @@ Module.register("currentweather", {
|
|||||||
roundTemp: false,
|
roundTemp: false,
|
||||||
|
|
||||||
iconTable: {
|
iconTable: {
|
||||||
"01d": "wi-day-sunny",
|
"01d": "day-sunny",
|
||||||
"02d": "wi-day-cloudy",
|
"02d": "day-cloudy",
|
||||||
"03d": "wi-cloudy",
|
"03d": "cloudy",
|
||||||
"04d": "wi-cloudy-windy",
|
"04d": "cloudy-windy",
|
||||||
"09d": "wi-showers",
|
"09d": "showers",
|
||||||
"10d": "wi-rain",
|
"10d": "rain",
|
||||||
"11d": "wi-thunderstorm",
|
"11d": "thunderstorm",
|
||||||
"13d": "wi-snow",
|
"13d": "snow",
|
||||||
"50d": "wi-fog",
|
"50d": "fog",
|
||||||
"01n": "wi-night-clear",
|
"01n": "night-clear",
|
||||||
"02n": "wi-night-cloudy",
|
"02n": "night-cloudy",
|
||||||
"03n": "wi-night-cloudy",
|
"03n": "night-cloudy",
|
||||||
"04n": "wi-night-cloudy",
|
"04n": "night-cloudy",
|
||||||
"09n": "wi-night-showers",
|
"09n": "night-showers",
|
||||||
"10n": "wi-night-rain",
|
"10n": "night-rain",
|
||||||
"11n": "wi-night-thunderstorm",
|
"11n": "night-thunderstorm",
|
||||||
"13n": "wi-night-snow",
|
"13n": "night-snow",
|
||||||
"50n": "wi-night-alt-cloudy-windy"
|
"50n": "night-alt-cloudy-windy"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -219,7 +221,7 @@ Module.register("currentweather", {
|
|||||||
|
|
||||||
if (this.config.hideTemp === false) {
|
if (this.config.hideTemp === false) {
|
||||||
var weatherIcon = document.createElement("span");
|
var weatherIcon = document.createElement("span");
|
||||||
weatherIcon.className = "wi weathericon " + this.weatherType;
|
weatherIcon.className = "wi weathericon wi-" + this.weatherType;
|
||||||
large.appendChild(weatherIcon);
|
large.appendChild(weatherIcon);
|
||||||
|
|
||||||
var temperature = document.createElement("span");
|
var temperature = document.createElement("span");
|
||||||
@ -258,13 +260,9 @@ Module.register("currentweather", {
|
|||||||
|
|
||||||
var feelsLike = document.createElement("span");
|
var feelsLike = document.createElement("span");
|
||||||
feelsLike.className = "dimmed";
|
feelsLike.className = "dimmed";
|
||||||
var feelsLikeHtml = this.translate("FEELS");
|
feelsLike.innerHTML = this.translate("FEELS", {
|
||||||
if (feelsLikeHtml.indexOf("{DEGREE}") > -1) {
|
|
||||||
feelsLikeHtml = this.translate("FEELS", {
|
|
||||||
DEGREE: this.feelsLike + degreeLabel
|
DEGREE: this.feelsLike + degreeLabel
|
||||||
});
|
});
|
||||||
} else feelsLikeHtml += " " + this.feelsLike + degreeLabel;
|
|
||||||
feelsLike.innerHTML = feelsLikeHtml;
|
|
||||||
small.appendChild(feelsLike);
|
small.appendChild(feelsLike);
|
||||||
|
|
||||||
wrapper.appendChild(small);
|
wrapper.appendChild(small);
|
||||||
@ -506,6 +504,7 @@ Module.register("currentweather", {
|
|||||||
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 });
|
||||||
|
this.sendNotification("CURRENTWEATHER_TYPE", { type: this.config.iconTable[data.weather[0].icon].replace("-", "_") });
|
||||||
},
|
},
|
||||||
|
|
||||||
/* scheduleUpdate()
|
/* scheduleUpdate()
|
||||||
@ -593,6 +592,7 @@ Module.register("currentweather", {
|
|||||||
*/
|
*/
|
||||||
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);
|
var roundValue = parseFloat(temperature).toFixed(decimals);
|
||||||
|
return roundValue === "-0" ? 0 : roundValue;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
9
modules/default/currentweather/node_helper.js
Normal file
9
modules/default/currentweather/node_helper.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const NodeHelper = require("node_helper");
|
||||||
|
const Log = require("logger");
|
||||||
|
|
||||||
|
module.exports = NodeHelper.create({
|
||||||
|
// Override start method.
|
||||||
|
start: function () {
|
||||||
|
Log.warn(`The module '${this.name}' is deprecated in favor of the 'weather'-module, please refer to the documentation for a migration path`);
|
||||||
|
}
|
||||||
|
});
|
3
modules/default/newsfeed/fullarticle.njk
Normal file
3
modules/default/newsfeed/fullarticle.njk
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<iframe class="newsfeed-fullarticle" src="{{ url }}"></iframe>
|
||||||
|
</div>
|
14
modules/default/newsfeed/newsfeed.css
Normal file
14
modules/default/newsfeed/newsfeed.css
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
iframe.newsfeed-fullarticle {
|
||||||
|
width: 100vw;
|
||||||
|
/* very large height value to allow scrolling */
|
||||||
|
height: 3000px;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border: none;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.region.bottom.bar.newsfeed-fullarticle {
|
||||||
|
bottom: inherit;
|
||||||
|
top: -90px;
|
||||||
|
}
|
@ -44,6 +44,11 @@ Module.register("newsfeed", {
|
|||||||
return ["moment.js"];
|
return ["moment.js"];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//Define required styles.
|
||||||
|
getStyles: function () {
|
||||||
|
return ["newsfeed.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.
|
||||||
@ -75,6 +80,9 @@ Module.register("newsfeed", {
|
|||||||
this.generateFeed(payload);
|
this.generateFeed(payload);
|
||||||
|
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
|
if (this.config.hideLoading) {
|
||||||
|
this.show();
|
||||||
|
}
|
||||||
this.scheduleUpdateInterval();
|
this.scheduleUpdateInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,123 +90,43 @@ Module.register("newsfeed", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Override dom generator.
|
//Override fetching of template name
|
||||||
getDom: function () {
|
getTemplate: function () {
|
||||||
const wrapper = document.createElement("div");
|
|
||||||
|
|
||||||
if (this.config.feedUrl) {
|
if (this.config.feedUrl) {
|
||||||
wrapper.className = "small bright";
|
return "oldconfig.njk";
|
||||||
wrapper.innerHTML = this.translate("MODULE_CONFIG_CHANGED", { MODULE_NAME: "Newsfeed" });
|
} else if (this.config.showFullArticle) {
|
||||||
return wrapper;
|
return "fullarticle.njk";
|
||||||
|
}
|
||||||
|
return "newsfeed.njk";
|
||||||
|
},
|
||||||
|
|
||||||
|
//Override template data and return whats used for the current template
|
||||||
|
getTemplateData: function () {
|
||||||
|
// this.config.showFullArticle is a run-time configuration, triggered by optional notifications
|
||||||
|
if (this.config.showFullArticle) {
|
||||||
|
return {
|
||||||
|
url: this.getActiveItemURL()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.newsItems.length === 0) {
|
||||||
|
return {
|
||||||
|
loaded: false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.activeItem >= this.newsItems.length) {
|
if (this.activeItem >= this.newsItems.length) {
|
||||||
this.activeItem = 0;
|
this.activeItem = 0;
|
||||||
}
|
}
|
||||||
|
const item = this.newsItems[this.activeItem];
|
||||||
|
|
||||||
if (this.newsItems.length > 0) {
|
return {
|
||||||
// this.config.showFullArticle is a run-time configuration, triggered by optional notifications
|
loaded: true,
|
||||||
if (!this.config.showFullArticle && (this.config.showSourceTitle || this.config.showPublishDate)) {
|
config: this.config,
|
||||||
const sourceAndTimestamp = document.createElement("div");
|
sourceTitle: item.sourceTitle,
|
||||||
sourceAndTimestamp.className = "newsfeed-source light small dimmed";
|
publishDate: moment(new Date(item.pubdate)).fromNow(),
|
||||||
|
title: item.title,
|
||||||
if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "") {
|
description: item.description
|
||||||
sourceAndTimestamp.innerHTML = this.newsItems[this.activeItem].sourceTitle;
|
};
|
||||||
}
|
|
||||||
if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "" && this.config.showPublishDate) {
|
|
||||||
sourceAndTimestamp.innerHTML += ", ";
|
|
||||||
}
|
|
||||||
if (this.config.showPublishDate) {
|
|
||||||
sourceAndTimestamp.innerHTML += moment(new Date(this.newsItems[this.activeItem].pubdate)).fromNow();
|
|
||||||
}
|
|
||||||
if ((this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "") || this.config.showPublishDate) {
|
|
||||||
sourceAndTimestamp.innerHTML += ":";
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapper.appendChild(sourceAndTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove selected tags from the beginning of rss feed items (title or description)
|
|
||||||
|
|
||||||
if (this.config.removeStartTags === "title" || this.config.removeStartTags === "both") {
|
|
||||||
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]) {
|
|
||||||
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.isShowingDescription) {
|
|
||||||
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]) {
|
|
||||||
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)
|
|
||||||
|
|
||||||
if (this.config.removeEndTags) {
|
|
||||||
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]) {
|
|
||||||
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].title.slice(0, -this.config.endTags[f].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isShowingDescription) {
|
|
||||||
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]) {
|
|
||||||
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(0, -this.config.endTags[f].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.config.showFullArticle) {
|
|
||||||
const title = document.createElement("div");
|
|
||||||
title.className = "newsfeed-title bright medium light" + (!this.config.wrapTitle ? " no-wrap" : "");
|
|
||||||
title.innerHTML = this.newsItems[this.activeItem].title;
|
|
||||||
wrapper.appendChild(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isShowingDescription) {
|
|
||||||
const description = document.createElement("div");
|
|
||||||
description.className = "newsfeed-desc small light" + (!this.config.wrapDescription ? " no-wrap" : "");
|
|
||||||
const txtDesc = this.newsItems[this.activeItem].description;
|
|
||||||
description.innerHTML = this.config.truncDescription ? (txtDesc.length > this.config.lengthDescription ? txtDesc.substring(0, this.config.lengthDescription) + "..." : txtDesc) : txtDesc;
|
|
||||||
wrapper.appendChild(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.showFullArticle) {
|
|
||||||
const fullArticle = document.createElement("iframe");
|
|
||||||
fullArticle.className = "";
|
|
||||||
fullArticle.style.width = "100vw";
|
|
||||||
// very large height value to allow scrolling
|
|
||||||
fullArticle.height = "3000";
|
|
||||||
fullArticle.style.height = "3000";
|
|
||||||
fullArticle.style.top = "0";
|
|
||||||
fullArticle.style.left = "0";
|
|
||||||
fullArticle.style.border = "none";
|
|
||||||
fullArticle.src = this.getActiveItemURL();
|
|
||||||
fullArticle.style.zIndex = 1;
|
|
||||||
wrapper.appendChild(fullArticle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.hideLoading) {
|
|
||||||
this.show();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.config.hideLoading) {
|
|
||||||
this.hide();
|
|
||||||
} else {
|
|
||||||
wrapper.innerHTML = this.translate("LOADING");
|
|
||||||
wrapper.className = "small dimmed";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrapper;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getActiveItemURL: function () {
|
getActiveItemURL: function () {
|
||||||
@ -257,6 +185,45 @@ Module.register("newsfeed", {
|
|||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newsItems.forEach((item) => {
|
||||||
|
//Remove selected tags from the beginning of rss feed items (title or description)
|
||||||
|
if (this.config.removeStartTags === "title" || this.config.removeStartTags === "both") {
|
||||||
|
for (let f = 0; f < this.config.startTags.length; f++) {
|
||||||
|
if (item.title.slice(0, this.config.startTags[f].length) === this.config.startTags[f]) {
|
||||||
|
item.title = item.title.slice(this.config.startTags[f].length, item.title.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.config.removeStartTags === "description" || this.config.removeStartTags === "both") {
|
||||||
|
if (this.isShowingDescription) {
|
||||||
|
for (let f = 0; f < this.config.startTags.length; f++) {
|
||||||
|
if (item.description.slice(0, this.config.startTags[f].length) === this.config.startTags[f]) {
|
||||||
|
item.description = item.description.slice(this.config.startTags[f].length, item.description.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove selected tags from the end of rss feed items (title or description)
|
||||||
|
|
||||||
|
if (this.config.removeEndTags) {
|
||||||
|
for (let f = 0; f < this.config.endTags.length; f++) {
|
||||||
|
if (item.title.slice(-this.config.endTags[f].length) === this.config.endTags[f]) {
|
||||||
|
item.title = item.title.slice(0, -this.config.endTags[f].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isShowingDescription) {
|
||||||
|
for (let f = 0; f < this.config.endTags.length; f++) {
|
||||||
|
if (item.description.slice(-this.config.endTags[f].length) === this.config.endTags[f]) {
|
||||||
|
item.description = item.description.slice(0, -this.config.endTags[f].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// get updated news items and broadcast them
|
// get updated news items and broadcast them
|
||||||
var updatedItems = [];
|
var updatedItems = [];
|
||||||
newsItems.forEach((value) => {
|
newsItems.forEach((value) => {
|
||||||
@ -335,8 +302,7 @@ Module.register("newsfeed", {
|
|||||||
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].classList.remove("newsfeed-fullarticle");
|
||||||
document.getElementsByClassName("region bottom bar")[0].style.top = "inherit";
|
|
||||||
if (!this.timer) {
|
if (!this.timer) {
|
||||||
this.scheduleUpdateInterval();
|
this.scheduleUpdateInterval();
|
||||||
}
|
}
|
||||||
@ -344,7 +310,9 @@ Module.register("newsfeed", {
|
|||||||
|
|
||||||
notificationReceived: function (notification, payload, sender) {
|
notificationReceived: function (notification, payload, sender) {
|
||||||
const before = this.activeItem;
|
const before = this.activeItem;
|
||||||
if (notification === "ARTICLE_NEXT") {
|
if (notification === "MODULE_DOM_CREATED" && this.config.hideLoading) {
|
||||||
|
this.hide();
|
||||||
|
} else 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;
|
||||||
@ -406,8 +374,7 @@ Module.register("newsfeed", {
|
|||||||
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].classList.add("newsfeed-fullarticle");
|
||||||
document.getElementsByClassName("region bottom bar")[0].style.top = "-90px";
|
|
||||||
}
|
}
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
this.timer = null;
|
this.timer = null;
|
||||||
|
28
modules/default/newsfeed/newsfeed.njk
Normal file
28
modules/default/newsfeed/newsfeed.njk
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{% if loaded %}
|
||||||
|
<div>
|
||||||
|
{% if (config.showSourceTitle and sourceTitle) or config.showPublishDate %}
|
||||||
|
<div class="newsfeed-source light small dimmed">
|
||||||
|
{% if sourceTitle and config.showSourceTitle %}
|
||||||
|
{{ sourceTitle }}{% if config.showPublishDate %}, {% else %}: {% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if config.showPublishDate %}
|
||||||
|
{{ publishDate }}:
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="newsfeed-title bright medium light{{ ' no-wrap' if config.wrapTitle }}">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
|
<div class="newsfeed-desc small light{{ ' no-wrap' if config.wrapDescription }}">
|
||||||
|
{% if config.truncDescription %}
|
||||||
|
{{ description | truncate(config.lengthDescription) }}
|
||||||
|
{% else %}
|
||||||
|
{{ description }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="small dimmed">
|
||||||
|
{{ "LOADING" | translate | safe }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
@ -4,7 +4,7 @@
|
|||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
*/
|
*/
|
||||||
const Log = require("../../../js/logger.js");
|
const Log = require("logger");
|
||||||
const FeedMe = require("feedme");
|
const FeedMe = require("feedme");
|
||||||
const request = require("request");
|
const request = require("request");
|
||||||
const iconv = require("iconv-lite");
|
const iconv = require("iconv-lite");
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
const NodeHelper = require("node_helper");
|
const NodeHelper = require("node_helper");
|
||||||
const validUrl = require("valid-url");
|
const validUrl = require("valid-url");
|
||||||
const NewsfeedFetcher = require("./newsfeedfetcher.js");
|
const NewsfeedFetcher = require("./newsfeedfetcher.js");
|
||||||
const Log = require("../../../js/logger");
|
const Log = require("logger");
|
||||||
|
|
||||||
module.exports = NodeHelper.create({
|
module.exports = NodeHelper.create({
|
||||||
// Override start method.
|
// Override start method.
|
||||||
|
3
modules/default/newsfeed/oldconfig.njk
Normal file
3
modules/default/newsfeed/oldconfig.njk
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div class="small bright">
|
||||||
|
{{ "MODULE_CONFIG_CHANGED" | translate({MODULE_NAME: "Newsfeed"}) | safe }}
|
||||||
|
</div>
|
@ -3,7 +3,7 @@ const simpleGits = [];
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const defaultModules = require(__dirname + "/../defaultmodules.js");
|
const defaultModules = require(__dirname + "/../defaultmodules.js");
|
||||||
const Log = require(__dirname + "/../../../js/logger.js");
|
const Log = require("logger");
|
||||||
const NodeHelper = require("node_helper");
|
const NodeHelper = require("node_helper");
|
||||||
|
|
||||||
module.exports = NodeHelper.create({
|
module.exports = NodeHelper.create({
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
{% if current or weatherData %}
|
{% if current %}
|
||||||
{% if weatherData %}
|
|
||||||
{% set current = weatherData.current %}
|
|
||||||
{% endif %}
|
|
||||||
{% if not config.onlyTemp %}
|
{% if not config.onlyTemp %}
|
||||||
<div class="normal medium">
|
<div class="normal medium">
|
||||||
<span class="wi wi-strong-wind dimmed"></span>
|
<span class="wi wi-strong-wind dimmed"></span>
|
||||||
@ -66,13 +63,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if (config.showFeelsLike or config.showPrecipitationAmount) and not config.onlyTemp %}
|
{% if (config.showFeelsLike or config.showPrecipitationAmount) and not config.onlyTemp %}
|
||||||
<div class="normal medium">
|
<div class="normal medium feelslike">
|
||||||
{% if config.showFeelsLike %}
|
{% if config.showFeelsLike %}
|
||||||
<span class="dimmed">
|
<span class="dimmed">
|
||||||
{{ "FEELS" | translate({DEGREE: current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }) }}
|
{{ "FEELS" | translate({DEGREE: current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }) }}
|
||||||
{% if not config.feelsLikeWithDegree %}
|
|
||||||
{{ current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }}
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if config.showPrecipitationAmount %}
|
{% if config.showPrecipitationAmount %}
|
||||||
@ -84,7 +78,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="dimmed light small">
|
<div class="dimmed light small">
|
||||||
{{ "LOADING" | translate | safe }}
|
{{ "LOADING" | translate }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
{% if forecast or weatherData %}
|
{% if forecast %}
|
||||||
{% if weatherData %}
|
|
||||||
{% set forecast = weatherData.days %}
|
|
||||||
{% set numSteps = forecast | calcNumEntries %}
|
|
||||||
{% else %}
|
|
||||||
{% set numSteps = forecast | calcNumSteps %}
|
{% set numSteps = forecast | calcNumSteps %}
|
||||||
{% endif %}
|
|
||||||
{% set currentStep = 0 %}
|
{% set currentStep = 0 %}
|
||||||
<table class="{{ config.tableClass }}">
|
<table class="{{ config.tableClass }}">
|
||||||
{% set forecast = forecast.slice(0, numSteps) %}
|
{% set forecast = forecast.slice(0, numSteps) %}
|
||||||
@ -35,7 +30,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="dimmed light small">
|
<div class="dimmed light small">
|
||||||
{{ "LOADING" | translate | safe }}
|
{{ "LOADING" | translate }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
{% if hourly or weatherData %}
|
{% if hourly %}
|
||||||
{% if weatherData %}
|
|
||||||
{% set hourly = weatherData.hours %}
|
|
||||||
{% endif %}
|
|
||||||
{% set numSteps = hourly | calcNumEntries %}
|
{% set numSteps = hourly | calcNumEntries %}
|
||||||
{% set currentStep = 0 %}
|
{% set currentStep = 0 %}
|
||||||
<table class="{{ config.tableClass }}">
|
<table class="{{ config.tableClass }}">
|
||||||
@ -24,9 +21,9 @@
|
|||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="dimmed light small">
|
<div class="dimmed light small">
|
||||||
{{ "LOADING" | translate | safe }}
|
{{ "LOADING" | translate }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Uncomment the line below to see the contents of the `hourly` object. -->
|
<!-- Uncomment the line below to see the contents of the `hourly` object. -->
|
||||||
<!-- <div style="word-wrap:break-word" class="xsmall dimmed">{{weatherData | dump}}</div> -->
|
<!-- <div style="word-wrap:break-word" class="xsmall dimmed">{{hourly | dump}}</div> -->
|
||||||
|
@ -29,16 +29,23 @@ WeatherProvider.register("yourprovider", {
|
|||||||
|
|
||||||
#### `fetchCurrentWeather()`
|
#### `fetchCurrentWeather()`
|
||||||
|
|
||||||
This method is called when the weather module tries to fetch the current weather of your provider. The implementation of this method is required.
|
This method is called when the weather module tries to fetch the current weather of your provider. The implementation of this method is required for current weather support.
|
||||||
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
||||||
After the response is processed, the current weather information (as a [WeatherObject](#weatherobject)) needs to be set with `this.setCurrentWeather(currentWeather);`.
|
After the response is processed, the current weather information (as a [WeatherObject](#weatherobject)) needs to be set with `this.setCurrentWeather(currentWeather);`.
|
||||||
It will then automatically refresh the module DOM with the new data.
|
It will then automatically refresh the module DOM with the new data.
|
||||||
|
|
||||||
#### `fetchWeatherForecast()`
|
#### `fetchWeatherForecast()`
|
||||||
|
|
||||||
This method is called when the weather module tries to fetch the weather of your provider. The implementation of this method is required.
|
This method is called when the weather module tries to fetch the weather of your provider. The implementation of this method is required for forecast support.
|
||||||
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
||||||
After the response is processed, the weather forecast information (as an array of [WeatherObject](#weatherobject)s) needs to be set with `this.setCurrentWeather(forecast);`.
|
After the response is processed, the weather forecast information (as an array of [WeatherObject](#weatherobject)s) needs to be set with `this.setWeatherForecast(forecast);`.
|
||||||
|
It will then automatically refresh the module DOM with the new data.
|
||||||
|
|
||||||
|
#### `fetchWeatherHourly()`
|
||||||
|
|
||||||
|
This method is called when the weather module tries to fetch the weather of your provider. The implementation of this method is required for hourly support.
|
||||||
|
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
||||||
|
After the response is processed, the hourly weather forecast information (as an array of [WeatherObject](#weatherobject)s) needs to be set with `this.setWeatherHourly(forecast);`.
|
||||||
It will then automatically refresh the module DOM with the new data.
|
It will then automatically refresh the module DOM with the new data.
|
||||||
|
|
||||||
### Weather Provider instance methods
|
### Weather Provider instance methods
|
||||||
@ -63,6 +70,10 @@ This returns a WeatherDay object for the current weather.
|
|||||||
|
|
||||||
This returns an array of WeatherDay objects for the weather forecast.
|
This returns an array of WeatherDay objects for the weather forecast.
|
||||||
|
|
||||||
|
#### `weatherHourly()`
|
||||||
|
|
||||||
|
This returns an array of WeatherDay objects for the hourly weather forecast.
|
||||||
|
|
||||||
#### `fetchedLocation()`
|
#### `fetchedLocation()`
|
||||||
|
|
||||||
This returns the name of the fetched location or an empty string.
|
This returns the name of the fetched location or an empty string.
|
||||||
@ -75,6 +86,10 @@ Set the currentWeather and notify the delegate that new information is available
|
|||||||
|
|
||||||
Set the weatherForecastArray and notify the delegate that new information is available.
|
Set the weatherForecastArray and notify the delegate that new information is available.
|
||||||
|
|
||||||
|
#### `setWeatherHourly(weatherHourlyArray)`
|
||||||
|
|
||||||
|
Set the weatherHourlyArray and notify the delegate that new information is available.
|
||||||
|
|
||||||
#### `setFetchedLocation(name)`
|
#### `setFetchedLocation(name)`
|
||||||
|
|
||||||
Set the fetched location name.
|
Set the fetched location name.
|
||||||
|
@ -15,6 +15,15 @@ WeatherProvider.register("darksky", {
|
|||||||
// Not strictly required, but helps for debugging.
|
// Not strictly required, but helps for debugging.
|
||||||
providerName: "Dark Sky",
|
providerName: "Dark Sky",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
apiBase: "https://cors-anywhere.herokuapp.com/https://api.darksky.net",
|
||||||
|
weatherEndpoint: "/forecast",
|
||||||
|
apiKey: "",
|
||||||
|
lat: 0,
|
||||||
|
lon: 0
|
||||||
|
},
|
||||||
|
|
||||||
units: {
|
units: {
|
||||||
imperial: "us",
|
imperial: "us",
|
||||||
metric: "si"
|
metric: "si"
|
||||||
|
@ -14,6 +14,18 @@ WeatherProvider.register("openweathermap", {
|
|||||||
// 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.
|
||||||
providerName: "OpenWeatherMap",
|
providerName: "OpenWeatherMap",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
apiVersion: "2.5",
|
||||||
|
apiBase: "https://api.openweathermap.org/data/",
|
||||||
|
weatherEndpoint: "",
|
||||||
|
locationID: false,
|
||||||
|
location: false,
|
||||||
|
lat: 0,
|
||||||
|
lon: 0,
|
||||||
|
apiKey: ""
|
||||||
|
},
|
||||||
|
|
||||||
// Overwrite the fetchCurrentWeather method.
|
// Overwrite the fetchCurrentWeather method.
|
||||||
fetchCurrentWeather() {
|
fetchCurrentWeather() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
@ -56,8 +68,8 @@ WeatherProvider.register("openweathermap", {
|
|||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
},
|
},
|
||||||
|
|
||||||
// Overwrite the fetchWeatherData method.
|
// Overwrite the fetchWeatherHourly method.
|
||||||
fetchWeatherData() {
|
fetchWeatherHourly() {
|
||||||
this.fetchData(this.getUrl())
|
this.fetchData(this.getUrl())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@ -69,7 +81,7 @@ WeatherProvider.register("openweathermap", {
|
|||||||
this.setFetchedLocation(`(${data.lat},${data.lon})`);
|
this.setFetchedLocation(`(${data.lat},${data.lon})`);
|
||||||
|
|
||||||
const weatherData = this.generateWeatherObjectsFromOnecall(data);
|
const weatherData = this.generateWeatherObjectsFromOnecall(data);
|
||||||
this.setWeatherData(weatherData);
|
this.setWeatherHourly(weatherData.hours);
|
||||||
})
|
})
|
||||||
.catch(function (request) {
|
.catch(function (request) {
|
||||||
Log.error("Could not load data ... ", request);
|
Log.error("Could not load data ... ", request);
|
||||||
@ -77,6 +89,31 @@ WeatherProvider.register("openweathermap", {
|
|||||||
.finally(() => this.updateAvailable());
|
.finally(() => this.updateAvailable());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides method for setting config to check if endpoint is correct for hourly
|
||||||
|
*
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
setConfig(config) {
|
||||||
|
this.config = config;
|
||||||
|
if (!this.config.weatherEndpoint) {
|
||||||
|
switch (this.config.type) {
|
||||||
|
case "hourly":
|
||||||
|
this.config.weatherEndpoint = "/onecall";
|
||||||
|
break;
|
||||||
|
case "daily":
|
||||||
|
case "forecast":
|
||||||
|
this.config.weatherEndpoint = "/forecast";
|
||||||
|
break;
|
||||||
|
case "current":
|
||||||
|
this.config.weatherEndpoint = "/weather";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.error("weatherEndpoint not configured and could not resolve it based on type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/** OpenWeatherMap Specific Methods - These are not part of the default provider methods */
|
/** OpenWeatherMap Specific Methods - These are not part of the default provider methods */
|
||||||
/*
|
/*
|
||||||
* Gets the complete url for the request
|
* Gets the complete url for the request
|
||||||
|
@ -14,6 +14,13 @@
|
|||||||
WeatherProvider.register("smhi", {
|
WeatherProvider.register("smhi", {
|
||||||
providerName: "SMHI",
|
providerName: "SMHI",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
lat: 0,
|
||||||
|
lon: 0,
|
||||||
|
precipitationValue: "pmedian"
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements method in interface for fetching current weather
|
* Implements method in interface for fetching current weather
|
||||||
*/
|
*/
|
||||||
@ -55,7 +62,7 @@ WeatherProvider.register("smhi", {
|
|||||||
this.config = config;
|
this.config = config;
|
||||||
if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) == -1) {
|
if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) == -1) {
|
||||||
console.log("invalid or not set: " + config.precipitationValue);
|
console.log("invalid or not set: " + config.precipitationValue);
|
||||||
config.precipitationValue = "pmedian";
|
config.precipitationValue = this.defaults.precipitationValue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,6 +14,13 @@ WeatherProvider.register("ukmetoffice", {
|
|||||||
// 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.
|
||||||
providerName: "UK Met Office",
|
providerName: "UK Met Office",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
apiBase: "http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/",
|
||||||
|
locationID: false,
|
||||||
|
apiKey: ""
|
||||||
|
},
|
||||||
|
|
||||||
units: {
|
units: {
|
||||||
imperial: "us",
|
imperial: "us",
|
||||||
metric: "si"
|
metric: "si"
|
||||||
|
@ -44,6 +44,16 @@ WeatherProvider.register("ukmetofficedatahub", {
|
|||||||
// Set the name of the provider.
|
// Set the name of the provider.
|
||||||
providerName: "UK Met Office (DataHub)",
|
providerName: "UK Met Office (DataHub)",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
apiBase: "https://api-metoffice.apiconnect.ibmcloud.com/metoffice/production/v0/forecasts/point/",
|
||||||
|
apiKey: "",
|
||||||
|
apiSecret: "",
|
||||||
|
lat: 0,
|
||||||
|
lon: 0,
|
||||||
|
windUnits: "mph"
|
||||||
|
},
|
||||||
|
|
||||||
// Build URL with query strings according to DataHub API (https://metoffice.apiconnect.ibmcloud.com/metoffice/production/api)
|
// Build URL with query strings according to DataHub API (https://metoffice.apiconnect.ibmcloud.com/metoffice/production/api)
|
||||||
getUrl(forecastType) {
|
getUrl(forecastType) {
|
||||||
let queryStrings = "?";
|
let queryStrings = "?";
|
||||||
|
@ -14,6 +14,15 @@ WeatherProvider.register("weatherbit", {
|
|||||||
// Not strictly required, but helps for debugging.
|
// Not strictly required, but helps for debugging.
|
||||||
providerName: "Weatherbit",
|
providerName: "Weatherbit",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
apiBase: "https://api.weatherbit.io/v2.0",
|
||||||
|
weatherEndpoint: "/current",
|
||||||
|
apiKey: "",
|
||||||
|
lat: 0,
|
||||||
|
lon: 0
|
||||||
|
},
|
||||||
|
|
||||||
units: {
|
units: {
|
||||||
imperial: "I",
|
imperial: "I",
|
||||||
metric: "M"
|
metric: "M"
|
||||||
|
@ -19,6 +19,14 @@ WeatherProvider.register("weathergov", {
|
|||||||
// 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.
|
||||||
providerName: "Weather.gov",
|
providerName: "Weather.gov",
|
||||||
|
|
||||||
|
// Set the default config properties that is specific to this provider
|
||||||
|
defaults: {
|
||||||
|
apiBase: "https://api.weatherbit.io/v2.0",
|
||||||
|
weatherEndpoint: "/forecast",
|
||||||
|
lat: 0,
|
||||||
|
lon: 0
|
||||||
|
},
|
||||||
|
|
||||||
// Flag all needed URLs availability
|
// Flag all needed URLs availability
|
||||||
configURLs: false,
|
configURLs: false,
|
||||||
|
|
||||||
|
@ -12,10 +12,6 @@ Module.register("weather", {
|
|||||||
weatherProvider: "openweathermap",
|
weatherProvider: "openweathermap",
|
||||||
roundTemp: false,
|
roundTemp: false,
|
||||||
type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
|
type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
|
||||||
lat: 0,
|
|
||||||
lon: 0,
|
|
||||||
location: false,
|
|
||||||
locationID: false,
|
|
||||||
units: config.units,
|
units: config.units,
|
||||||
useKmh: false,
|
useKmh: false,
|
||||||
tempUnits: config.units,
|
tempUnits: config.units,
|
||||||
@ -40,20 +36,13 @@ Module.register("weather", {
|
|||||||
fade: true,
|
fade: true,
|
||||||
fadePoint: 0.25, // Start on 1/4th of the list.
|
fadePoint: 0.25, // Start on 1/4th of the list.
|
||||||
initialLoadDelay: 0, // 0 seconds delay
|
initialLoadDelay: 0, // 0 seconds delay
|
||||||
retryDelay: 2500,
|
|
||||||
apiKey: "",
|
|
||||||
apiSecret: "",
|
|
||||||
apiVersion: "2.5",
|
|
||||||
apiBase: "https://api.openweathermap.org/data/", // TODO: this should not be part of the weather.js file, but should be contained in the openweatherprovider
|
|
||||||
weatherEndpoint: "/weather",
|
|
||||||
appendLocationNameToHeader: true,
|
appendLocationNameToHeader: true,
|
||||||
calendarClass: "calendar",
|
calendarClass: "calendar",
|
||||||
tableClass: "small",
|
tableClass: "small",
|
||||||
onlyTemp: false,
|
onlyTemp: false,
|
||||||
showPrecipitationAmount: false,
|
showPrecipitationAmount: false,
|
||||||
colored: false,
|
colored: false,
|
||||||
showFeelsLike: true,
|
showFeelsLike: true
|
||||||
feelsLikeWithDegree: false
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Module properties.
|
// Module properties.
|
||||||
@ -89,8 +78,6 @@ Module.register("weather", {
|
|||||||
// Let the weather provider know we are starting.
|
// Let the weather provider know we are starting.
|
||||||
this.weatherProvider.start();
|
this.weatherProvider.start();
|
||||||
|
|
||||||
this.config.feelsLikeWithDegree = this.translate("FEELS").indexOf("{DEGREE}") > -1;
|
|
||||||
|
|
||||||
// Add custom filters
|
// Add custom filters
|
||||||
this.addFilters();
|
this.addFilters();
|
||||||
|
|
||||||
@ -133,8 +120,9 @@ Module.register("weather", {
|
|||||||
case "daily":
|
case "daily":
|
||||||
case "forecast":
|
case "forecast":
|
||||||
return `forecast.njk`;
|
return `forecast.njk`;
|
||||||
|
//Make the invalid values use the "Loading..." from forecast
|
||||||
default:
|
default:
|
||||||
return `${this.config.type.toLowerCase()}.njk`;
|
return `forecast.njk`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -144,7 +132,7 @@ Module.register("weather", {
|
|||||||
config: this.config,
|
config: this.config,
|
||||||
current: this.weatherProvider.currentWeather(),
|
current: this.weatherProvider.currentWeather(),
|
||||||
forecast: this.weatherProvider.weatherForecast(),
|
forecast: this.weatherProvider.weatherForecast(),
|
||||||
weatherData: this.weatherProvider.weatherData(),
|
hourly: this.weatherProvider.weatherHourly(),
|
||||||
indoor: {
|
indoor: {
|
||||||
humidity: this.indoorHumidity,
|
humidity: this.indoorHumidity,
|
||||||
temperature: this.indoorTemperature
|
temperature: this.indoorTemperature
|
||||||
@ -157,6 +145,10 @@ Module.register("weather", {
|
|||||||
Log.log("New weather information available.");
|
Log.log("New weather information available.");
|
||||||
this.updateDom(0);
|
this.updateDom(0);
|
||||||
this.scheduleUpdate();
|
this.scheduleUpdate();
|
||||||
|
|
||||||
|
if (this.weatherProvider.currentWeather()) {
|
||||||
|
this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType.replace("-", "_") });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
scheduleUpdate: function (delay = null) {
|
scheduleUpdate: function (delay = null) {
|
||||||
@ -166,19 +158,27 @@ Module.register("weather", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.config.weatherEndpoint === "/onecall") {
|
switch (this.config.type.toLowerCase()) {
|
||||||
this.weatherProvider.fetchWeatherData();
|
case "current":
|
||||||
} else if (this.config.type === "forecast") {
|
|
||||||
this.weatherProvider.fetchWeatherForecast();
|
|
||||||
} else {
|
|
||||||
this.weatherProvider.fetchCurrentWeather();
|
this.weatherProvider.fetchCurrentWeather();
|
||||||
|
break;
|
||||||
|
case "hourly":
|
||||||
|
this.weatherProvider.fetchWeatherHourly();
|
||||||
|
break;
|
||||||
|
case "daily":
|
||||||
|
case "forecast":
|
||||||
|
this.weatherProvider.fetchWeatherForecast();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.error(`Invalid type ${this.config.type} configured (must be one of 'current', 'hourly', 'daily' or 'forecast')`);
|
||||||
}
|
}
|
||||||
}, 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);
|
var roundValue = parseFloat(temperature).toFixed(decimals);
|
||||||
|
return roundValue === "-0" ? 0 : roundValue;
|
||||||
},
|
},
|
||||||
|
|
||||||
addFilters() {
|
addFilters() {
|
||||||
|
@ -11,12 +11,13 @@
|
|||||||
var WeatherProvider = Class.extend({
|
var WeatherProvider = Class.extend({
|
||||||
// Weather Provider Properties
|
// Weather Provider Properties
|
||||||
providerName: null,
|
providerName: null,
|
||||||
|
defaults: {},
|
||||||
|
|
||||||
// The following properties have accessor methods.
|
// The following properties have accessor methods.
|
||||||
// Try to not access them directly.
|
// Try to not access them directly.
|
||||||
currentWeatherObject: null,
|
currentWeatherObject: null,
|
||||||
weatherForecastArray: null,
|
weatherForecastArray: null,
|
||||||
weatherDataObject: null,
|
weatherHourlyArray: null,
|
||||||
fetchedLocationName: null,
|
fetchedLocationName: null,
|
||||||
|
|
||||||
// The following properties will be set automatically.
|
// The following properties will be set automatically.
|
||||||
@ -57,10 +58,10 @@ var WeatherProvider = Class.extend({
|
|||||||
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 method should start the API request to fetch the weather forecast.
|
// This method should start the API request to fetch the weather hourly.
|
||||||
// This method should definitely be overwritten in the provider.
|
// This method should definitely be overwritten in the provider.
|
||||||
fetchWeatherData: function () {
|
fetchWeatherHourly: function () {
|
||||||
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchWeatherData method.`);
|
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchWeatherHourly method.`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// This returns a WeatherDay object for the current weather.
|
// This returns a WeatherDay object for the current weather.
|
||||||
@ -74,8 +75,8 @@ var WeatherProvider = Class.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// This returns an object containing WeatherDay object(s) depending on the type of call.
|
// This returns an object containing WeatherDay object(s) depending on the type of call.
|
||||||
weatherData: function () {
|
weatherHourly: function () {
|
||||||
return this.weatherDataObject;
|
return this.weatherHourlyArray;
|
||||||
},
|
},
|
||||||
|
|
||||||
// This returns the name of the fetched location or an empty string.
|
// This returns the name of the fetched location or an empty string.
|
||||||
@ -95,9 +96,9 @@ var WeatherProvider = Class.extend({
|
|||||||
this.weatherForecastArray = weatherForecastArray;
|
this.weatherForecastArray = weatherForecastArray;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the weatherDataObject and notify the delegate that new information is available.
|
// Set the weatherHourlyArray and notify the delegate that new information is available.
|
||||||
setWeatherData: function (weatherDataObject) {
|
setWeatherHourly: function (weatherHourlyArray) {
|
||||||
this.weatherDataObject = weatherDataObject;
|
this.weatherHourlyArray = weatherHourlyArray;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the fetched location name.
|
// Set the fetched location name.
|
||||||
@ -154,10 +155,11 @@ WeatherProvider.register = function (providerIdentifier, providerDetails) {
|
|||||||
WeatherProvider.initialize = function (providerIdentifier, delegate) {
|
WeatherProvider.initialize = function (providerIdentifier, delegate) {
|
||||||
providerIdentifier = providerIdentifier.toLowerCase();
|
providerIdentifier = providerIdentifier.toLowerCase();
|
||||||
|
|
||||||
var provider = new WeatherProvider.providers[providerIdentifier]();
|
const provider = new WeatherProvider.providers[providerIdentifier]();
|
||||||
|
const config = Object.assign({}, provider.defaults, delegate.config);
|
||||||
|
|
||||||
provider.delegate = delegate;
|
provider.delegate = delegate;
|
||||||
provider.setConfig(delegate.config);
|
provider.setConfig(config);
|
||||||
|
|
||||||
provider.providerIdentifier = providerIdentifier;
|
provider.providerIdentifier = providerIdentifier;
|
||||||
if (!provider.providerName) {
|
if (!provider.providerName) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Module: Weather Forecast
|
# Module: Weather Forecast
|
||||||
|
|
||||||
|
> :warning: **This module is deprecated in favor of the [weather](https://docs.magicmirror.builders/modules/weather.html) module.**
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
9
modules/default/weatherforecast/node_helper.js
Normal file
9
modules/default/weatherforecast/node_helper.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const NodeHelper = require("node_helper");
|
||||||
|
const Log = require("logger");
|
||||||
|
|
||||||
|
module.exports = NodeHelper.create({
|
||||||
|
// Override start method.
|
||||||
|
start: function () {
|
||||||
|
Log.warn(`The module '${this.name}' is deprecated in favor of the 'weather'-module, please refer to the documentation for a migration path`);
|
||||||
|
}
|
||||||
|
});
|
@ -3,6 +3,8 @@
|
|||||||
*
|
*
|
||||||
* By Michael Teeuw https://michaelteeuw.nl
|
* By Michael Teeuw https://michaelteeuw.nl
|
||||||
* MIT Licensed.
|
* MIT Licensed.
|
||||||
|
*
|
||||||
|
* This module is deprecated. Any additional feature will no longer be merged.
|
||||||
*/
|
*/
|
||||||
Module.register("weatherforecast", {
|
Module.register("weatherforecast", {
|
||||||
// Default module config.
|
// Default module config.
|
||||||
@ -351,6 +353,13 @@ Module.register("weatherforecast", {
|
|||||||
this.forecast = [];
|
this.forecast = [];
|
||||||
var lastDay = null;
|
var lastDay = null;
|
||||||
var forecastData = {};
|
var forecastData = {};
|
||||||
|
var dayStarts = 8;
|
||||||
|
var dayEnds = 17;
|
||||||
|
|
||||||
|
if (data.city && data.city.sunrise && data.city.sunset) {
|
||||||
|
dayStarts = new Date(moment.unix(data.city.sunrise).locale("en").format("YYYY/MM/DD HH:mm:ss")).getHours();
|
||||||
|
dayEnds = new Date(moment.unix(data.city.sunset).locale("en").format("YYYY/MM/DD HH:mm:ss")).getHours();
|
||||||
|
}
|
||||||
|
|
||||||
// Handle different structs between forecast16 and onecall endpoints
|
// Handle different structs between forecast16 and onecall endpoints
|
||||||
var forecastList = null;
|
var forecastList = null;
|
||||||
@ -371,10 +380,10 @@ Module.register("weatherforecast", {
|
|||||||
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").toDate().getHours();
|
hour = new Date(moment(forecast.dt_txt).locale("en").format("YYYY-MM-DD HH:mm:ss")).getHours();
|
||||||
} else {
|
} else {
|
||||||
day = moment(forecast.dt, "X").format("ddd");
|
day = moment(forecast.dt, "X").format("ddd");
|
||||||
hour = moment(forecast.dt, "X").toDate().getHours();
|
hour = new Date(moment(forecast.dt, "X")).getHours();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (day !== lastDay) {
|
if (day !== lastDay) {
|
||||||
@ -400,7 +409,7 @@ Module.register("weatherforecast", {
|
|||||||
|
|
||||||
// Since we don't want an icon from the start of the day (in the middle of the night)
|
// Since we don't want an icon from the start of the day (in the middle of the night)
|
||||||
// we update the icon as long as it's somewhere during the day.
|
// we update the icon as long as it's somewhere during the day.
|
||||||
if (hour >= 8 && hour <= 17) {
|
if (hour > dayStarts && hour < dayEnds) {
|
||||||
forecastData.icon = this.config.iconTable[forecast.weather[0].icon];
|
forecastData.icon = this.config.iconTable[forecast.weather[0].icon];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,7 +471,8 @@ Module.register("weatherforecast", {
|
|||||||
*/
|
*/
|
||||||
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);
|
var roundValue = parseFloat(temperature).toFixed(decimals);
|
||||||
|
return roundValue === "-0" ? 0 : roundValue;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* processRain(forecast, allForecasts)
|
/* processRain(forecast, allForecasts)
|
||||||
|
5709
package-lock.json
generated
5709
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
49
package.json
49
package.json
@ -1,25 +1,26 @@
|
|||||||
{
|
{
|
||||||
"name": "magicmirror",
|
"name": "magicmirror",
|
||||||
"version": "2.14.0",
|
"version": "2.15.0-develop",
|
||||||
"description": "The open source modular smart mirror platform.",
|
"description": "The open source modular smart mirror platform.",
|
||||||
"main": "js/electron.js",
|
"main": "js/electron.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js",
|
"start": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js",
|
||||||
|
"start:dev": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js dev",
|
||||||
"server": "node ./serveronly",
|
"server": "node ./serveronly",
|
||||||
"install": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error",
|
"install": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error",
|
||||||
"install-fonts": "echo \"Installing fonts ...\n\" && cd fonts && npm install --loglevel=error",
|
"install-fonts": "echo \"Installing fonts ...\n\" && cd fonts && npm install --loglevel=error",
|
||||||
"postinstall": "npm run install-fonts && echo \"MagicMirror installation finished successfully! \n\"",
|
"postinstall": "npm run install-fonts && echo \"MagicMirror installation finished successfully! \n\"",
|
||||||
"test": "NODE_ENV=test mocha tests --recursive",
|
"test": "NODE_ENV=test mocha tests --recursive",
|
||||||
"test:coverage": "NODE_ENV=test nyc mocha tests --recursive --timeout=3000",
|
"test:coverage": "NODE_ENV=test nyc --reporter=lcov --reporter=text mocha tests --recursive --timeout=3000",
|
||||||
"test:e2e": "NODE_ENV=test mocha tests/e2e --recursive",
|
"test:e2e": "NODE_ENV=test mocha tests/e2e --recursive",
|
||||||
"test:unit": "NODE_ENV=test mocha tests/unit --recursive",
|
"test:unit": "NODE_ENV=test mocha tests/unit --recursive",
|
||||||
"test:prettier": "prettier --check **/*.{js,css,json,md,yml}",
|
"test:prettier": "prettier --check **/*.{js,css,json,md,yml}",
|
||||||
"test:js": "eslint *.js js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --quiet",
|
"test:js": "eslint js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --quiet",
|
||||||
"test:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json",
|
"test:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json",
|
||||||
"test:calendar": "node ./modules/default/calendar/debug.js",
|
"test:calendar": "node ./modules/default/calendar/debug.js",
|
||||||
"config:check": "node js/check_config.js",
|
"config:check": "node js/check_config.js",
|
||||||
"lint:prettier": "prettier --write **/*.{js,css,json,md,yml}",
|
"lint:prettier": "prettier --write **/*.{js,css,json,md,yml}",
|
||||||
"lint:js": "eslint *.js js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --fix",
|
"lint:js": "eslint js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --fix",
|
||||||
"lint:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json --fix"
|
"lint:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json --fix"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -42,53 +43,57 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://magicmirror.builders",
|
"homepage": "https://magicmirror.builders",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.3.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"danger": "^10.5.4",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-config-prettier": "^7.0.0",
|
"eslint-plugin-jsdoc": "^32.2.0",
|
||||||
"eslint-plugin-jsdoc": "^30.7.8",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-prettier": "^3.2.0",
|
|
||||||
"express-basic-auth": "^1.2.0",
|
"express-basic-auth": "^1.2.0",
|
||||||
"husky": "^4.3.5",
|
"husky": "^4.3.8",
|
||||||
"jsdom": "^16.4.0",
|
"jsdom": "^16.4.0",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.21",
|
||||||
"mocha": "^8.2.1",
|
"mocha": "^8.3.0",
|
||||||
"mocha-each": "^2.0.1",
|
"mocha-each": "^2.0.1",
|
||||||
"mocha-logger": "^1.0.7",
|
"mocha-logger": "^1.0.7",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"pretty-quick": "^3.1.0",
|
"pretty-quick": "^3.1.0",
|
||||||
"spectron": "^10.0.1",
|
"sinon": "^9.2.4",
|
||||||
"stylelint": "^13.8.0",
|
"spectron": "^13.0.0",
|
||||||
|
"stylelint": "^13.11.0",
|
||||||
"stylelint-config-prettier": "^8.0.2",
|
"stylelint-config-prettier": "^8.0.2",
|
||||||
"stylelint-config-standard": "^20.0.0",
|
"stylelint-config-standard": "^20.0.0",
|
||||||
"stylelint-prettier": "^1.1.2"
|
"stylelint-prettier": "^1.1.2"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"electron": "^8.5.3"
|
"electron": "^11.3.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"console-stamp": "^3.0.0-rc4.2",
|
"console-stamp": "^3.0.0-rc4.2",
|
||||||
"eslint": "^7.15.0",
|
"eslint": "^7.20.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-ipfilter": "^1.1.2",
|
"express-ipfilter": "^1.1.2",
|
||||||
"feedme": "^2.0.2",
|
"feedme": "^2.0.2",
|
||||||
"helmet": "^4.2.0",
|
"helmet": "^4.4.1",
|
||||||
"ical": "^0.8.0",
|
"ical": "^0.8.0",
|
||||||
"iconv-lite": "^0.6.2",
|
"iconv-lite": "^0.6.2",
|
||||||
"module-alias": "^2.2.2",
|
"module-alias": "^2.2.2",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"node-ical": "^0.12.7",
|
"node-ical": "^0.12.8",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"rrule": "^2.6.6",
|
"rrule": "^2.6.8",
|
||||||
"rrule-alt": "^2.2.8",
|
"rrule-alt": "^2.2.8",
|
||||||
"simple-git": "^2.31.0",
|
"simple-git": "^2.35.2",
|
||||||
"socket.io": "^3.0.4",
|
"socket.io": "^3.1.2",
|
||||||
"valid-url": "^1.0.9"
|
"valid-url": "^1.0.9"
|
||||||
},
|
},
|
||||||
"_moduleAliases": {
|
"_moduleAliases": {
|
||||||
"node_helper": "js/node_helper.js"
|
"node_helper": "js/node_helper.js",
|
||||||
|
"logger": "js/logger.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const app = require("../js/app.js");
|
const app = require("../js/app.js");
|
||||||
const Log = require("../js/logger.js");
|
const Log = require("logger");
|
||||||
|
|
||||||
app.start(function (config) {
|
app.start(function (config) {
|
||||||
var bindAddress = config.address ? config.address : "localhost";
|
var bindAddress = config.address ? config.address : "localhost";
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ var config = {
|
|||||||
calendars: [
|
calendars: [
|
||||||
{
|
{
|
||||||
maximumNumberOfDays: 10000,
|
maximumNumberOfDays: 10000,
|
||||||
url: "http://localhost:8011/tests/configs/data/calendar_test.ics",
|
url: "http://localhost:8080/tests/configs/data/calendar_test.ics",
|
||||||
auth: {
|
auth: {
|
||||||
user: "MagicMirror",
|
user: "MagicMirror",
|
||||||
pass: "CallMeADog"
|
pass: "CallMeADog"
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ var config = {
|
|||||||
calendars: [
|
calendars: [
|
||||||
{
|
{
|
||||||
maximumNumberOfDays: 10000,
|
maximumNumberOfDays: 10000,
|
||||||
url: "http://localhost:8010/tests/configs/data/calendar_test.ics",
|
url: "http://localhost:8080/tests/configs/data/calendar_test.ics",
|
||||||
auth: {
|
auth: {
|
||||||
user: "MagicMirror",
|
user: "MagicMirror",
|
||||||
pass: "CallMeADog",
|
pass: "CallMeADog",
|
||||||
|
44
tests/configs/modules/calendar/changed-port.js
Normal file
44
tests/configs/modules/calendar/changed-port.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* Magic Mirror Test config default calendar with auth by default
|
||||||
|
*
|
||||||
|
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 12,
|
||||||
|
units: "metric",
|
||||||
|
electronOptions: {
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "calendar",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
calendars: [
|
||||||
|
{
|
||||||
|
maximumNumberOfDays: 10000,
|
||||||
|
url: "http://localhost:8010/tests/configs/data/calendar_test.ics",
|
||||||
|
auth: {
|
||||||
|
user: "MagicMirror",
|
||||||
|
pass: "CallMeADog"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
@ -11,7 +11,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ var config = {
|
|||||||
calendars: [
|
calendars: [
|
||||||
{
|
{
|
||||||
maximumNumberOfDays: 10000,
|
maximumNumberOfDays: 10000,
|
||||||
url: "http://localhost:8012/tests/configs/data/calendar_test.ics",
|
url: "http://localhost:8080/tests/configs/data/calendar_test.ics",
|
||||||
user: "MagicMirror",
|
user: "MagicMirror",
|
||||||
pass: "CallMeADog"
|
pass: "CallMeADog"
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ var config = {
|
|||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
49
tests/configs/modules/weather/currentweather_compliments.js
Normal file
49
tests/configs/modules/weather/currentweather_compliments.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* Magic Mirror Test config current weather compliments
|
||||||
|
*
|
||||||
|
* By rejas https://github.com/rejas
|
||||||
|
*
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
port: 8080,
|
||||||
|
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||||
|
|
||||||
|
language: "en",
|
||||||
|
timeFormat: 24,
|
||||||
|
units: "metric",
|
||||||
|
electronOptions: {
|
||||||
|
fullscreen: false,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "compliments",
|
||||||
|
position: "top_bar",
|
||||||
|
config: {
|
||||||
|
compliments: {
|
||||||
|
snow: ["snow"]
|
||||||
|
},
|
||||||
|
updateInterval: 4000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
location: "Munich",
|
||||||
|
apiKey: "fake key",
|
||||||
|
initialLoadDelay: 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
@ -14,7 +14,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ let config = {
|
|||||||
units: "imperial",
|
units: "imperial",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ let config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ var config = {
|
|||||||
units: "metric",
|
units: "metric",
|
||||||
electronOptions: {
|
electronOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -31,26 +31,18 @@ describe("Electron app environment", function () {
|
|||||||
return helpers.stopApplication(app);
|
return helpers.stopApplication(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should open a browserwindow", function () {
|
it("should open a browserwindow", async function () {
|
||||||
return (
|
await app.client.waitUntilWindowLoaded();
|
||||||
app.client
|
app.browserWindow.focus();
|
||||||
.waitUntilWindowLoaded()
|
expect(await app.client.getWindowCount()).to.equal(1);
|
||||||
// .browserWindow.focus()
|
expect(await app.browserWindow.isMinimized()).to.be.false;
|
||||||
.getWindowCount()
|
expect(await app.browserWindow.isDevToolsOpened()).to.be.false;
|
||||||
.should.eventually.equal(1)
|
expect(await app.browserWindow.isVisible()).to.be.true;
|
||||||
.browserWindow.isMinimized()
|
expect(await app.browserWindow.isFocused()).to.be.true;
|
||||||
.should.eventually.be.false.browserWindow.isDevToolsOpened()
|
const bounds = await app.browserWindow.getBounds();
|
||||||
.should.eventually.be.false.browserWindow.isVisible()
|
expect(bounds.width).to.be.above(0);
|
||||||
.should.eventually.be.true.browserWindow.isFocused()
|
expect(bounds.height).to.be.above(0);
|
||||||
.should.eventually.be.true.browserWindow.getBounds()
|
expect(await app.browserWindow.getTitle()).to.equal("MagicMirror²");
|
||||||
.should.eventually.have.property("width")
|
|
||||||
.and.be.above(0)
|
|
||||||
.browserWindow.getBounds()
|
|
||||||
.should.eventually.have.property("height")
|
|
||||||
.and.be.above(0)
|
|
||||||
.browserWindow.getTitle()
|
|
||||||
.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) {
|
||||||
|
@ -20,7 +20,7 @@ global.before(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
exports.getElectronPath = function () {
|
exports.getElectronPath = function () {
|
||||||
var electronPath = path.join(__dirname, "..", "..", "node_modules", ".bin", "electron");
|
let electronPath = path.join(__dirname, "..", "..", "node_modules", ".bin", "electron");
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
electronPath += ".cmd";
|
electronPath += ".cmd";
|
||||||
}
|
}
|
||||||
@ -42,9 +42,9 @@ exports.startApplication = function (options) {
|
|||||||
options.startTimeout = 30000;
|
options.startTimeout = 30000;
|
||||||
}
|
}
|
||||||
|
|
||||||
var app = new Application(options);
|
const app = new Application(options);
|
||||||
return app.start().then(function () {
|
return app.start().then(function () {
|
||||||
assert.equal(app.isRunning(), true);
|
assert.strictEqual(app.isRunning(), true);
|
||||||
chaiAsPromised.transferPromiseness = app.transferPromiseness;
|
chaiAsPromised.transferPromiseness = app.transferPromiseness;
|
||||||
return app;
|
return app;
|
||||||
});
|
});
|
||||||
@ -56,6 +56,6 @@ exports.stopApplication = function (app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return app.stop().then(function () {
|
return app.stop().then(function () {
|
||||||
assert.equal(app.isRunning(), false);
|
assert.strictEqual(app.isRunning(), false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -76,11 +76,11 @@ describe("Calendar module", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Basic auth", function () {
|
describe("Changed port", 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/changed-port.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function (done) {
|
after(function (done) {
|
||||||
@ -92,17 +92,23 @@ describe("Calendar module", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Basic auth", function () {
|
||||||
|
before(function () {
|
||||||
|
// Set config sample for use in test
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/basic-auth.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return TestEvents", function () {
|
||||||
|
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);
|
|
||||||
// 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) {
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
@ -110,15 +116,10 @@ describe("Calendar module", function () {
|
|||||||
|
|
||||||
describe("Basic auth backward compatibility configuration: DEPRECATED", function () {
|
describe("Basic auth backward compatibility configuration: DEPRECATED", function () {
|
||||||
before(function () {
|
before(function () {
|
||||||
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) {
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -30,14 +30,16 @@ describe("Clock set to spanish language module", function () {
|
|||||||
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", async 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);
|
const elem = await app.client.$(".clock .date");
|
||||||
|
return elem.getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows time in 24hr format", function () {
|
it("shows time in 24hr format", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,14 +49,16 @@ describe("Clock set to spanish language module", function () {
|
|||||||
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", async 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);
|
const elem = await app.client.$(".clock .date");
|
||||||
|
return elem.getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows time in 12hr format", function () {
|
it("shows time in 12hr format", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,9 +68,10 @@ describe("Clock set to spanish language module", function () {
|
|||||||
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", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -76,9 +81,10 @@ describe("Clock set to spanish language module", function () {
|
|||||||
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", async function () {
|
||||||
const weekRegex = /^Semana [0-9]{1,2}$/;
|
const weekRegex = /^Semana [0-9]{1,2}$/;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .week").should.eventually.match(weekRegex);
|
const elem = await app.client.$(".clock .week");
|
||||||
|
elem.getText(".clock .week").should.eventually.match(weekRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -32,14 +32,16 @@ describe("Clock module", function () {
|
|||||||
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("should show the date in the correct format", function () {
|
it("should show the date in the correct format", async 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);
|
const elem = await app.client.$(".clock .date");
|
||||||
|
return elem.getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should show the time in 24hr format", function () {
|
it("should show the time in 24hr format", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -49,14 +51,16 @@ describe("Clock module", function () {
|
|||||||
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("should show the date in the correct format", function () {
|
it("should show the date in the correct format", async 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);
|
const elem = await app.client.$(".clock .date");
|
||||||
|
return elem.getText(".clock .date").should.eventually.match(dateRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should show the time in 12hr format", function () {
|
it("should show the time in 12hr format", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -66,9 +70,10 @@ describe("Clock module", function () {
|
|||||||
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("should show 12hr time with upper case AM/PM", function () {
|
it("should show 12hr time with upper case AM/PM", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -78,9 +83,10 @@ describe("Clock module", function () {
|
|||||||
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("should show 12hr time without seconds am/pm", function () {
|
it("should show 12hr time without seconds am/pm", async 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);
|
const elem = await app.client.$(".clock .time");
|
||||||
|
return elem.getText(".clock .time").should.eventually.match(timeRegex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -90,15 +96,17 @@ describe("Clock module", function () {
|
|||||||
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("should show the week in the correct format", function () {
|
it("should show the week in the correct format", async 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);
|
const elem = await app.client.$(".clock .week");
|
||||||
|
return elem.getText(".clock .week").should.eventually.match(weekRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should show the week with the correct number of week of year", function () {
|
it("should show the week with the correct number of week of year", async function () {
|
||||||
const currentWeekNumber = moment().week();
|
const currentWeekNumber = moment().week();
|
||||||
const weekToShow = "Week " + currentWeekNumber;
|
const weekToShow = "Week " + currentWeekNumber;
|
||||||
return app.client.waitUntilWindowLoaded().getText(".clock .week").should.eventually.equal(weekToShow);
|
const elem = await app.client.$(".clock .week");
|
||||||
|
return elem.getText(".clock .week").should.eventually.equal(weekToShow);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,40 +31,34 @@ describe("Compliments module", function () {
|
|||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_parts_day.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_parts_day.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("if Morning compliments for that part of day", function () {
|
it("if Morning compliments for that part of day", async function () {
|
||||||
var hour = new Date().getHours();
|
var hour = new Date().getHours();
|
||||||
if (hour >= 3 && hour < 12) {
|
if (hour >= 3 && hour < 12) {
|
||||||
// if morning check
|
// if morning check
|
||||||
return app.client
|
const elem = await app.client.$(".compliments");
|
||||||
.waitUntilWindowLoaded()
|
return elem.getText(".compliments").then(function (text) {
|
||||||
.getText(".compliments")
|
|
||||||
.then(function (text) {
|
|
||||||
expect(text).to.be.oneOf(["Hi", "Good Morning", "Morning test"]);
|
expect(text).to.be.oneOf(["Hi", "Good Morning", "Morning test"]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("if Afternoon show Compliments for that part of day", function () {
|
it("if Afternoon show Compliments for that part of day", async function () {
|
||||||
var hour = new Date().getHours();
|
var hour = new Date().getHours();
|
||||||
if (hour >= 12 && hour < 17) {
|
if (hour >= 12 && hour < 17) {
|
||||||
// if morning check
|
// if morning check
|
||||||
return app.client
|
const elem = await app.client.$(".compliments");
|
||||||
.waitUntilWindowLoaded()
|
return elem.getText(".compliments").then(function (text) {
|
||||||
.getText(".compliments")
|
|
||||||
.then(function (text) {
|
|
||||||
expect(text).to.be.oneOf(["Hello", "Good Afternoon", "Afternoon test"]);
|
expect(text).to.be.oneOf(["Hello", "Good Afternoon", "Afternoon test"]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("if Evening show Compliments for that part of day", function () {
|
it("if Evening show Compliments for that part of day", async function () {
|
||||||
var hour = new Date().getHours();
|
var hour = new Date().getHours();
|
||||||
if (!(hour >= 3 && hour < 12) && !(hour >= 12 && hour < 17)) {
|
if (!(hour >= 3 && hour < 12) && !(hour >= 12 && hour < 17)) {
|
||||||
// if evening check
|
// if evening check
|
||||||
return app.client
|
const elem = await app.client.$(".compliments");
|
||||||
.waitUntilWindowLoaded()
|
return elem.getText(".compliments").then(function (text) {
|
||||||
.getText(".compliments")
|
|
||||||
.then(function (text) {
|
|
||||||
expect(text).to.be.oneOf(["Hello There", "Good Evening", "Evening test"]);
|
expect(text).to.be.oneOf(["Hello There", "Good Evening", "Evening test"]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -78,11 +72,9 @@ describe("Compliments module", function () {
|
|||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_anytime.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_anytime.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Show anytime because if configure empty parts of day compliments and set anytime compliments", function () {
|
it("Show anytime because if configure empty parts of day compliments and set anytime compliments", async function () {
|
||||||
return app.client
|
const elem = await app.client.$(".compliments");
|
||||||
.waitUntilWindowLoaded()
|
return elem.getText(".compliments").then(function (text) {
|
||||||
.getText(".compliments")
|
|
||||||
.then(function (text) {
|
|
||||||
expect(text).to.be.oneOf(["Anytime here"]);
|
expect(text).to.be.oneOf(["Anytime here"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -94,11 +86,9 @@ describe("Compliments module", function () {
|
|||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_only_anytime.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_only_anytime.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Show anytime compliments", function () {
|
it("Show anytime compliments", async function () {
|
||||||
return app.client
|
const elem = await app.client.$(".compliments");
|
||||||
.waitUntilWindowLoaded()
|
return elem.getText(".compliments").then(function (text) {
|
||||||
.getText(".compliments")
|
|
||||||
.then(function (text) {
|
|
||||||
expect(text).to.be.oneOf(["Anytime here"]);
|
expect(text).to.be.oneOf(["Anytime here"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -112,11 +102,9 @@ describe("Compliments module", function () {
|
|||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_date.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_date.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Show happy new year compliment on new years day", function () {
|
it("Show happy new year compliment on new years day", async function () {
|
||||||
return app.client
|
const elem = await app.client.$(".compliments");
|
||||||
.waitUntilWindowLoaded()
|
return elem.getText(".compliments").then(function (text) {
|
||||||
.getText(".compliments")
|
|
||||||
.then(function (text) {
|
|
||||||
expect(text).to.be.oneOf(["Happy new year!"]);
|
expect(text).to.be.oneOf(["Happy new year!"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -30,8 +30,9 @@ describe("Test helloworld module", function () {
|
|||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/helloworld/helloworld.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/helloworld/helloworld.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Test message helloworld module", function () {
|
it("Test message helloworld module", async function () {
|
||||||
return app.client.waitUntilWindowLoaded().getText(".helloworld").should.eventually.equal("Test HelloWorld Module");
|
const elem = await app.client.$("helloworld");
|
||||||
|
return elem.getText(".helloworld").should.eventually.equal("Test HelloWorld Module");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -41,8 +42,9 @@ describe("Test helloworld module", function () {
|
|||||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/helloworld/helloworld_default.js";
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/helloworld/helloworld_default.js";
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Test message helloworld module", function () {
|
it("Test message helloworld module", async function () {
|
||||||
return app.client.waitUntilWindowLoaded().getText(".helloworld").should.eventually.equal("Hello World!");
|
const elem = await app.client.$("helloworld");
|
||||||
|
return elem.getText(".helloworld").should.eventually.equal("Hello World!");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user