mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-21 21:00:57 +00:00
Merge branch 'develop' into develop
This commit is contained in:
@@ -205,7 +205,7 @@ Module.register("calendar", {
|
||||
eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
|
||||
}
|
||||
|
||||
eventWrapper.className = "normal";
|
||||
eventWrapper.className = "normal event";
|
||||
|
||||
if (this.config.displaySymbol) {
|
||||
var symbolWrapper = document.createElement("td");
|
||||
@@ -217,11 +217,7 @@ Module.register("calendar", {
|
||||
var symbolClass = this.symbolClassForUrl(event.url);
|
||||
symbolWrapper.className = "symbol align-right " + symbolClass;
|
||||
|
||||
var symbols = this.symbolsForUrl(event.url);
|
||||
if (typeof symbols === "string") {
|
||||
symbols = [symbols];
|
||||
}
|
||||
|
||||
var symbols = this.symbolsForEvent(event);
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
var symbol = document.createElement("span");
|
||||
symbol.className = "fa fa-fw fa-" + symbols[i];
|
||||
@@ -230,6 +226,7 @@ Module.register("calendar", {
|
||||
}
|
||||
symbolWrapper.appendChild(symbol);
|
||||
}
|
||||
|
||||
eventWrapper.appendChild(symbolWrapper);
|
||||
} else if (this.config.timeFormat === "dateheaders") {
|
||||
var blankCell = document.createElement("td");
|
||||
@@ -419,7 +416,7 @@ Module.register("calendar", {
|
||||
* it will a localeSpecification object with the system locale time format.
|
||||
*
|
||||
* @param {number} timeFormat Specifies either 12 or 24 hour time format
|
||||
* @returns {moment.LocaleSpecification}
|
||||
* @returns {moment.LocaleSpecification} formatted time
|
||||
*/
|
||||
getLocaleSpecification: function (timeFormat) {
|
||||
switch (timeFormat) {
|
||||
@@ -435,12 +432,11 @@ Module.register("calendar", {
|
||||
}
|
||||
},
|
||||
|
||||
/* hasCalendarURL(url)
|
||||
* Check if this config contains the calendar url.
|
||||
/**
|
||||
* Checks if this config contains the calendar url.
|
||||
*
|
||||
* argument url string - Url to look for.
|
||||
*
|
||||
* return bool - Has calendar url
|
||||
* @param {string} url The calendar url
|
||||
* @returns {boolean} True if the calendar config contains the url, False otherwise
|
||||
*/
|
||||
hasCalendarURL: function (url) {
|
||||
for (var c in this.config.calendars) {
|
||||
@@ -453,10 +449,10 @@ Module.register("calendar", {
|
||||
return false;
|
||||
},
|
||||
|
||||
/* createEventList()
|
||||
/**
|
||||
* Creates the sorted list of all events.
|
||||
*
|
||||
* return array - Array with events.
|
||||
* @returns {object[]} Array with events.
|
||||
*/
|
||||
createEventList: function () {
|
||||
var events = [];
|
||||
@@ -467,6 +463,7 @@ Module.register("calendar", {
|
||||
var calendar = this.calendarData[c];
|
||||
for (var e in calendar) {
|
||||
var event = JSON.parse(JSON.stringify(calendar[e])); // clone object
|
||||
|
||||
if (event.endDate < now) {
|
||||
continue;
|
||||
}
|
||||
@@ -536,10 +533,12 @@ Module.register("calendar", {
|
||||
return false;
|
||||
},
|
||||
|
||||
/* createEventList(url)
|
||||
/**
|
||||
* Requests node helper to add calendar url.
|
||||
*
|
||||
* argument url string - Url to add.
|
||||
* @param {string} url The calendar url to add
|
||||
* @param {object} auth The authentication method and credentials
|
||||
* @param {object} calendarConfig The config of the specific calendar
|
||||
*/
|
||||
addCalendar: function (url, auth, calendarConfig) {
|
||||
this.sendSocketNotification("ADD_CALENDAR", {
|
||||
@@ -558,94 +557,100 @@ Module.register("calendar", {
|
||||
},
|
||||
|
||||
/**
|
||||
* symbolsForUrl(url)
|
||||
* Retrieves the symbols for a specific url.
|
||||
* Retrieves the symbols for a specific event.
|
||||
*
|
||||
* argument url string - Url to look for.
|
||||
*
|
||||
* return string/array - The Symbols
|
||||
* @param {object} event Event to look for.
|
||||
* @returns {string[]} The symbols
|
||||
*/
|
||||
symbolsForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "symbol", this.config.defaultSymbol);
|
||||
symbolsForEvent: function (event) {
|
||||
let symbols = this.getCalendarPropertyAsArray(event.url, "symbol", this.config.defaultSymbol);
|
||||
|
||||
if (event.recurringEvent === true && this.hasCalendarProperty(event.url, "recurringSymbol")) {
|
||||
symbols = this.mergeUnique(this.getCalendarPropertyAsArray(event.url, "recurringSymbol", this.config.defaultSymbol), symbols);
|
||||
}
|
||||
|
||||
if (event.fullDayEvent === true && this.hasCalendarProperty(event.url, "fullDaySymbol")) {
|
||||
symbols = this.mergeUnique(this.getCalendarPropertyAsArray(event.url, "fullDaySymbol", this.config.defaultSymbol), symbols);
|
||||
}
|
||||
|
||||
return symbols;
|
||||
},
|
||||
|
||||
mergeUnique: function (arr1, arr2) {
|
||||
return arr1.concat(
|
||||
arr2.filter(function (item) {
|
||||
return arr1.indexOf(item) === -1;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* symbolClassForUrl(url)
|
||||
* Retrieves the symbolClass for a specific url.
|
||||
* Retrieves the symbolClass for a specific calendar url.
|
||||
*
|
||||
* @param url string - Url to look for.
|
||||
*
|
||||
* @returns string
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The class to be used for the symbols of the calendar
|
||||
*/
|
||||
symbolClassForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "symbolClass", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* titleClassForUrl(url)
|
||||
* Retrieves the titleClass for a specific url.
|
||||
* Retrieves the titleClass for a specific calendar url.
|
||||
*
|
||||
* @param url string - Url to look for.
|
||||
*
|
||||
* @returns string
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The class to be used for the title of the calendar
|
||||
*/
|
||||
titleClassForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "titleClass", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* timeClassForUrl(url)
|
||||
* Retrieves the timeClass for a specific url.
|
||||
* Retrieves the timeClass for a specific calendar url.
|
||||
*
|
||||
* @param url string - Url to look for.
|
||||
*
|
||||
* @returns string
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The class to be used for the time of the calendar
|
||||
*/
|
||||
timeClassForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "timeClass", "");
|
||||
},
|
||||
|
||||
/* calendarNameForUrl(url)
|
||||
* Retrieves the calendar name for a specific url.
|
||||
/**
|
||||
* Retrieves the calendar name for a specific calendar url.
|
||||
*
|
||||
* argument url string - Url to look for.
|
||||
*
|
||||
* return string - The name of the calendar
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The name of the calendar
|
||||
*/
|
||||
calendarNameForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "name", "");
|
||||
},
|
||||
|
||||
/* colorForUrl(url)
|
||||
* Retrieves the color for a specific url.
|
||||
/**
|
||||
* Retrieves the color for a specific calendar url.
|
||||
*
|
||||
* argument url string - Url to look for.
|
||||
*
|
||||
* return string - The Color
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The color
|
||||
*/
|
||||
colorForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "color", "#fff");
|
||||
},
|
||||
|
||||
/* countTitleForUrl(url)
|
||||
* Retrieves the name for a specific url.
|
||||
/**
|
||||
* Retrieves the count title for a specific calendar url.
|
||||
*
|
||||
* argument url string - Url to look for.
|
||||
*
|
||||
* return string - The Symbol
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The title
|
||||
*/
|
||||
countTitleForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "repeatingCountTitle", this.config.defaultRepeatingCountTitle);
|
||||
},
|
||||
|
||||
/* getCalendarProperty(url, property, defaultValue)
|
||||
* Helper method to retrieve the property for a specific url.
|
||||
/**
|
||||
* Helper method to retrieve the property for a specific calendar url.
|
||||
*
|
||||
* argument url string - Url to look for.
|
||||
* argument property string - Property to look for.
|
||||
* argument defaultValue string - Value if property is not found.
|
||||
*
|
||||
* return string - The Property
|
||||
* @param {string} url The calendar url
|
||||
* @param {string} property The property to look for
|
||||
* @param {string} defaultValue The value if the property is not found
|
||||
* @returns {*} The property
|
||||
*/
|
||||
getCalendarProperty: function (url, property, defaultValue) {
|
||||
for (var c in this.config.calendars) {
|
||||
@@ -658,6 +663,16 @@ Module.register("calendar", {
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
getCalendarPropertyAsArray: function (url, property, defaultValue) {
|
||||
let p = this.getCalendarProperty(url, property, defaultValue);
|
||||
if (!(p instanceof Array)) p = [p];
|
||||
return p;
|
||||
},
|
||||
|
||||
hasCalendarProperty: function (url, property) {
|
||||
return !!this.getCalendarProperty(url, property, undefined);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shortens a string if it's longer than maxLength and add a ellipsis to the end
|
||||
*
|
||||
@@ -711,22 +726,27 @@ Module.register("calendar", {
|
||||
}
|
||||
},
|
||||
|
||||
/* capFirst(string)
|
||||
/**
|
||||
* Capitalize the first letter of a string
|
||||
* Return capitalized string
|
||||
*
|
||||
* @param {string} string The string to capitalize
|
||||
* @returns {string} The capitalized string
|
||||
*/
|
||||
capFirst: function (string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
},
|
||||
|
||||
/* titleTransform(title)
|
||||
/**
|
||||
* Transforms the title of an event for usage.
|
||||
* Replaces parts of the text as defined in config.titleReplace.
|
||||
* Shortens title based on config.maxTitleLength and config.wrapEvents
|
||||
*
|
||||
* argument title string - The title to transform.
|
||||
*
|
||||
* return string - The transformed title.
|
||||
* @param {string} title The title to transform.
|
||||
* @param {object} titleReplace Pairs of strings to be replaced in the title
|
||||
* @param {boolean} wrapEvents Wrap the text after the line has reached maxLength
|
||||
* @param {number} maxTitleLength The max length of the string
|
||||
* @param {number} maxTitleLines The max number of vertical lines before cutting event title
|
||||
* @returns {string} The transformed title.
|
||||
*/
|
||||
titleTransform: function (title, titleReplace, wrapEvents, maxTitleLength, maxTitleLines) {
|
||||
for (var needle in titleReplace) {
|
||||
@@ -745,7 +765,7 @@ Module.register("calendar", {
|
||||
return title;
|
||||
},
|
||||
|
||||
/* broadcastEvents()
|
||||
/**
|
||||
* Broadcasts the events to all other modules for reuse.
|
||||
* The all events available in one array, sorted on startdate.
|
||||
*/
|
||||
@@ -755,7 +775,7 @@ Module.register("calendar", {
|
||||
var calendar = this.calendarData[url];
|
||||
for (var e in calendar) {
|
||||
var event = cloneObject(calendar[e]);
|
||||
event.symbol = this.symbolsForUrl(url);
|
||||
event.symbol = this.symbolsForEvent(event);
|
||||
event.calendarName = this.calendarNameForUrl(url);
|
||||
event.color = this.colorForUrl(url);
|
||||
delete event.url;
|
||||
|
@@ -6,10 +6,28 @@
|
||||
*/
|
||||
const Log = require("../../../js/logger.js");
|
||||
const ical = require("ical");
|
||||
const moment = require("moment");
|
||||
const request = require("request");
|
||||
|
||||
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumberOfDays, auth, includePastEvents) {
|
||||
/**
|
||||
* Moment date
|
||||
*
|
||||
* @external Moment
|
||||
* @see {@link http://momentjs.com}
|
||||
*/
|
||||
const moment = require("moment");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} url The url of the calendar to fetch
|
||||
* @param {number} reloadInterval Time in ms the calendar is fetched again
|
||||
* @param {string[]} excludedEvents An array of words / phrases from event titles that will be excluded from being shown.
|
||||
* @param {number} maximumEntries The maximum number of events fetched.
|
||||
* @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 {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too
|
||||
* @class
|
||||
*/
|
||||
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) {
|
||||
const self = this;
|
||||
|
||||
let reloadTimer = null;
|
||||
@@ -18,7 +36,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
let fetchFailedCallback = function () {};
|
||||
let eventsReceivedCallback = function () {};
|
||||
|
||||
/* fetchCalendar()
|
||||
/**
|
||||
* Initiates calendar fetch.
|
||||
*/
|
||||
const fetchCalendar = function () {
|
||||
@@ -267,6 +285,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
startDate: startDate.format("x"),
|
||||
endDate: endDate.format("x"),
|
||||
fullDayEvent: isFullDayEvent(event),
|
||||
recurringEvent: true,
|
||||
class: event.class,
|
||||
firstYear: event.start.getFullYear(),
|
||||
location: location,
|
||||
@@ -330,14 +349,14 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
return a.startDate - b.startDate;
|
||||
});
|
||||
|
||||
events = newEvents;
|
||||
events = newEvents.slice(0, maximumEntries);
|
||||
|
||||
self.broadcastEvents();
|
||||
scheduleTimer();
|
||||
});
|
||||
};
|
||||
|
||||
/* scheduleTimer()
|
||||
/**
|
||||
* Schedule the timer for the next update.
|
||||
*/
|
||||
const scheduleTimer = function () {
|
||||
@@ -347,12 +366,11 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
}, reloadInterval);
|
||||
};
|
||||
|
||||
/* isFullDayEvent(event)
|
||||
/**
|
||||
* Checks if an event is a fullday event.
|
||||
*
|
||||
* argument event object - The event object to check.
|
||||
*
|
||||
* return bool - The event is a fullday event.
|
||||
* @param {object} event The event object to check.
|
||||
* @returns {boolean} True if the event is a fullday event, false otherwise
|
||||
*/
|
||||
const isFullDayEvent = function (event) {
|
||||
if (event.start.length === 8 || event.start.dateOnly) {
|
||||
@@ -370,14 +388,13 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
return false;
|
||||
};
|
||||
|
||||
/* timeFilterApplies()
|
||||
/**
|
||||
* Determines if the user defined time filter should apply
|
||||
*
|
||||
* argument now Date - Date object using previously created object for consistency
|
||||
* argument endDate Moment - Moment object representing the event end date
|
||||
* argument filter string - The time to subtract from the end date to determine if an event should be shown
|
||||
*
|
||||
* return bool - The event should be filtered out
|
||||
* @param {Date} now Date object using previously created object for consistency
|
||||
* @param {Moment} endDate Moment object representing the event end date
|
||||
* @param {string} filter The time to subtract from the end date to determine if an event should be shown
|
||||
* @returns {boolean} True if the event should be filtered out, false otherwise
|
||||
*/
|
||||
const timeFilterApplies = function (now, endDate, filter) {
|
||||
if (filter) {
|
||||
@@ -392,12 +409,11 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
return false;
|
||||
};
|
||||
|
||||
/* getTitleFromEvent(event)
|
||||
/**
|
||||
* Gets the title from the event.
|
||||
*
|
||||
* argument event object - The event object to check.
|
||||
*
|
||||
* return string - The title of the event, or "Event" if no title is found.
|
||||
* @param {object} event The event object to check.
|
||||
* @returns {string} The title of the event, or "Event" if no title is found.
|
||||
*/
|
||||
const getTitleFromEvent = function (event) {
|
||||
let title = "Event";
|
||||
@@ -428,14 +444,14 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
|
||||
/* public methods */
|
||||
|
||||
/* startFetch()
|
||||
/**
|
||||
* Initiate fetchCalendar();
|
||||
*/
|
||||
this.startFetch = function () {
|
||||
fetchCalendar();
|
||||
};
|
||||
|
||||
/* broadcastItems()
|
||||
/**
|
||||
* Broadcast the existing events.
|
||||
*/
|
||||
this.broadcastEvents = function () {
|
||||
@@ -443,37 +459,37 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNu
|
||||
eventsReceivedCallback(self);
|
||||
};
|
||||
|
||||
/* onReceive(callback)
|
||||
/**
|
||||
* Sets the on success callback
|
||||
*
|
||||
* argument callback function - The on success callback.
|
||||
* @param {Function} callback The on success callback.
|
||||
*/
|
||||
this.onReceive = function (callback) {
|
||||
eventsReceivedCallback = callback;
|
||||
};
|
||||
|
||||
/* onError(callback)
|
||||
/**
|
||||
* Sets the on error callback
|
||||
*
|
||||
* argument callback function - The on error callback.
|
||||
* @param {Function} callback The on error callback.
|
||||
*/
|
||||
this.onError = function (callback) {
|
||||
fetchFailedCallback = callback;
|
||||
};
|
||||
|
||||
/* url()
|
||||
/**
|
||||
* Returns the url of this fetcher.
|
||||
*
|
||||
* return string - The url of this fetcher.
|
||||
* @returns {string} The url of this fetcher.
|
||||
*/
|
||||
this.url = function () {
|
||||
return url;
|
||||
};
|
||||
|
||||
/* events()
|
||||
/**
|
||||
* Returns current available events for this fetcher.
|
||||
*
|
||||
* return array - The current available events for this fetcher.
|
||||
* @returns {object[]} The current available events for this fetcher.
|
||||
*/
|
||||
this.events = function () {
|
||||
return events;
|
||||
|
@@ -4,7 +4,6 @@
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
|
||||
const NodeHelper = require("node_helper");
|
||||
const validUrl = require("valid-url");
|
||||
const CalendarFetcher = require("./calendarfetcher.js");
|
||||
@@ -20,18 +19,24 @@ module.exports = NodeHelper.create({
|
||||
// Override socketNotificationReceived method.
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
if (notification === "ADD_CALENDAR") {
|
||||
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, 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.id);
|
||||
}
|
||||
},
|
||||
|
||||
/* createFetcher(url, reloadInterval)
|
||||
/**
|
||||
* Creates a fetcher for a new url if it doesn't exist yet.
|
||||
* Otherwise it reuses the existing one.
|
||||
*
|
||||
* attribute url string - URL of the news feed.
|
||||
* attribute reloadInterval number - Reload interval in milliseconds.
|
||||
* @param {string} url The url of the calendar
|
||||
* @param {number} fetchInterval How often does the calendar needs to be fetched in ms
|
||||
* @param {string[]} excludedEvents An array of words / phrases from event titles that will be excluded from being shown.
|
||||
* @param {number} maximumEntries The maximum number of events fetched.
|
||||
* @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 {boolean} broadcastPastEvents If true events from the past maximumNumberOfDays will be included in event broadcasts
|
||||
* @param {string} identifier ID of the module
|
||||
*/
|
||||
createFetcher: function (url, fetchInterval, excludedEvents, maximumNumberOfDays, auth, broadcastPastEvents, identifier) {
|
||||
createFetcher: function (url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, identifier) {
|
||||
var self = this;
|
||||
|
||||
if (!validUrl.isUri(url)) {
|
||||
@@ -42,7 +47,7 @@ module.exports = NodeHelper.create({
|
||||
var fetcher;
|
||||
if (typeof self.fetchers[identifier + url] === "undefined") {
|
||||
Log.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval);
|
||||
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumNumberOfDays, auth, broadcastPastEvents);
|
||||
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents);
|
||||
|
||||
fetcher.onReceive(function (fetcher) {
|
||||
self.sendSocketNotification("CALENDAR_EVENTS", {
|
||||
|
Reference in New Issue
Block a user