Permalink
Browse files

Merge pull request #1498 from MichMich/develop

Release 2.6.0.
  • Loading branch information...
MichMich committed Jan 1, 2019
2 parents 6db61b4 + e70e011 commit de57daa3cd881ce1a14b88307bf61e8109879c81
Showing with 2,836 additions and 1,602 deletions.
  1. +37 −0 CHANGELOG.md
  2. +2 −2 README.md
  3. +2 −2 config/config.js.sample
  4. +6 −1 modules/default/calendar/README.md
  5. +85 −36 modules/default/calendar/calendar.js
  6. +9 −1 modules/default/calendar/calendarfetcher.js
  7. +7 −1 modules/default/calendar/vendor/ical.js/node-ical.js
  8. +5 −0 modules/default/clock/README.md
  9. BIN modules/default/clock/clock_screenshot.png
  10. +20 −16 modules/default/compliments/README.md
  11. BIN modules/default/compliments/compliments_screenshot.png
  12. +6 −1 modules/default/currentweather/README.md
  13. BIN modules/default/currentweather/weather_screenshot.png
  14. +2 −1 modules/default/defaultmodules.js
  15. +4 −0 modules/default/newsfeed/README.md
  16. +1 −1 modules/default/newsfeed/newsfeed.js
  17. BIN modules/default/newsfeed/newsfeed_screenshot.png
  18. +98 −0 modules/default/weather/README.md
  19. +68 −0 modules/default/weather/current.njk
  20. BIN modules/default/weather/current.png
  21. +26 −0 modules/default/weather/forecast.njk
  22. BIN modules/default/weather/forecast.png
  23. +129 −0 modules/default/weather/providers/README.md
  24. +113 −0 modules/default/weather/providers/darksky.js
  25. +165 −0 modules/default/weather/providers/openweathermap.js
  26. +45 −0 modules/default/weather/weather.css
  27. +212 −0 modules/default/weather/weather.js
  28. +100 −0 modules/default/weather/weatherobject.js
  29. +154 −0 modules/default/weather/weatherprovider.js
  30. +9 −3 modules/default/weatherforecast/README.md
  31. BIN modules/default/weatherforecast/forecast_screenshot.png
  32. +3 −3 modules/default/weatherforecast/weatherforecast.js
  33. +1,171 −1,082 package-lock.json
  34. +9 −7 package.json
  35. +35 −0 translations/hr.json
  36. +1 −1 translations/pl.json
  37. +6 −4 translations/pt.json
  38. +3 −1 translations/ro.json
  39. +2 −1 translations/translations.js
  40. +120 −438 vendor/package-lock.json
  41. +1 −0 vendor/package.json
  42. +2 −0 vendor/vendor.js
  43. +178 −0 vendor/yarn.lock
@@ -4,9 +4,46 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

---

## [2.6.0] - 2019-01-01

ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues updating, make sure you are running the latest version of Node.

### ✨ Experimental ✨
- New default [module weather](modules/default/weather). This module will eventually replace the current `currentweather` and `weatherforecast` modules. The new module is still pretty experimental, but it's included so you can give it a try and help us improve this module. Please give us you feedback using [this forum post](https://forum.magicmirror.builders/topic/9335/default-weather-module-refactoring).

### Added
- Possibility to add classes to the cell of symbol, title and time of the events of calendar.
- Font-awesome 5, still has 4 for backwards compatibility.
- Missing `showEnd` in calendar documentation
- Screenshot for the new feed module
- Screenshot for the compliments module
- Screenshot for the clock module
- Screenshot for the current weather
- Screenshot for the weather forecast module
- Portuguese translation for "Feels"
- Croatian translation
- Fading for dateheaders timeFormat in Calendar [#1464](https://github.com/MichMich/MagicMirror/issues/1464)
- Documentation for the existing `scale` option in the Weather Forecast module.

### Fixed
- Allow to parse recurring calendar events where the start date is before 1900
- Fixed Polish translation for Single Update Info
- Ignore entries with unparseable details in the calendar module
- Bug showing FullDayEvents one day too long in calendar fixed
- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MichMich/MagicMirror/issues/1478)

