Merge branch 'develop' into fix_suspend

This commit is contained in:
Michael Teeuw 2018-06-07 16:29:16 +02:00 committed by GitHub
commit 1e4b7599a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 376 additions and 4573 deletions

View File

@ -2,15 +2,49 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
[ unreleased] =======
### fixes ## [2.4.0] - Unreleased (Current Develop Branch)
- invoke module suspend even if no dom content. [#1308](https://github.com/MichMich/MagicMirror/issues/1308) *This release is scheduled to be released on 2018-07-01.*
⚠️ **Warning:** This release includes an updated version of Electron. This requires a Raspberry Pi configuration change to allow the best performance and prevent the CPU from overheating. Please read the information on the [MagicMirror Wiki](https://github.com/michmich/magicmirror/wiki/configuring-the-raspberry-pi#enable-the-open-gl-driver-to-decrease-electrons-cpu-usage).
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
### Added
- Enabled translation of feelsLike for module currentweather
- Added support for on-going calendar events
- Added scroll up in fullscreen newsfeed article view
- Changed fullscreen newsfeed width from 100% to 100vw (better results)
- Added option to calendar module that colors only the symbol instead of the whole line
- Added option for new display format in the calendar module with date headers with times/events below.
- Ability to fetch compliments from a remote server
- Add regex filtering to calendar module
### Changed
- Upgrade to Electron 2.0.0.
- Remove yarn-or-npm which breaks production builds.
- Invoke module suspend even if no dom content. [#1308](https://github.com/MichMich/MagicMirror/issues/1308)
### Fixed
- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MichMich/MagicMirror/issues/1247)
- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MichMich/MagicMirror/issues/1240)
- In default module currentWeather/currentWeather.js line 296, 300, self.config.animationSpeed can not be found because the notificationReceived function does not have "self" variable.
- Fixed browser-side code to work on the Midori browser.
- Fixed issue where heat index was reporting incorrect values in Celsius and Fahrenheit. [#1263](https://github.com/MichMich/MagicMirror/issues/1263)
- Fixed weatherforecast to use dt_txt field instead of dt to handle timezones better
- Newsfeed now remembers to show the description when `"ARTICLE_LESS_DETAILS"` is called if the user wants to always show the description. [#1282](https://github.com/MichMich/MagicMirror/issues/1282)
- `clientonly/*.js` is now linted, and one linting error is fixed
### Updated
- Updated Italian translation
- Updated German translation
- Updated Dutch translation
## [2.3.1] - 2018-04-01 ## [2.3.1] - 2018-04-01
### Fixed ### Fixed
- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MichMich/MagicMirror/issues/1243) - Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MichMich/MagicMirror/issues/1243)
## [2.3.0] - 2018-04-01 ## [2.3.0] - 2018-04-01

View File

@ -11,6 +11,7 @@ module.exports = function(grunt) {
"modules/default/*.js", "modules/default/*.js",
"modules/default/*/*.js", "modules/default/*/*.js",
"serveronly/*.js", "serveronly/*.js",
"clientonly/*.js",
"*.js", "*.js",
"tests/**/*.js", "tests/**/*.js",
"!modules/default/alert/notificationFx.js", "!modules/default/alert/notificationFx.js",

View File

@ -119,11 +119,11 @@ The following wiki links are helpful for the initial configuration of your Magic
### General ### General
1. Copy `config/config.js.sample` to `config/config.js`. \ 1. Copy `/home/pi/MagicMirror/config/config.js.sample` to `/home/pi/MagicMirror/config/config.js`. \
**Note:** If you used the installer script. This step is already done for you. **Note:** If you used the installer script. This step is already done for you.
2. Modify your required settings. \ 2. Modify your required settings. \
Note: You'll can check your configuration running `npm run config:check`. Note: You'll can check your configuration running `npm run config:check` in `/home/pi/MagicMirror`.
The following properties can be configured: The following properties can be configured:

View File

@ -88,7 +88,7 @@
process.stdout.write(`Client: ${err}`); process.stdout.write(`Client: ${err}`);
}); });
child.on('close', (code) => { child.on("close", (code) => {
if (code != 0) { if (code != 0) {
console.log(`There something wrong. The clientonly is not running code ${code}`); console.log(`There something wrong. The clientonly is not running code ${code}`);
} }

View File

@ -21,7 +21,7 @@ var MM = (function() {
var createDomObjects = function() { var createDomObjects = function() {
var domCreationPromises = []; var domCreationPromises = [];
modules.forEach(module => { modules.forEach(function(module) {
if (typeof module.data.position !== "string") { if (typeof module.data.position !== "string") {
return; return;
} }
@ -52,14 +52,14 @@ var MM = (function() {
var domCreationPromise = updateDom(module, 0); var domCreationPromise = updateDom(module, 0);
domCreationPromises.push(domCreationPromise); domCreationPromises.push(domCreationPromise);
domCreationPromise.then(() => { domCreationPromise.then(function() {
sendNotification("MODULE_DOM_CREATED", null, null, module); sendNotification("MODULE_DOM_CREATED", null, null, module);
}).catch(Log.error); }).catch(Log.error);
}); });
updateWrapperStates(); updateWrapperStates();
Promise.all(domCreationPromises).then(() => { Promise.all(domCreationPromises).then(function() {
sendNotification("DOM_OBJECTS_CREATED"); sendNotification("DOM_OBJECTS_CREATED");
}); });
}; };
@ -106,7 +106,7 @@ var MM = (function() {
* return Promise - Resolved when the dom is fully updated. * return Promise - Resolved when the dom is fully updated.
*/ */
var updateDom = function(module, speed) { var updateDom = function(module, speed) {
return new Promise((resolve) => { return new Promise(function(resolve) {
var newContentPromise = module.getDom(); var newContentPromise = module.getDom();
var newHeader = module.getHeader(); var newHeader = module.getHeader();
@ -115,7 +115,7 @@ var MM = (function() {
newContentPromise = Promise.resolve(newContentPromise); newContentPromise = Promise.resolve(newContentPromise);
} }
newContentPromise.then((newContent) => { newContentPromise.then(function(newContent) {
var updatePromise = updateDomWithContent(module, speed, newHeader, newContent); var updatePromise = updateDomWithContent(module, speed, newHeader, newContent);
updatePromise.then(resolve).catch(Log.error); updatePromise.then(resolve).catch(Log.error);
@ -134,7 +134,7 @@ var MM = (function() {
* return Promise - Resolved when the module dom has been updated. * return Promise - Resolved when the module dom has been updated.
*/ */
var updateDomWithContent = function(module, speed, newHeader, newContent) { var updateDomWithContent = function(module, speed, newHeader, newContent) {
return new Promise((resolve) => { return new Promise(function(resolve) {
if (module.hidden || !speed) { if (module.hidden || !speed) {
updateModuleContent(module, newHeader, newContent); updateModuleContent(module, newHeader, newContent);
resolve(); resolve();

View File

@ -81,15 +81,16 @@ var Module = Class.extend({
* return DomObject | Promise - The dom or a promise with the dom to display. * return DomObject | Promise - The dom or a promise with the dom to display.
*/ */
getDom: function () { getDom: function () {
return new Promise((resolve) => { var self = this;
return new Promise(function(resolve) {
var div = document.createElement("div"); var div = document.createElement("div");
var template = this.getTemplate(); var template = self.getTemplate();
var templateData = this.getTemplateData(); var templateData = self.getTemplateData();
// Check to see if we need to render a template string or a file. // Check to see if we need to render a template string or a file.
if (/^.*((\.html)|(\.njk))$/.test(template)) { if (/^.*((\.html)|(\.njk))$/.test(template)) {
// the template is a filename // the template is a filename
this.nunjucksEnvironment().render(template, templateData, function (err, res) { self.nunjucksEnvironment().render(template, templateData, function (err, res) {
if (err) { if (err) {
Log.error(err) Log.error(err)
} }
@ -100,7 +101,7 @@ var Module = Class.extend({
}); });
} else { } else {
// the template is a template string. // the template is a template string.
div.innerHTML = this.nunjucksEnvironment().renderString(template, templateData); div.innerHTML = self.nunjucksEnvironment().renderString(template, templateData);
resolve(div); resolve(div);
} }

View File

@ -110,11 +110,13 @@ Module.register("alert",{
}, },
hide_alert: function(sender) { hide_alert: function(sender) {
//Dismiss alert and remove from this.alerts //Dismiss alert and remove from this.alerts
if (this.alerts[sender.name]) {
this.alerts[sender.name].dismiss(); this.alerts[sender.name].dismiss();
this.alerts[sender.name] = null; this.alerts[sender.name] = null;
//Remove overlay //Remove overlay
var overlay = document.getElementById("overlay"); var overlay = document.getElementById("overlay");
overlay.parentNode.removeChild(overlay); overlay.parentNode.removeChild(overlay);
}
}, },
setPosition: function(pos) { setPosition: function(pos) {
//Add css to body depending on the set position for notifications //Add css to body depending on the set position for notifications

8
modules/default/calendar/README.md Normal file → Executable file
View File

@ -1,6 +1,7 @@
# Module: Calendar # Module: Calendar
The `calendar` module is one of the default modules of the MagicMirror. The `calendar` module is one of the default modules of the MagicMirror.
This module displays events from a public .ical calendar. It can combine multiple calendars. This module displays events from a public .ical calendar. It can combine multiple calendars.
Note that calendars may not contain any entry before 1st January 1970, otherwise the calendar won't be displayed and the module will crash.
## Using the module ## Using the module
@ -41,22 +42,25 @@ The following properties can be configured:
| `displayRepeatingCountTitle` | Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary") <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false` | `displayRepeatingCountTitle` | Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary") <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `dateFormat` | Format to use for the date of events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th) | `dateFormat` | Format to use for the date of events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
| `fullDayEventDateFormat` | Format to use for the date of full day events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th) | `fullDayEventDateFormat` | Format to use for the date of full day events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
| `timeFormat` | Display event times as absolute dates, or relative time <br><br> **Possible values:** `absolute` or `relative` <br> **Default value:** `relative` | `timeFormat` | Display event times as absolute dates, or relative time, or using absolute date headers with times for each event next to it <br><br> **Possible values:** `absolute` or `relative` or `dateheaders` <br> **Default value:** `relative`
| `getRelative` | How much time (in hours) should be left until calendar events start getting relative? <br><br> **Possible values:** `0` (events stay absolute) - `48` (48 hours before the event starts) <br> **Default value:** `6` | `getRelative` | How much time (in hours) should be left until calendar events start getting relative? <br><br> **Possible values:** `0` (events stay absolute) - `48` (48 hours before the event starts) <br> **Default value:** `6`
| `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates <br><br> **Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days) <br><br> **Default value:** `7` | `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates <br><br> **Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days) <br><br> **Default value:** `7`
| `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`. <br><br> **Possible values:** `true`, `false` <br><br> **Default value:** `true` | `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`. <br><br> **Possible values:** `true`, `false` <br><br> **Default value:** `true`
| `hidePrivate` | Hides private calendar events. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false` | `hidePrivate` | Hides private calendar events. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown. <br><br>Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.<br>**Required**<br>`filterBy` - string used to determine if filter is applied.<br>**Optional**<br>`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]<br>`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity<br><br> **Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}]` <br> **Default value:** `[]` | `hideOngoing` | Hides calendar events that have already started. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown. <br><br>Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.<br>**Required**<br>`filterBy` - string used to determine if filter is applied.<br>**Optional**<br>`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]<br>`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity<br>`regex` - set to `true` if filterBy is a regex. For those not familiar with regex it is used for pattern matching, please see [here](https://regexr.com/) for more info.<br><br> **Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}, {filterBy: '^[0-9]{1,}.*', regex: true}]` <br> **Default value:** `[]`
### Calendar configuration ### Calendar configuration
The `calendars` property contains an array of the configured calendars. The `calendars` property contains an array of the configured calendars.
The `colored` property gives the option for an individual color for each calendar. The `colored` property gives the option for an individual color for each calendar.
The `coloredSymbolOnly` property will apply color to the symbol only, not the whole line. This is only applicable when `colored` is also enabled.
#### Default value: #### Default value:
````javascript ````javascript
config: { config: {
colored: false, colored: false,
coloredSymbolOnly: false,
calendars: [ calendars: [
{ {
url: 'http://www.calendarlabs.com/templates/ical/US-Holidays.ics', url: 'http://www.calendarlabs.com/templates/ical/US-Holidays.ics',

90
modules/default/calendar/calendar.js Normal file → Executable file
View File

@ -29,7 +29,9 @@ Module.register("calendar", {
getRelative: 6, getRelative: 6,
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,
colored: false, colored: false,
coloredSymbolOnly: false,
calendars: [ calendars: [
{ {
symbol: "calendar", symbol: "calendar",
@ -130,11 +132,32 @@ Module.register("calendar", {
return wrapper; return wrapper;
} }
var lastSeenDate = "";
for (var e in events) { for (var e in events) {
var event = events[e]; var event = events[e];
var dateAsString = moment(event.startDate, "x").format(this.config.dateFormat);
if(this.config.timeFormat === "dateheaders"){
if(lastSeenDate !== dateAsString){
var dateRow = document.createElement("tr");
dateRow.className = "normal"
var dateCell = document.createElement("td");
dateCell.colSpan = "3";
dateCell.innerHTML = dateAsString;
dateRow.appendChild(dateCell);
wrapper.appendChild(dateRow);
lastSeenDate = dateAsString;
}
}
var eventWrapper = document.createElement("tr"); var eventWrapper = document.createElement("tr");
if (this.config.colored) { if (this.config.colored && !this.config.coloredSymbolOnly) {
eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url); eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
} }
@ -142,6 +165,11 @@ Module.register("calendar", {
if (this.config.displaySymbol) { if (this.config.displaySymbol) {
var symbolWrapper = document.createElement("td"); var symbolWrapper = document.createElement("td");
if (this.config.colored && this.config.coloredSymbolOnly) {
symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
}
symbolWrapper.className = "symbol align-right"; symbolWrapper.className = "symbol align-right";
var symbols = this.symbolsForUrl(event.url); var symbols = this.symbolsForUrl(event.url);
if(typeof symbols === "string") { if(typeof symbols === "string") {
@ -157,6 +185,10 @@ Module.register("calendar", {
symbolWrapper.appendChild(symbol); symbolWrapper.appendChild(symbol);
} }
eventWrapper.appendChild(symbolWrapper); eventWrapper.appendChild(symbolWrapper);
}else if(this.config.timeFormat === "dateheaders"){
var blankCell = document.createElement("td");
blankCell.innerHTML = "&nbsp;&nbsp;&nbsp;"
eventWrapper.appendChild(blankCell);
} }
var titleWrapper = document.createElement("td"), var titleWrapper = document.createElement("td"),
@ -182,9 +214,42 @@ Module.register("calendar", {
titleWrapper.className = "title"; titleWrapper.className = "title";
} }
eventWrapper.appendChild(titleWrapper); if(this.config.timeFormat === "dateheaders"){
if (event.fullDayEvent) {
titleWrapper.colSpan = "2";
titleWrapper.align = "left";
}else{
var timeWrapper = document.createElement("td"); var timeWrapper = document.createElement("td");
timeWrapper.className = "time light";
timeWrapper.align = "left";
timeWrapper.style.paddingLeft = "2px";
var timeFormatString = "";
switch (config.timeFormat) {
case 12: {
timeFormatString = "h:mm A";
break;
}
case 24: {
timeFormatString = "HH:mm";
break;
}
default: {
timeFormatString = "HH:mm";
break;
}
}
timeWrapper.innerHTML = moment(event.startDate, "x").format(timeFormatString);
eventWrapper.appendChild(timeWrapper);
titleWrapper.align = "right";
}
eventWrapper.appendChild(titleWrapper);
}else{
var timeWrapper = document.createElement("td");
eventWrapper.appendChild(titleWrapper);
//console.log(event.today); //console.log(event.today);
var now = new Date(); var now = new Date();
// Define second, minute, hour, and day variables // Define second, minute, hour, and day variables
@ -265,6 +330,7 @@ Module.register("calendar", {
//console.log(event); //console.log(event);
timeWrapper.className = "time light"; timeWrapper.className = "time light";
eventWrapper.appendChild(timeWrapper); eventWrapper.appendChild(timeWrapper);
}
wrapper.appendChild(eventWrapper); wrapper.appendChild(eventWrapper);
@ -336,6 +402,7 @@ Module.register("calendar", {
createEventList: function () { createEventList: function () {
var events = []; var events = [];
var today = moment().startOf("day"); var today = moment().startOf("day");
var now = new Date();
for (var c in this.calendarData) { for (var c in this.calendarData) {
var calendar = this.calendarData[c]; var calendar = this.calendarData[c];
for (var e in calendar) { for (var e in calendar) {
@ -346,6 +413,14 @@ Module.register("calendar", {
continue; continue;
} }
} }
if(this.config.hideOngoing) {
if(event.startDate < now) {
continue;
}
}
if(this.listContainsEvent(events,event)){
continue;
}
event.url = c; event.url = c;
event.today = event.startDate >= today && event.startDate < (today + 24 * 60 * 60 * 1000); event.today = event.startDate >= today && event.startDate < (today + 24 * 60 * 60 * 1000);
events.push(event); events.push(event);
@ -359,6 +434,17 @@ Module.register("calendar", {
return events.slice(0, this.config.maximumEntries); return events.slice(0, this.config.maximumEntries);
}, },
listContainsEvent: function(eventList, event){
for(let evt of eventList){
if(evt.title === event.title && parseInt(evt.startDate) === parseInt(event.startDate)){
return true;
}
}
return false;
},
/* createEventList(url) /* createEventList(url)
* Requests node helper to add calendar url. * Requests node helper to add calendar url.
* *

View File

@ -119,19 +119,29 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
for (var f in excludedEvents) { for (var f in excludedEvents) {
var filter = excludedEvents[f], var filter = excludedEvents[f],
testTitle = title.toLowerCase(), testTitle = title.toLowerCase(),
until = null; until = null,
useRegex = false,
regexFlags = "g";
if (filter instanceof Object) { if (filter instanceof Object) {
if (typeof filter.until !== "undefined") { if (typeof filter.until !== "undefined") {
until = filter.until; until = filter.until;
} }
if (typeof filter.regex !== "undefined") {
useRegex = filter.regex;
}
// If additional advanced filtering is added in, this section // If additional advanced filtering is added in, this section
// must remain last as we overwrite the filter object with the // must remain last as we overwrite the filter object with the
// filterBy string // filterBy string
if (filter.caseSensitive) { if (filter.caseSensitive) {
filter = filter.filterBy; filter = filter.filterBy;
testTitle = title; testTitle = title;
} else if (useRegex) {
filter = filter.filterBy;
testTitle = title;
regexFlags += "i";
} else { } else {
filter = filter.filterBy.toLowerCase(); filter = filter.filterBy.toLowerCase();
} }
@ -139,7 +149,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
filter = filter.toLowerCase(); filter = filter.toLowerCase();
} }
if (testTitle.includes(filter)) { if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) {
if (until) { if (until) {
dateFilter = until; dateFilter = until;
} else { } else {
@ -294,6 +304,22 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
return false; return false;
}; };
var testTitleByFilter = function (title, filter, useRegex, regexFlags) {
if (useRegex) {
// Assume if leading slash, there is also trailing slash
if (filter[0] === "/") {
// Strip leading and trailing slashes
filter = filter.substr(1).slice(0, -1);
}
filter = new RegExp(filter, regexFlags);
return filter.test(title);
} else {
return title.includes(filter);
}
}
/* public methods */ /* public methods */
/* startFetch() /* startFetch()

View File

@ -30,7 +30,7 @@ The following properties can be configured:
| `updateInterval` | How often does the compliment have to change? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `30000` (30 seconds) | `updateInterval` | How often does the compliment have to change? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `30000` (30 seconds)
| `fadeSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `4000` (4 seconds) | `fadeSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `4000` (4 seconds)
| `compliments` | The list of compliments. <br><br> **Possible values:** An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. See _compliment configuration_ below. <br> **Default value:** See _compliment configuration_ below. | `compliments` | The list of compliments. <br><br> **Possible values:** An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. See _compliment configuration_ below. <br> **Default value:** See _compliment configuration_ below.
| `remoteFile` | External file from which to load the compliments <br><br> **Possible values:** Path to a JSON file containing compliments, configured as per the value of the _compliments configuration_ (see below). An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. - `compliments.json` <br> **Default value:** `null` (Do not load from file) | `remoteFile` | External file from which to load the compliments <br><br> **Possible values:** Path or URL (starting with `http://` or `https://`) to a JSON file containing compliments, configured as per the value of the _compliments configuration_ (see below). An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. - `compliments.json` <br> **Default value:** `null` (Do not load from file)
| `classes` | Override the CSS classes of the div showing the compliments <br><br> **Default value:** `thin xlarge bright` | `classes` | Override the CSS classes of the div showing the compliments <br><br> **Default value:** `thin xlarge bright`
| `morningStartTime` | Time in hours (in 24 format), after which the mode of "morning" will begin <br> **Possible values:** `0` - `24` <br><br> **Default value:** `3` | `morningStartTime` | Time in hours (in 24 format), after which the mode of "morning" will begin <br> **Possible values:** `0` - `24` <br><br> **Default value:** `3`
| `morningEndTime` | Time in hours (in 24 format), after which the mode of "morning" will end <br> **Possible values:** `0` - `24` <br><br> **Default value:** `12` | `morningEndTime` | Time in hours (in 24 format), after which the mode of "morning" will end <br> **Possible values:** `0` - `24` <br><br> **Default value:** `12`

View File

@ -55,8 +55,8 @@ Module.register("compliments", {
var self = this; var self = this;
if (this.config.remoteFile != null) { if (this.config.remoteFile != null) {
this.complimentFile((response) => { this.complimentFile(function(response) {
this.config.compliments = JSON.parse(response); self.config.compliments = JSON.parse(response);
self.updateDom(); self.updateDom();
}); });
} }
@ -128,9 +128,11 @@ Module.register("compliments", {
* Retrieve a file from the local filesystem * Retrieve a file from the local filesystem
*/ */
complimentFile: function(callback) { complimentFile: function(callback) {
var xobj = new XMLHttpRequest(); var xobj = new XMLHttpRequest(),
isRemote = this.config.remoteFile.indexOf("http://") === 0 || this.config.remoteFile.indexOf("https://") === 0,
path = isRemote ? this.config.remoteFile : this.file(this.config.remoteFile);
xobj.overrideMimeType("application/json"); xobj.overrideMimeType("application/json");
xobj.open("GET", this.file(this.config.remoteFile), true); xobj.open("GET", path, true);
xobj.onreadystatechange = function() { xobj.onreadystatechange = function() {
if (xobj.readyState == 4 && xobj.status == "200") { if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText); callback(xobj.responseText);

View File

@ -67,7 +67,7 @@ Module.register("currentweather",{
}, },
}, },
// create a variable for the first upcoming calendaar event. Used if no location is specified. // create a variable for the first upcoming calendar event. Used if no location is specified.
firstEvent: false, firstEvent: false,
// create a variable to hold the location name based on the API result. // create a variable to hold the location name based on the API result.
@ -87,7 +87,7 @@ Module.register("currentweather",{
getTranslations: function() { getTranslations: function() {
// The translations for the default modules are defined in the core translation files. // The translations for the default modules are defined in the core translation files.
// Therefor we can just return false. Otherwise we should have returned a dictionary. // Therefor we can just return false. Otherwise we should have returned a dictionary.
// If you're trying to build yiur own module including translations, check out the documentation. // If you're trying to build your own module including translations, check out the documentation.
return false; return false;
}, },
@ -251,7 +251,7 @@ Module.register("currentweather",{
var feelsLike = document.createElement("span"); var feelsLike = document.createElement("span");
feelsLike.className = "dimmed"; feelsLike.className = "dimmed";
feelsLike.innerHTML = "Feels " + this.feelsLike + "&deg;" + degreeLabel; feelsLike.innerHTML = this.translate("FEELS") + " " + this.feelsLike + "&deg;" + degreeLabel;
small.appendChild(feelsLike); small.appendChild(feelsLike);
wrapper.appendChild(small); wrapper.appendChild(small);
@ -293,11 +293,11 @@ Module.register("currentweather",{
} }
if (notification === "INDOOR_TEMPERATURE") { if (notification === "INDOOR_TEMPERATURE") {
this.indoorTemperature = this.roundValue(payload); this.indoorTemperature = this.roundValue(payload);
this.updateDom(self.config.animationSpeed); this.updateDom(this.config.animationSpeed);
} }
if (notification === "INDOOR_HUMIDITY") { if (notification === "INDOOR_HUMIDITY") {
this.indoorHumidity = this.roundValue(payload); this.indoorHumidity = this.roundValue(payload);
this.updateDom(self.config.animationSpeed); this.updateDom(this.config.animationSpeed);
} }
}, },
@ -407,8 +407,8 @@ Module.register("currentweather",{
if (windInMph > 3 && tempInF < 50){ if (windInMph > 3 && tempInF < 50){
// windchill // windchill
var windchillinF = Math.round(35.74+0.6215*tempInF-35.75*Math.pow(windInMph,0.16)+0.4275*tempInF*Math.pow(windInMph,0.16)); var windChillInF = Math.round(35.74+0.6215*tempInF-35.75*Math.pow(windInMph,0.16)+0.4275*tempInF*Math.pow(windInMph,0.16));
var windChillInC = (windchillinF - 32) * (5/9); var windChillInC = (windChillInF - 32) * (5/9);
// this.feelsLike = windChillInC.toFixed(0); // this.feelsLike = windChillInC.toFixed(0);
switch (this.config.units){ switch (this.config.units){
@ -432,9 +432,9 @@ Module.register("currentweather",{
- 1.99*Math.pow(10,-6)*tempInF*tempInF*this.humidity*this.humidity; - 1.99*Math.pow(10,-6)*tempInF*tempInF*this.humidity*this.humidity;
switch (this.config.units){ switch (this.config.units){
case "metric": this.feelsLike = Hindex.toFixed(0); case "metric": this.feelsLike = parseFloat((Hindex - 32) / 1.8).toFixed(0);
break; break;
case "imperial": this.feelsLike = parseFloat(Hindex * 1.8 + 32).toFixed(0); case "imperial": this.feelsLike = Hindex.toFixed(0);
break; break;
case "default": case "default":
var tc = Hindex - 273.15; var tc = Hindex - 273.15;

View File

@ -67,6 +67,7 @@ Module.register("newsfeed",{
this.registerFeeds(); this.registerFeeds();
this.isShowingDescription = this.config.showDescription;
}, },
// Override socket notification handler. // Override socket notification handler.
@ -133,7 +134,7 @@ Module.register("newsfeed",{
if (this.config.removeStartTags == "description" || this.config.removeStartTags == "both") { if (this.config.removeStartTags == "description" || this.config.removeStartTags == "both") {
if (this.config.showDescription) { if (this.isShowingDescription) {
for (f=0; f<this.config.startTags.length;f++) { for (f=0; f<this.config.startTags.length;f++) {
if (this.newsItems[this.activeItem].description.slice(0,this.config.startTags[f].length) == this.config.startTags[f]) { if (this.newsItems[this.activeItem].description.slice(0,this.config.startTags[f].length) == this.config.startTags[f]) {
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].description.slice(this.config.startTags[f].length,this.newsItems[this.activeItem].description.length); this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].description.slice(this.config.startTags[f].length,this.newsItems[this.activeItem].description.length);
@ -152,7 +153,7 @@ Module.register("newsfeed",{
} }
} }
if (this.config.showDescription) { if (this.isShowingDescription) {
for (f=0; f<this.config.endTags.length;f++) { for (f=0; f<this.config.endTags.length;f++) {
if (this.newsItems[this.activeItem].description.slice(-this.config.endTags[f].length)==this.config.endTags[f]) { if (this.newsItems[this.activeItem].description.slice(-this.config.endTags[f].length)==this.config.endTags[f]) {
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(0,-this.config.endTags[f].length); this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(0,-this.config.endTags[f].length);
@ -169,7 +170,7 @@ Module.register("newsfeed",{
wrapper.appendChild(title); wrapper.appendChild(title);
} }
if (this.config.showDescription) { if (this.isShowingDescription) {
var description = document.createElement("div"); var description = document.createElement("div");
description.className = "small light" + (!this.config.wrapDescription ? " no-wrap" : ""); description.className = "small light" + (!this.config.wrapDescription ? " no-wrap" : "");
var txtDesc = this.newsItems[this.activeItem].description; var txtDesc = this.newsItems[this.activeItem].description;
@ -180,10 +181,10 @@ Module.register("newsfeed",{
if (this.config.showFullArticle) { if (this.config.showFullArticle) {
var fullArticle = document.createElement("iframe"); var fullArticle = document.createElement("iframe");
fullArticle.className = ""; fullArticle.className = "";
fullArticle.style.width = "100%"; fullArticle.style.width = "100vw";
// very large height value to allow scrolling // very large height value to allow scrolling
fullArticle.height = "10000"; fullArticle.height = "3000";
fullArticle.style.height = "10000"; fullArticle.style.height = "3000";
fullArticle.style.top = "0"; fullArticle.style.top = "0";
fullArticle.style.left = "0"; fullArticle.style.left = "0";
fullArticle.style.border = "none"; fullArticle.style.border = "none";
@ -323,7 +324,7 @@ Module.register("newsfeed",{
}, },
resetDescrOrFullArticleAndTimer: function() { resetDescrOrFullArticleAndTimer: function() {
this.config.showDescription = false; this.isShowingDescription = this.config.showDescription;
this.config.showFullArticle = false; this.config.showFullArticle = false;
this.scrollPosition = 0; this.scrollPosition = 0;
// reset bottom bar alignment // reset bottom bar alignment
@ -366,8 +367,8 @@ Module.register("newsfeed",{
} }
// display full article // display full article
else { else {
this.config.showDescription = !this.config.showDescription; this.isShowingDescription = !this.isShowingDescription;
this.config.showFullArticle = !this.config.showDescription; this.config.showFullArticle = !this.isShowingDescription;
// make bottom bar align to top to allow scrolling // make bottom bar align to top to allow scrolling
if(this.config.showFullArticle == true){ if(this.config.showFullArticle == true){
document.getElementsByClassName("region bottom bar")[0].style.bottom = "inherit"; document.getElementsByClassName("region bottom bar")[0].style.bottom = "inherit";
@ -375,9 +376,16 @@ Module.register("newsfeed",{
} }
clearInterval(timer); clearInterval(timer);
timer = null; timer = null;
Log.info(this.name + " - showing " + this.config.showDescription ? "article description" : "full article"); Log.info(this.name + " - showing " + this.isShowingDescription ? "article description" : "full article");
this.updateDom(100); this.updateDom(100);
} }
} else if(notification == "ARTICLE_SCROLL_UP"){
if(this.config.showFullArticle == true){
this.scrollPosition -= this.config.scrollLength;
window.scrollTo(0, this.scrollPosition);
Log.info(this.name + " - scrolling up");
Log.info(this.name + " - ARTICLE_SCROLL_UP, scroll position: " + this.config.scrollLength);
}
} else if(notification == "ARTICLE_LESS_DETAILS"){ } else if(notification == "ARTICLE_LESS_DETAILS"){
this.resetDescrOrFullArticleAndTimer(); this.resetDescrOrFullArticleAndTimer();
Log.info(this.name + " - showing only article titles again"); Log.info(this.name + " - showing only article titles again");

View File

@ -333,8 +333,8 @@ Module.register("weatherforecast",{
var forecast = data.list[i]; var forecast = data.list[i];
this.parserDataWeather(forecast); // hack issue #1017 this.parserDataWeather(forecast); // hack issue #1017
var day = moment(forecast.dt, "X").format("ddd"); var day = moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss").format("ddd");
var hour = moment(forecast.dt, "X").format("H"); var hour = moment(forecast.dt_txt, "YYYY-MM-DD hh:mm:ss").format("H");
if (day !== lastDay) { if (day !== lastDay) {
var forecastData = { var forecastData = {

112
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "magicmirror", "name": "magicmirror",
"version": "2.3.1", "version": "2.4.0-dev",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -38,9 +38,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "7.0.57", "version": "8.10.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.57.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.14.tgz",
"integrity": "sha512-Iikf0IAus1OX++3Jrc1R2bsZggO+m22G5ee56JccYKejx5GNT3nHhY8v6J4OXId1hXXlb0n45hcaVwZwQcZZ6w==" "integrity": "sha512-TKQqQIaYNO+8MrOsFgobkt3fbMzkfXhBFKcg20Nip5Omptw1HOY/IEvYiFtMwIbr7Me/Y2H/JO+TgNUMJ9NGjA=="
}, },
"JSV": { "JSV": {
"version": "4.0.2", "version": "4.0.2",
@ -616,6 +616,11 @@
"ms": "2.0.0" "ms": "2.0.0"
} }
}, },
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
},
"qs": { "qs": {
"version": "6.5.1", "version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
@ -1572,11 +1577,11 @@
"dev": true "dev": true
}, },
"electron": { "electron": {
"version": "1.7.13", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-1.7.13.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-2.0.0.tgz",
"integrity": "sha1-EIUbrsd9aG2VgS80QlwX5IrBQT8=", "integrity": "sha512-FCcVzHgoBmNTPUEhKN7yUxjluCRNAQsHNOfdtFEWKL3DPYEdLdyQW8CpmJEMqIXha5qZ+qdKVAtwvvuJs+b/PQ==",
"requires": { "requires": {
"@types/node": "7.0.57", "@types/node": "8.10.14",
"electron-download": "3.3.0", "electron-download": "3.3.0",
"extract-zip": "1.6.5" "extract-zip": "1.6.5"
} }
@ -1614,7 +1619,7 @@
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
"dev": true, "dev": true,
"requires": { "requires": {
"iconv-lite": "0.4.19" "iconv-lite": "0.4.23"
} }
}, },
"end-of-stream": { "end-of-stream": {
@ -2215,7 +2220,7 @@
"integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=",
"dev": true, "dev": true,
"requires": { "requires": {
"iconv-lite": "0.4.19", "iconv-lite": "0.4.23",
"jschardet": "1.5.1", "jschardet": "1.5.1",
"tmp": "0.0.31" "tmp": "0.0.31"
} }
@ -2624,7 +2629,7 @@
"grunt-known-options": "1.1.0", "grunt-known-options": "1.1.0",
"grunt-legacy-log": "1.0.1", "grunt-legacy-log": "1.0.1",
"grunt-legacy-util": "1.0.0", "grunt-legacy-util": "1.0.0",
"iconv-lite": "0.4.19", "iconv-lite": "0.4.23",
"js-yaml": "3.5.5", "js-yaml": "3.5.5",
"minimatch": "3.0.4", "minimatch": "3.0.4",
"nopt": "3.0.6", "nopt": "3.0.6",
@ -2672,37 +2677,43 @@
"integrity": "sha512-VZlDOLrB2KKefDDcx/wR8rEEz7smDwDKVblmooa+itdt/2jWw3ee2AiZB5Ap4s4AoRY0pbHRjZ3HHwY8uKR9Rw==", "integrity": "sha512-VZlDOLrB2KKefDDcx/wR8rEEz7smDwDKVblmooa+itdt/2jWw3ee2AiZB5Ap4s4AoRY0pbHRjZ3HHwY8uKR9Rw==",
"dev": true, "dev": true,
"requires": { "requires": {
"chalk": "2.3.0", "chalk": "2.3.2",
"eslint": "4.16.0" "eslint": "4.16.0"
}, },
"dependencies": { "dependencies": {
"ansi-styles": { "ansi-styles": {
"version": "3.2.0", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true, "dev": true,
"requires": { "requires": {
"color-convert": "1.9.0" "color-convert": "1.9.0"
} }
}, },
"chalk": { "chalk": {
"version": "2.3.0", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
"integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-styles": "3.2.0", "ansi-styles": "3.2.1",
"escape-string-regexp": "1.0.5", "escape-string-regexp": "1.0.5",
"supports-color": "4.5.0" "supports-color": "5.3.0"
} }
}, },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"supports-color": { "supports-color": {
"version": "4.5.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==",
"dev": true, "dev": true,
"requires": { "requires": {
"has-flag": "2.0.0" "has-flag": "3.0.0"
} }
} }
} }
@ -2841,7 +2852,7 @@
"requires": { "requires": {
"async": "2.6.0", "async": "2.6.0",
"chalk": "1.1.3", "chalk": "1.1.3",
"js-yaml": "3.10.0" "js-yaml": "3.11.0"
}, },
"dependencies": { "dependencies": {
"async": { "async": {
@ -2850,7 +2861,7 @@
"integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
"dev": true, "dev": true,
"requires": { "requires": {
"lodash": "4.17.4" "lodash": "4.17.5"
} }
}, },
"esprima": { "esprima": {
@ -2860,9 +2871,9 @@
"dev": true "dev": true
}, },
"js-yaml": { "js-yaml": {
"version": "3.10.0", "version": "3.11.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
"integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
"dev": true, "dev": true,
"requires": { "requires": {
"argparse": "1.0.9", "argparse": "1.0.9",
@ -2870,9 +2881,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.4", "version": "4.17.5",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
"dev": true "dev": true
} }
} }
@ -3128,9 +3139,12 @@
"dev": true "dev": true
}, },
"iconv-lite": { "iconv-lite": {
"version": "0.4.19", "version": "0.4.23",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
"requires": {
"safer-buffer": "2.1.2"
}
}, },
"ienoopen": { "ienoopen": {
"version": "1.0.0", "version": "1.0.0",
@ -5793,6 +5807,11 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
}, },
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sax": { "sax": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@ -7130,9 +7149,9 @@
} }
}, },
"walk": { "walk": {
"version": "2.3.9", "version": "2.3.13",
"resolved": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.13.tgz",
"integrity": "sha1-MbTbZnjyrgHDnqn7hyWpAx5Vins=", "integrity": "sha512-78SMe7To9U7kqVhSoGho3GfspA089ZDBIj2f8jElg2hi6lUCoagtDJ8sSMFNlpAh5Ib8Jt1gQ6Y7gh9mzHtFng==",
"requires": { "requires": {
"foreachasync": "3.0.0" "foreachasync": "3.0.0"
} }
@ -7332,6 +7351,14 @@
"dev": true, "dev": true,
"requires": { "requires": {
"iconv-lite": "0.4.19" "iconv-lite": "0.4.19"
},
"dependencies": {
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
"dev": true
}
} }
}, },
"whatwg-url": { "whatwg-url": {
@ -7465,15 +7492,6 @@
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true "dev": true
}, },
"yarn-or-npm": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/yarn-or-npm/-/yarn-or-npm-2.0.4.tgz",
"integrity": "sha1-RuOKr850w1DmwMynJxL8p0EPrZg=",
"dev": true,
"requires": {
"cross-spawn": "5.1.0"
}
},
"yauzl": { "yauzl": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",

View File

@ -1,13 +1,13 @@
{ {
"name": "magicmirror", "name": "magicmirror",
"version": "2.3.1", "version": "2.4.0-dev",
"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": "sh run-start.sh", "start": "sh run-start.sh",
"install": "cd vendor && yon install", "install": "cd vendor && npm install",
"install-fonts": "cd fonts && yon install", "install-fonts": "cd fonts && npm install",
"postinstall": "sh installers/postinstall/postinstall.sh && yon run install-fonts", "postinstall": "sh installers/postinstall/postinstall.sh && npm run install-fonts",
"test": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests --recursive", "test": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests --recursive",
"test:unit": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/unit --recursive", "test:unit": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/unit --recursive",
"test:e2e": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/e2e --recursive", "test:e2e": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/e2e --recursive",
@ -52,13 +52,12 @@
"spectron": "3.7.x", "spectron": "3.7.x",
"stylelint": "^8.4.0", "stylelint": "^8.4.0",
"stylelint-config-standard": "latest", "stylelint-config-standard": "latest",
"time-grunt": "latest", "time-grunt": "latest"
"yarn-or-npm": "^2.0.4"
}, },
"dependencies": { "dependencies": {
"body-parser": "^1.18.2", "body-parser": "^1.18.2",
"colors": "^1.1.2", "colors": "^1.1.2",
"electron": "^1.4.15", "electron": "^2.0.0",
"express": "^4.16.2", "express": "^4.16.2",
"express-ipfilter": "0.3.1", "express-ipfilter": "0.3.1",
"feedme": "latest", "feedme": "latest",

View File

@ -28,5 +28,7 @@
"UPDATE_NOTIFICATION": "Aktualisierung für MagicMirror² verfügbar.", "UPDATE_NOTIFICATION": "Aktualisierung für MagicMirror² verfügbar.",
"UPDATE_NOTIFICATION_MODULE": "Aktualisierung für das {MODULE_NAME} Modul verfügbar.", "UPDATE_NOTIFICATION_MODULE": "Aktualisierung für das {MODULE_NAME} Modul verfügbar.",
"UPDATE_INFO": "Die aktuelle Installation ist {COMMIT_COUNT} hinter dem {BRANCH_NAME} branch." "UPDATE_INFO": "Die aktuelle Installation ist {COMMIT_COUNT} hinter dem {BRANCH_NAME} Branch.",
"FEELS": "Gefühlt"
} }

View File

@ -28,5 +28,7 @@
"UPDATE_NOTIFICATION": "MagicMirror² update available.", "UPDATE_NOTIFICATION": "MagicMirror² update available.",
"UPDATE_NOTIFICATION_MODULE": "Update available for {MODULE_NAME} module.", "UPDATE_NOTIFICATION_MODULE": "Update available for {MODULE_NAME} module.",
"UPDATE_INFO": "The current installation is {COMMIT_COUNT} behind on the {BRANCH_NAME} branch." "UPDATE_INFO": "The current installation is {COMMIT_COUNT} behind on the {BRANCH_NAME} branch.",
"FEELS": "Feels"
} }

View File

@ -3,8 +3,11 @@
"TODAY": "Oggi", "TODAY": "Oggi",
"TOMORROW": "Domani", "TOMORROW": "Domani",
"DAYAFTERTOMORROW": "Dopodomani",
"RUNNING": "Termina entro", "RUNNING": "Termina entro",
"EMPTY": "Nessun evento in arrivo.", "EMPTY": "Nessun evento imminente.",
"WEEK": "Settimana {weekNumber}",
"N": "N", "N": "N",
"NNE": "NNE", "NNE": "NNE",
@ -15,11 +18,15 @@
"SE": "SE", "SE": "SE",
"SSE": "SSE", "SSE": "SSE",
"S": "S", "S": "S",
"SSW": "SSW", "SSW": "SSO",
"SW": "SW", "SW": "SO",
"WSW": "WSW", "WSW": "OSO",
"W": "W", "W": "O",
"WNW": "WNW", "WNW": "ONO",
"NW": "NW", "NW": "NO",
"NNW": "NNW" "NNW": "NNO",
"UPDATE_NOTIFICATION": "E' disponibile un aggiornamento di MagicMirror².",
"UPDATE_NOTIFICATION_MODULE": "E' disponibile un aggiornamento del modulo {MODULE_NAME}.",
"UPDATE_INFO": "L'installazione è {COMMIT_COUNT} indietro rispetto all'attuale branch {BRANCH_NAME}."
} }

View File

@ -26,5 +26,7 @@
"UPDATE_NOTIFICATION": "MagicMirror² update beschikbaar.", "UPDATE_NOTIFICATION": "MagicMirror² update beschikbaar.",
"UPDATE_NOTIFICATION_MODULE": "Update beschikbaar voor {MODULE_NAME} module.", "UPDATE_NOTIFICATION_MODULE": "Update beschikbaar voor {MODULE_NAME} module.",
"UPDATE_INFO": "De huidige installatie loopt {COMMIT_COUNT} achter op de {BRANCH_NAME} branch." "UPDATE_INFO": "De huidige installatie loopt {COMMIT_COUNT} achter op de {BRANCH_NAME} branch.",
"FEELS": "Gevoelstemperatuur"
} }

4391
yarn.lock

File diff suppressed because it is too large Load Diff