### Updated
- The default calendar setting `showEnd` is changed to `false`.

### Changed
- The Weather Forecast module by default displays the ° symbol after every numeric value to be consistent with the Current Weather module.


## [2.5.0] - 2018-10-01

### Added
- Romanian translation for "Feels"
- Support multi-line compliments
- Simplified Chinese translation for "Feels"
- Polish translate for "Feels"
@@ -38,7 +38,7 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](http://elec

*Electron*, the app wrapper around MagicMirror², only supports the Raspberry Pi 2/3. The Raspberry Pi 0/1 is currently **not** supported. If you want to run this on a Raspberry Pi 1, use the [server only](#server-only) feature and setup a fullscreen browser yourself. (Yes, people have managed to run MM² also on a Pi0, so if you insist, search in the forums.)

Note that you will need to install the lastest full version of Raspbian, **don't use the Lite version**.
Note that you will need to install the latest full version of Raspbian, **don't use the Lite version**.

Execute the following command on your Raspberry Pi to install MagicMirror²:

@@ -140,7 +140,7 @@ The following properties can be configured:
| `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. |
| `units` | The units that will be used in the default weather modules. Possible values are `metric` or `imperial`. The default is `metric`. |
| `modules` | An array of active modules. **The array must contain objects. See the next table below for more information.** |
| `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (example: `electronOptions: { fullscreen: false, width: 800, height: 600 }`). Kiosk mode can be enabled by setting `kiosk = true`, `autoHideMenuBar = false` and `fullscreen = false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). |
| `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (example: `electronOptions: { fullscreen: false, width: 800, height: 600 }`). Kiosk mode can be enabled by setting `kiosk: true`, `autoHideMenuBar: false` and `fullscreen: false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). |
| `customCss` | The path of the `custom.css` stylesheet. The default is `css/custom.css`. |

Module configuration:
@@ -44,7 +44,7 @@ var config = {
config: {
calendars: [
{
symbol: "calendar-check-o ",
symbol: "calendar-check",
url: "webcal://www.calendarlabs.com/templates/ical/US-Holidays.ics"
}
]
@@ -69,7 +69,7 @@ var config = {
header: "Weather Forecast",
config: {
location: "New York",
locationID: "5128581", //ID from http://www.openweathermap.org/help/city_list.txt
locationID: "5128581", //ID from https://openweathermap.org/city
appid: "YOUR_OPENWEATHER_API_KEY"
}
},
@@ -1,7 +1,6 @@
# Module: Calendar
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.
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

@@ -42,8 +41,11 @@ The following properties can be configured:
| `titleReplace` | An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title. <br><br> **Example:** `{'Birthday of ' : '', 'foo':'bar'}` <br> **Default value:** `{ "De verjaardag van ": "", "'s birthday": "" }`
| `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)
| `dateEndFormat` | Format to use for the end time of events <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `HH:mm` (e.g. 16:30)
| `showEnd` | Show end time of events <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `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, 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`
| `showEnd` | Display the end of a date as well <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
| `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`
| `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`
@@ -86,6 +88,9 @@ config: {
| `maximumEntries` | The maximum number of events shown. Overrides global setting. **Possible values:** `0` - `100`
| `maximumNumberOfDays` | The maximum number of days in the future. Overrides global setting
| `auth` | The object containing options for authentication against the calendar.
| `symbolClass` | Add a class to the cell of symbol.
| `titleClass` | Add a class to the title's cell.
| `timeClass` | Add a class to the time's cell.


#### Calendar authentication options:
@@ -27,7 +27,7 @@ Module.register("calendar", {
dateFormat: "MMM Do",
dateEndFormat: "HH:mm",
fullDayEventDateFormat: "MMM Do",
showEnd: true,
showEnd: false,
getRelative: 6,
fadePoint: 0.25, // Start on 1/4th of the list.
hidePrivate: false,
@@ -51,7 +51,7 @@ Module.register("calendar", {

// Define required scripts.
getStyles: function () {
return ["calendar.css", "font-awesome.css"];
return ["calendar.css", "font-awesome5.css", "font-awesome5.v4shims.css"];
},

// Define required scripts.
@@ -82,6 +82,15 @@ Module.register("calendar", {
maximumEntries: calendar.maximumEntries,
maximumNumberOfDays: calendar.maximumNumberOfDays
};
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
calendarConfig.symbolClass = "";
}
if (calendar.titleClass === "undefined" || calendar.titleClass === null) {
calendarConfig.titleClass = "";
}
if (calendar.timeClass === "undefined" || calendar.timeClass === null) {
calendarConfig.timeClass = "";
}

// we check user and password here for backwards compatibility with old configs
if(calendar.user && calendar.pass) {
@@ -135,6 +144,15 @@ Module.register("calendar", {
return wrapper;
}

if (this.config.fade && this.config.fadePoint < 1) {
if (this.config.fadePoint < 0) {
this.config.fadePoint = 0;
}
var startFade = events.length * this.config.fadePoint;
var fadeSteps = events.length - startFade;
}

var currentFadeStep = 0;
var lastSeenDate = "";

for (var e in events) {
@@ -143,14 +161,18 @@ Module.register("calendar", {
if(this.config.timeFormat === "dateheaders"){
if(lastSeenDate !== dateAsString){
var dateRow = document.createElement("tr");
dateRow.className = "normal"
dateRow.className = "normal";
var dateCell = document.createElement("td");

dateCell.colSpan = "3";
dateCell.innerHTML = dateAsString;
dateRow.appendChild(dateCell);
wrapper.appendChild(dateRow);

if (e >= startFade) { //fading
currentFadeStep = e - startFade;
dateRow.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
}

lastSeenDate = dateAsString;
}
@@ -172,7 +194,9 @@ Module.register("calendar", {
symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
}

symbolWrapper.className = "symbol align-right";
var symbolClass = this.symbolClassForUrl(event.url);
symbolWrapper.className = "symbol align-right " + symbolClass;

var symbols = this.symbolsForUrl(event.url);
if(typeof symbols === "string") {
symbols = [symbols];
@@ -189,7 +213,7 @@ Module.register("calendar", {
eventWrapper.appendChild(symbolWrapper);
}else if(this.config.timeFormat === "dateheaders"){
var blankCell = document.createElement("td");
blankCell.innerHTML = "&nbsp;&nbsp;&nbsp;"
blankCell.innerHTML = "&nbsp;&nbsp;&nbsp;";
eventWrapper.appendChild(blankCell);
}

@@ -210,10 +234,12 @@ Module.register("calendar", {

titleWrapper.innerHTML = this.titleTransform(event.title) + repeatingCountTitle;

var titleClass = this.titleClassForUrl(event.url);

if (!this.config.colored) {
titleWrapper.className = "title bright";
titleWrapper.className = "title bright " + titleClass;
} else {
titleWrapper.className = "title";
titleWrapper.className = "title " + titleClass;
}

if(this.config.timeFormat === "dateheaders"){
@@ -223,26 +249,13 @@ Module.register("calendar", {
titleWrapper.align = "left";

}else{

var timeClass = this.timeClassForUrl(event.url);
var timeWrapper = document.createElement("td");
timeWrapper.className = "time light";
timeWrapper.className = "time light " + timeClass;
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);
timeWrapper.innerHTML = moment(event.startDate, "x").format("LT");
eventWrapper.appendChild(timeWrapper);
titleWrapper.align = "right";
}
@@ -260,6 +273,8 @@ Module.register("calendar", {
var oneHour = oneMinute * 60;
var oneDay = oneHour * 24;
if (event.fullDayEvent) {
//subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day
event.endDate -= oneSecond;
if (event.today) {
timeWrapper.innerHTML = this.capFirst(this.translate("TODAY"));
} else if (event.startDate - now < oneDay && event.startDate - now > 0) {
@@ -343,23 +358,17 @@ Module.register("calendar", {
}
//timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll');
//console.log(event);
timeWrapper.className = "time light";
var timeClass = this.timeClassForUrl(event.url);
timeWrapper.className = "time light " + timeClass;
eventWrapper.appendChild(timeWrapper);
}

wrapper.appendChild(eventWrapper);

// Create fade effect.
if (this.config.fade && this.config.fadePoint < 1) {
if (this.config.fadePoint < 0) {
this.config.fadePoint = 0;
}
var startingPoint = events.length * this.config.fadePoint;
var steps = events.length - startingPoint;
if (e >= startingPoint) {
var currentStep = e - startingPoint;
eventWrapper.style.opacity = 1 - (1 / steps * currentStep);
}
if (e >= startFade) {
currentFadeStep = e - startFade;
eventWrapper.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
}
}

@@ -472,11 +481,15 @@ Module.register("calendar", {
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
fetchInterval: this.config.fetchInterval,
symbolClass: calendarConfig.symbolClass,
titleClass: calendarConfig.titleClass,
timeClass: calendarConfig.timeClass,
auth: auth
});
},

/* symbolsForUrl(url)
/**
* symbolsForUrl(url)
* Retrieves the symbols for a specific url.
*
* argument url string - Url to look for.
@@ -487,6 +500,42 @@ Module.register("calendar", {
return this.getCalendarProperty(url, "symbol", this.config.defaultSymbol);
},

/**
* symbolClassForUrl(url)
* Retrieves the symbolClass for a specific url.
*
* @param url string - Url to look for.
*
* @returns string
*/
symbolClassForUrl: function (url) {
return this.getCalendarProperty(url, "symbolClass", "");
},

/**
* titleClassForUrl(url)
* Retrieves the titleClass for a specific url.
*
* @param url string - Url to look for.
*
* @returns string
*/
titleClassForUrl: function (url) {
return this.getCalendarProperty(url, "titleClass", "");
},

/**
* timeClassForUrl(url)
* Retrieves the timeClass for a specific url.
*
* @param url string - Url to look for.
*
* @returns string
*/
timeClassForUrl: function (url) {
return this.getCalendarProperty(url, "timeClass", "");
},

/* colorForUrl(url)
* Retrieves the color for a specific url.
*
@@ -171,8 +171,16 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
var geo = event.geo || false;
var description = event.description || false;

if (typeof event.rrule != "undefined" && !isFacebookBirthday) {
if (typeof event.rrule != "undefined" && event.rrule != null && !isFacebookBirthday) {
var rule = event.rrule;

// can cause problems with e.g. birthdays before 1900
if(rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 ||
rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900){
rule.origOptions.dtstart.setYear(1900);
rule.options.dtstart.setYear(1900);
}

var dates = rule.between(today, future, true, limitFunction);

for (var d in dates) {
@@ -44,7 +44,13 @@ ical.objectHandlers['END'] = function(val, params, curr, stack){
rule += ' EXDATE:' + curr.exdates[i].toISOString().replace(/[-:]/g, '');
rule = rule.replace(/\.[0-9]{3}/, '');
}
curr.rrule = rrulestr(rule);
try {
curr.rrule = rrulestr(rule);
}
catch(err) {
console.log("Unrecognised element in calendar feed, ignoring: " + rule);
curr.rrule = null;
}
}
return originalEnd.call(this, val, params, curr, stack);
}
@@ -2,6 +2,11 @@
The `clock` module is one of the default modules of the MagicMirror.
This module displays the current date and time. The information will be updated realtime.

## Screenshot

- Current time
![Current time](clock_screenshot.png)

## Using the module

To use this module, add it to the modules array in the `config/config.js` file:
Binary file not shown.
Oops, something went wrong.

0 comments on commit de57daa

Please sign in to comment.