908 lines
32 KiB
JavaScript
Raw Normal View History

/* global CalendarUtils, cloneObject */
2016-03-31 11:05:32 +02:00
/* MagicMirror²
* Module: Calendar
*
2020-04-28 23:05:28 +02:00
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("calendar", {
// Define module defaults
2016-03-31 11:05:32 +02:00
defaults: {
maximumEntries: 10, // Total Maximum Entries
maximumNumberOfDays: 365,
limitDays: 0, // Limit the number of days shown, 0 = no limit
pastDaysCount: 0,
2016-03-31 11:05:32 +02:00
displaySymbol: true,
2022-01-09 11:25:03 +01:00
defaultSymbol: "calendar-alt", // Fontawesome Symbol see https://fontawesome.com/cheatsheet?from=io
defaultSymbolClassName: "fas fa-fw fa-",
showLocation: false,
displayRepeatingCountTitle: false,
defaultRepeatingCountTitle: "",
maxTitleLength: 25,
2020-06-01 22:25:07 +02:00
maxLocationTitleLength: 25,
wrapEvents: false, // Wrap events to multiple lines breaking at maxTitleLength
2020-06-01 22:25:07 +02:00
wrapLocationEvents: false,
2019-01-16 22:51:44 -08:00
maxTitleLines: 3,
2020-06-01 22:25:07 +02:00
maxEventTitleLines: 3,
fetchInterval: 60 * 60 * 1000, // Update every hour
2016-03-31 11:05:32 +02:00
animationSpeed: 2000,
fade: true,
urgency: 7,
timeFormat: "relative",
2016-11-10 17:26:29 +01:00
dateFormat: "MMM Do",
dateEndFormat: "LT",
fullDayEventDateFormat: "MMM Do",
2018-10-26 15:22:05 +02:00
showEnd: false,
2016-09-04 00:05:02 +02:00
getRelative: 6,
2016-03-31 11:05:32 +02:00
fadePoint: 0.25, // Start on 1/4th of the list.
hidePrivate: false,
2018-04-08 14:57:28 +03:00
hideOngoing: false,
hideTime: false,
hideDuplicates: true,
2022-05-10 14:05:38 -04:00
showTimeToday: false,
2017-01-29 00:59:38 +01:00
colored: false,
customEvents: [], // Array of {keyword: "", symbol: "", color: "", eventClass: ""} where Keyword is a regexp and symbol/color/eventClass are to be applied for matched
tableClass: "small",
2016-04-05 14:35:11 -04:00
calendars: [
2016-03-31 11:05:32 +02:00
{
2022-01-09 08:38:48 +01:00
symbol: "calendar-alt",
url: "https://www.calendarlabs.com/templates/ical/US-Holidays.ics"
}
2016-03-31 11:05:32 +02:00
],
titleReplace: {
2016-06-06 12:05:41 +02:00
"De verjaardag van ": "",
"'s birthday": ""
},
2020-06-01 22:25:07 +02:00
locationTitleReplace: {
"street ": ""
},
broadcastEvents: true,
excludedEvents: [],
sliceMultiDayEvents: false,
broadcastPastEvents: false,
nextDaysRelative: false,
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
selfSignedCert: false,
coloredText: false,
coloredBorder: false,
coloredSymbol: false,
coloredBackground: false,
limitDaysNeverSkip: false,
flipDateHeaderTitle: false,
updateOnFetch: true
2016-03-31 11:05:32 +02:00
},
2020-10-11 22:39:42 -05:00
requiresVersion: "2.1.0",
2016-03-31 11:05:32 +02:00
// Define required scripts.
getStyles: function () {
2019-01-09 21:38:07 +00:00
return ["calendar.css", "font-awesome.css"];
2016-03-31 11:05:32 +02:00
},
// Define required scripts.
getScripts: function () {
return ["calendarutils.js", "moment.js"];
2016-03-31 11:05:32 +02:00
},
2016-04-21 01:04:00 +02:00
// Define required translations.
getTranslations: function () {
2017-03-30 22:14:11 +02:00
// The translations for the default modules are defined in the core translation files.
2021-01-02 21:08:53 +01:00
// Therefore we can just return false. Otherwise we should have returned a dictionary.
// If you're trying to build your own module including translations, check out the documentation.
2016-05-11 12:38:41 +02:00
return false;
2016-04-21 01:04:00 +02:00
},
2016-03-31 11:05:32 +02:00
// Override start method.
start: function () {
Log.info(`Starting module: ${this.name}`);
2016-03-31 11:05:32 +02:00
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.colored) {
Log.warn("Your are using the deprecated config values 'colored'. Please switch to 'coloredSymbol' & 'coloredText'!");
this.config.coloredText = true;
this.config.coloredSymbol = true;
}
if (this.config.coloredSymbolOnly) {
Log.warn("Your are using the deprecated config values 'coloredSymbolOnly'. Please switch to 'coloredSymbol' & 'coloredText'!");
this.config.coloredText = false;
this.config.coloredSymbol = true;
}
2016-03-31 11:05:32 +02:00
// Set locale.
moment.updateLocale(config.language, CalendarUtils.getLocaleSpecification(config.timeFormat));
// clear data holder before start
this.calendarData = {};
// indicate no data available yet
this.loaded = false;
// data holder of calendar url. Avoid fade out/in on updateDom (one for each calendar update)
this.calendarDisplayer = {};
2021-01-04 21:59:41 +01:00
this.config.calendars.forEach((calendar) => {
2016-04-05 14:35:11 -04:00
calendar.url = calendar.url.replace("webcal://", "http://");
2021-01-04 21:59:41 +01:00
const calendarConfig = {
maximumEntries: calendar.maximumEntries,
maximumNumberOfDays: calendar.maximumNumberOfDays,
pastDaysCount: calendar.pastDaysCount,
broadcastPastEvents: calendar.broadcastPastEvents,
selfSignedCert: calendar.selfSignedCert,
excludedEvents: calendar.excludedEvents,
fetchInterval: calendar.fetchInterval
};
2021-01-04 21:59:41 +01:00
if (typeof calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
calendarConfig.symbolClass = "";
}
if (typeof calendar.titleClass === "undefined" || calendar.titleClass === null) {
calendarConfig.titleClass = "";
}
if (typeof 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) {
Log.warn("Deprecation warning: Please update your calendar authentication configuration.");
Log.warn("https://github.com/MichMich/MagicMirror/tree/v2.1.2/modules/default/calendar#calendar-authentication-options");
calendar.auth = {
user: calendar.user,
pass: calendar.pass
2019-06-05 10:23:58 +02:00
};
}
// tell helper to start a fetcher for this calendar
// fetcher till cycle
this.addCalendar(calendar.url, calendar.auth, calendarConfig);
2021-01-04 21:59:41 +01:00
});
Calendar translate (#3249) Hello and thank you for wanting to contribute to the MagicMirror² project **Please make sure that you have followed these 4 rules before submitting your Pull Request:** > 1. Base your pull requests against the `develop` branch. DONE ;D > 2. Include these infos in the description: > - Does the pull request solve a **related** issue? NO > - What does the pull request accomplish? Use a list if needed. For calendar entries containing a year (e.g. DOB) in the title, the age can be calculated. Example before: ![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/67ca65f4-24c3-46a8-bee8-0519e4bba3f5) after: ![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/0b4af07d-d3d9-4644-a4a6-e8c402598208) Achieved by adding a new keyword `transform` to customEvents ``` customEvents: [ {keyword: 'Geburtstag', symbol: 'birthday-cake', color: 'Gold', transform: { search: '^([^\']*) \'(\\d{4})$' , replace: '$1 ($2.)', yearmatchgroup: 2}}, {keyword: 'in Hamburg', transform: { search: ' in Hamburg$' , replace: ''}} ], ``` and therewith obsoleting `titleReplace`; a backward compatibility part is already included. If `yearmatchgroup` is unset, behaviour is as in previous code (some additions to which RegExes are accepted, though) If `yearmatchgroup` is set, it is considered the RegEx match group id, which will be used for calculating the age. > - If it includes major visual changes please add screenshots. NO > 3. Please run `npm run lint:prettier` before submitting so that style issues are fixed. DONE > 4. Don't forget to add an entry about your changes to the CHANGELOG.md file. DONE > Thanks again and have a nice day! You too and if any questions, feel free to let me know. --------- Co-authored-by: veeck <michael.veeck@nebenan.de>
2023-11-01 00:07:56 +01:00
// for backward compatibility titleReplace
if (typeof this.config.titleReplace !== "undefined") {
Log.warn("Deprecation warning: Please consider upgrading your calendar titleReplace configuration to customEvents.");
for (const [titlesearchstr, titlereplacestr] of Object.entries(this.config.titleReplace)) {
this.config.customEvents.push({ keyword: ".*", transform: { search: titlesearchstr, replace: titlereplacestr } });
}
}
this.selfUpdate();
2016-03-31 11:05:32 +02:00
},
// Override socket notification handler.
socketNotificationReceived: function (notification, payload) {
if (notification === "FETCH_CALENDAR") {
2022-07-29 10:25:23 +02:00
this.sendSocketNotification(notification, { url: payload.url, id: this.identifier });
}
2022-07-29 10:25:23 +02:00
2020-06-01 17:19:41 +02:00
if (this.identifier !== payload.id) {
return;
}
2016-04-05 14:35:11 -04:00
if (notification === "CALENDAR_EVENTS") {
2016-03-31 11:05:32 +02:00
if (this.hasCalendarURL(payload.url)) {
this.calendarData[payload.url] = payload.events;
this.error = null;
this.loaded = true;
if (this.config.broadcastEvents) {
this.broadcastEvents();
}
if (!this.config.updateOnFetch) {
if (this.calendarDisplayer[payload.url] === undefined) {
// calendar will never displayed, so display it
this.updateDom(this.config.animationSpeed);
// set this calendar as displayed
this.calendarDisplayer[payload.url] = true;
} else {
Log.debug("[Calendar] DOM not updated waiting self update()");
}
return;
}
2016-03-31 11:05:32 +02:00
}
} else if (notification === "CALENDAR_ERROR") {
2021-05-02 14:43:12 +02:00
let error_message = this.translate(payload.error_type);
this.error = this.translate("MODULE_CONFIG_ERROR", { MODULE_NAME: this.name, ERROR: error_message });
this.loaded = true;
2016-03-31 11:05:32 +02:00
}
this.updateDom(this.config.animationSpeed);
},
// Override dom generator.
getDom: function () {
const ONE_SECOND = 1000; // 1,000 milliseconds
const ONE_MINUTE = ONE_SECOND * 60;
const ONE_HOUR = ONE_MINUTE * 60;
const ONE_DAY = ONE_HOUR * 24;
const events = this.createEventList(true);
2021-01-04 21:59:41 +01:00
const wrapper = document.createElement("table");
wrapper.className = this.config.tableClass;
2016-03-31 11:05:32 +02:00
if (this.error) {
wrapper.innerHTML = this.error;
wrapper.className = `${this.config.tableClass} dimmed`;
return wrapper;
}
2016-03-31 11:05:32 +02:00
if (events.length === 0) {
wrapper.innerHTML = this.loaded ? this.translate("EMPTY") : this.translate("LOADING");
wrapper.className = `${this.config.tableClass} dimmed`;
2016-03-31 11:05:32 +02:00
return wrapper;
}
2021-02-09 17:37:43 +01:00
let currentFadeStep = 0;
let startFade;
let fadeSteps;
if (this.config.fade && this.config.fadePoint < 1) {
if (this.config.fadePoint < 0) {
this.config.fadePoint = 0;
}
2021-02-09 17:37:43 +01:00
startFade = events.length * this.config.fadePoint;
fadeSteps = events.length - startFade;
}
2021-02-09 17:37:43 +01:00
let lastSeenDate = "";
2021-02-09 17:37:43 +01:00
events.forEach((event, index) => {
const dateAsString = moment(event.startDate, "x").format(this.config.dateFormat);
if (this.config.timeFormat === "dateheaders") {
if (lastSeenDate !== dateAsString) {
2021-01-04 21:59:41 +01:00
const dateRow = document.createElement("tr");
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
dateRow.className = "dateheader normal";
if (event.today) dateRow.className += " today";
else if (event.dayBeforeYesterday) dateRow.className += " dayBeforeYesterday";
else if (event.yesterday) dateRow.className += " yesterday";
else if (event.tomorrow) dateRow.className += " tomorrow";
else if (event.dayAfterTomorrow) dateRow.className += " dayAfterTomorrow";
2021-01-04 21:59:41 +01:00
const dateCell = document.createElement("td");
dateCell.colSpan = "3";
dateCell.innerHTML = dateAsString;
dateCell.style.paddingTop = "10px";
dateRow.appendChild(dateCell);
wrapper.appendChild(dateRow);
2021-02-09 17:37:43 +01:00
if (this.config.fade && index >= startFade) {
//fading
2021-02-09 17:37:43 +01:00
currentFadeStep = index - startFade;
dateRow.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
}
lastSeenDate = dateAsString;
}
}
2021-01-04 21:59:41 +01:00
const eventWrapper = document.createElement("tr");
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.coloredText) {
eventWrapper.style.cssText = `color:${this.colorForUrl(event.url, false)}`;
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
}
if (this.config.coloredBackground) {
eventWrapper.style.backgroundColor = this.colorForUrl(event.url, true);
2017-01-29 00:59:38 +01:00
}
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.coloredBorder) {
eventWrapper.style.borderColor = this.colorForUrl(event.url, false);
}
eventWrapper.className = "event-wrapper normal event";
if (event.today) eventWrapper.className += " today";
else if (event.dayBeforeYesterday) eventWrapper.className += " dayBeforeYesterday";
else if (event.yesterday) eventWrapper.className += " yesterday";
else if (event.tomorrow) eventWrapper.className += " tomorrow";
else if (event.dayAfterTomorrow) eventWrapper.className += " dayAfterTomorrow";
2016-03-31 11:05:32 +02:00
2021-01-04 21:59:41 +01:00
const symbolWrapper = document.createElement("td");
2021-01-04 21:59:41 +01:00
if (this.config.displaySymbol) {
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.coloredSymbol) {
symbolWrapper.style.cssText = `color:${this.colorForUrl(event.url, false)}`;
}
2021-01-04 21:59:41 +01:00
const symbolClass = this.symbolClassForUrl(event.url);
symbolWrapper.className = `symbol align-right ${symbolClass}`;
2021-01-04 21:59:41 +01:00
const symbols = this.symbolsForEvent(event);
symbols.forEach((s, index) => {
const symbol = document.createElement("span");
symbol.className = s;
2021-01-04 21:59:41 +01:00
if (index > 0) {
2017-03-16 16:57:55 +01:00
symbol.style.paddingLeft = "5px";
}
symbolWrapper.appendChild(symbol);
2021-01-04 21:59:41 +01:00
});
2016-03-31 11:05:32 +02:00
eventWrapper.appendChild(symbolWrapper);
} else if (this.config.timeFormat === "dateheaders") {
2021-01-04 21:59:41 +01:00
const blankCell = document.createElement("td");
blankCell.innerHTML = "&nbsp;&nbsp;&nbsp;";
eventWrapper.appendChild(blankCell);
2016-03-31 11:05:32 +02:00
}
2021-01-04 21:59:41 +01:00
const titleWrapper = document.createElement("td");
let repeatingCountTitle = "";
2016-05-11 12:38:41 +02:00
2019-01-16 22:53:28 -08:00
if (this.config.displayRepeatingCountTitle && event.firstYear !== undefined) {
2016-05-03 11:56:24 +02:00
repeatingCountTitle = this.countTitleForUrl(event.url);
2016-05-11 12:38:41 +02:00
if (repeatingCountTitle !== "") {
2021-01-04 21:59:41 +01:00
const thisYear = new Date(parseInt(event.startDate)).getFullYear(),
yearDiff = thisYear - event.firstYear;
2016-05-11 12:38:41 +02:00
repeatingCountTitle = `, ${yearDiff} ${repeatingCountTitle}`;
}
2016-05-11 12:38:41 +02:00
}
Calendar translate (#3249) Hello and thank you for wanting to contribute to the MagicMirror² project **Please make sure that you have followed these 4 rules before submitting your Pull Request:** > 1. Base your pull requests against the `develop` branch. DONE ;D > 2. Include these infos in the description: > - Does the pull request solve a **related** issue? NO > - What does the pull request accomplish? Use a list if needed. For calendar entries containing a year (e.g. DOB) in the title, the age can be calculated. Example before: ![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/67ca65f4-24c3-46a8-bee8-0519e4bba3f5) after: ![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/0b4af07d-d3d9-4644-a4a6-e8c402598208) Achieved by adding a new keyword `transform` to customEvents ``` customEvents: [ {keyword: 'Geburtstag', symbol: 'birthday-cake', color: 'Gold', transform: { search: '^([^\']*) \'(\\d{4})$' , replace: '$1 ($2.)', yearmatchgroup: 2}}, {keyword: 'in Hamburg', transform: { search: ' in Hamburg$' , replace: ''}} ], ``` and therewith obsoleting `titleReplace`; a backward compatibility part is already included. If `yearmatchgroup` is unset, behaviour is as in previous code (some additions to which RegExes are accepted, though) If `yearmatchgroup` is set, it is considered the RegEx match group id, which will be used for calculating the age. > - If it includes major visual changes please add screenshots. NO > 3. Please run `npm run lint:prettier` before submitting so that style issues are fixed. DONE > 4. Don't forget to add an entry about your changes to the CHANGELOG.md file. DONE > Thanks again and have a nice day! You too and if any questions, feel free to let me know. --------- Co-authored-by: veeck <michael.veeck@nebenan.de>
2023-11-01 00:07:56 +01:00
var transformedTitle = event.title;
// Color events if custom color or eventClass are specified, transform title if required
if (this.config.customEvents.length > 0) {
2021-02-09 17:37:43 +01:00
for (let ev in this.config.customEvents) {
let needle = new RegExp(this.config.customEvents[ev].keyword, "gi");
if (needle.test(event.title)) {
Calendar translate (#3249) Hello and thank you for wanting to contribute to the MagicMirror² project **Please make sure that you have followed these 4 rules before submitting your Pull Request:** > 1. Base your pull requests against the `develop` branch. DONE ;D > 2. Include these infos in the description: > - Does the pull request solve a **related** issue? NO > - What does the pull request accomplish? Use a list if needed. For calendar entries containing a year (e.g. DOB) in the title, the age can be calculated. Example before: ![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/67ca65f4-24c3-46a8-bee8-0519e4bba3f5) after: ![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/0b4af07d-d3d9-4644-a4a6-e8c402598208) Achieved by adding a new keyword `transform` to customEvents ``` customEvents: [ {keyword: 'Geburtstag', symbol: 'birthday-cake', color: 'Gold', transform: { search: '^([^\']*) \'(\\d{4})$' , replace: '$1 ($2.)', yearmatchgroup: 2}}, {keyword: 'in Hamburg', transform: { search: ' in Hamburg$' , replace: ''}} ], ``` and therewith obsoleting `titleReplace`; a backward compatibility part is already included. If `yearmatchgroup` is unset, behaviour is as in previous code (some additions to which RegExes are accepted, though) If `yearmatchgroup` is set, it is considered the RegEx match group id, which will be used for calculating the age. > - If it includes major visual changes please add screenshots. NO > 3. Please run `npm run lint:prettier` before submitting so that style issues are fixed. DONE > 4. Don't forget to add an entry about your changes to the CHANGELOG.md file. DONE > Thanks again and have a nice day! You too and if any questions, feel free to let me know. --------- Co-authored-by: veeck <michael.veeck@nebenan.de>
2023-11-01 00:07:56 +01:00
if (typeof this.config.customEvents[ev].transform === "object") {
transformedTitle = CalendarUtils.titleTransform(transformedTitle, [this.config.customEvents[ev].transform]);
}
if (typeof this.config.customEvents[ev].color !== "undefined" && this.config.customEvents[ev].color !== "") {
// Respect parameter ColoredSymbolOnly also for custom events
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.coloredText) {
eventWrapper.style.cssText = `color:${this.config.customEvents[ev].color}`;
titleWrapper.style.cssText = `color:${this.config.customEvents[ev].color}`;
2021-02-09 15:21:14 +01:00
}
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.displaySymbol && this.config.coloredSymbol) {
symbolWrapper.style.cssText = `color:${this.config.customEvents[ev].color}`;
}
}
if (typeof this.config.customEvents[ev].eventClass !== "undefined" && this.config.customEvents[ev].eventClass !== "") {
eventWrapper.className += ` ${this.config.customEvents[ev].eventClass}`;
}
}
}
}
titleWrapper.innerHTML = CalendarUtils.shorten(transformedTitle, this.config.maxTitleLength, this.config.wrapEvents, this.config.maxTitleLines) + repeatingCountTitle;
2021-01-04 21:59:41 +01:00
const titleClass = this.titleClassForUrl(event.url);
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (!this.config.coloredText) {
titleWrapper.className = `title bright ${titleClass}`;
2017-01-29 00:59:38 +01:00
} else {
titleWrapper.className = `title ${titleClass}`;
2017-01-29 00:59:38 +01:00
}
if (this.config.timeFormat === "dateheaders") {
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper);
if (event.fullDayEvent) {
titleWrapper.colSpan = "2";
titleWrapper.classList.add("align-left");
2019-06-05 09:32:10 +02:00
} else {
2021-01-04 21:59:41 +01:00
const timeWrapper = document.createElement("td");
timeWrapper.className = `time light ${this.config.flipDateHeaderTitle ? "align-right " : "align-left "}${this.timeClassForUrl(event.url)}`;
timeWrapper.style.paddingLeft = "2px";
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
timeWrapper.style.textAlign = this.config.flipDateHeaderTitle ? "right" : "left";
timeWrapper.innerHTML = moment(event.startDate, "x").format("LT");
// Add endDate to dataheaders if showEnd is enabled
if (this.config.showEnd) {
timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(moment(event.endDate, "x").format("LT"))}`;
}
eventWrapper.appendChild(timeWrapper);
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (!this.config.flipDateHeaderTitle) titleWrapper.classList.add("align-right");
}
if (!this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper);
2019-06-05 09:32:10 +02:00
} else {
2021-01-04 21:59:41 +01:00
const timeWrapper = document.createElement("td");
eventWrapper.appendChild(titleWrapper);
2021-01-04 21:59:41 +01:00
const now = new Date();
if (this.config.timeFormat === "absolute") {
// Use dateFormat
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.dateFormat));
// Add end time if showEnd
if (this.config.showEnd) {
timeWrapper.innerHTML += "-";
timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat));
}
// For full day events we use the fullDayEventDateFormat
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 -= ONE_SECOND;
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat));
2022-03-27 09:16:25 -05:00
} else if (this.config.getRelative > 0 && event.startDate < now) {
// Ongoing and getRelative is set
timeWrapper.innerHTML = CalendarUtils.capFirst(
this.translate("RUNNING", {
fallback: `${this.translate("RUNNING")} {timeUntilEnd}`,
timeUntilEnd: moment(event.endDate, "x").fromNow(true)
})
);
} else if (this.config.urgency > 0 && event.startDate - now < this.config.urgency * ONE_DAY) {
// Within urgency days
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").fromNow());
}
if (event.fullDayEvent && this.config.nextDaysRelative) {
// Full days events within the next two days
if (event.today) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY"));
} else if (event.yesterday) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("YESTERDAY"));
} else if (event.startDate - now < ONE_DAY && event.startDate - now > 0) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TOMORROW"));
} else if (event.startDate - now < 2 * ONE_DAY && event.startDate - now > 0) {
if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW"));
}
}
}
} else {
// Show relative times
2021-12-21 15:22:52 +01:00
if (event.startDate >= now || (event.fullDayEvent && event.today)) {
// Use relative time
2021-12-21 15:22:52 +01:00
if (!this.config.hideTime && !event.fullDayEvent) {
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat }));
} else {
timeWrapper.innerHTML = CalendarUtils.capFirst(
moment(event.startDate, "x").calendar(null, {
sameDay: this.config.showTimeToday ? "LT" : `[${this.translate("TODAY")}]`,
nextDay: `[${this.translate("TOMORROW")}]`,
nextWeek: "dddd",
2021-12-21 15:22:52 +01:00
sameElse: event.fullDayEvent ? this.config.fullDayEventDateFormat : this.config.dateFormat
})
);
}
if (event.fullDayEvent) {
// Full days events within the next two days
if (event.today) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY"));
} else if (event.dayBeforeYesterday) {
if (this.translate("DAYBEFOREYESTERDAY") !== "DAYBEFOREYESTERDAY") {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYBEFOREYESTERDAY"));
}
} else if (event.yesterday) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("YESTERDAY"));
} else if (event.startDate - now < ONE_DAY && event.startDate - now > 0) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TOMORROW"));
} else if (event.startDate - now < 2 * ONE_DAY && event.startDate - now > 0) {
if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW"));
}
}
} else if (event.startDate - now < this.config.getRelative * ONE_HOUR) {
// If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").fromNow());
2021-12-21 15:22:52 +01:00
}
} else {
// Ongoing event
timeWrapper.innerHTML = CalendarUtils.capFirst(
this.translate("RUNNING", {
fallback: `${this.translate("RUNNING")} {timeUntilEnd}`,
timeUntilEnd: moment(event.endDate, "x").fromNow(true)
})
);
}
2016-04-15 13:13:06 +02:00
}
timeWrapper.className = `time light ${this.timeClassForUrl(event.url)}`;
eventWrapper.appendChild(timeWrapper);
}
2016-03-31 11:05:32 +02:00
// Create fade effect.
2021-02-09 17:37:43 +01:00
if (index >= startFade) {
currentFadeStep = index - startFade;
eventWrapper.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
2016-03-31 11:05:32 +02:00
}
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
wrapper.appendChild(eventWrapper);
if (this.config.showLocation) {
if (event.location !== false) {
2021-01-04 21:59:41 +01:00
const locationRow = document.createElement("tr");
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
locationRow.className = "event-wrapper-location normal xsmall light";
if (event.today) locationRow.className += " today";
else if (event.dayBeforeYesterday) locationRow.className += " dayBeforeYesterday";
else if (event.yesterday) locationRow.className += " yesterday";
else if (event.tomorrow) locationRow.className += " tomorrow";
else if (event.dayAfterTomorrow) locationRow.className += " dayAfterTomorrow";
if (this.config.displaySymbol) {
2021-01-04 21:59:41 +01:00
const symbolCell = document.createElement("td");
locationRow.appendChild(symbolCell);
}
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (this.config.coloredText) {
locationRow.style.cssText = `color:${this.colorForUrl(event.url, false)}`;
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
}
if (this.config.coloredBackground) {
locationRow.style.backgroundColor = this.colorForUrl(event.url, true);
}
if (this.config.coloredBorder) {
locationRow.style.borderColor = this.colorForUrl(event.url, false);
}
2021-01-04 21:59:41 +01:00
const descCell = document.createElement("td");
descCell.className = "location";
descCell.colSpan = "2";
const transformedTitle = CalendarUtils.titleTransform(event.location, this.config.locationTitleReplace);
descCell.innerHTML = CalendarUtils.shorten(transformedTitle, this.config.maxLocationTitleLength, this.config.wrapLocationEvents, this.config.maxEventTitleLines);
locationRow.appendChild(descCell);
wrapper.appendChild(locationRow);
2021-02-09 17:37:43 +01:00
if (index >= startFade) {
currentFadeStep = index - startFade;
locationRow.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
}
}
}
2021-02-09 17:37:43 +01:00
});
2016-03-31 11:05:32 +02:00
return wrapper;
},
2020-07-30 12:54:39 +02:00
/**
* Checks if this config contains the calendar url.
* @param {string} url The calendar url
* @returns {boolean} True if the calendar config contains the url, False otherwise
*/
hasCalendarURL: function (url) {
2021-01-04 21:59:41 +01:00
for (const calendar of this.config.calendars) {
2016-03-31 11:05:32 +02:00
if (calendar.url === url) {
return true;
}
}
return false;
},
2020-07-30 12:54:39 +02:00
/**
* Creates the sorted list of all events.
2022-01-17 10:48:16 -05:00
* @param {boolean} limitNumberOfEntries Whether to filter returned events for display.
2020-08-03 11:19:54 +02:00
* @returns {object[]} Array with events.
*/
2022-01-17 10:48:16 -05:00
createEventList: function (limitNumberOfEntries) {
const ONE_SECOND = 1000; // 1,000 milliseconds
const ONE_MINUTE = ONE_SECOND * 60;
const ONE_HOUR = ONE_MINUTE * 60;
const ONE_DAY = ONE_HOUR * 24;
2021-01-04 21:59:41 +01:00
const now = new Date();
const today = moment().startOf("day");
const future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate();
let events = [];
2021-02-09 17:37:43 +01:00
for (const calendarUrl in this.calendarData) {
const calendar = this.calendarData[calendarUrl];
let remainingEntries = this.maximumEntriesForUrl(calendarUrl);
let maxPastDaysCompare = now - this.maximumPastDaysForUrl(calendarUrl) * ONE_DAY;
2021-02-09 17:37:43 +01:00
for (const e in calendar) {
const event = JSON.parse(JSON.stringify(calendar[e])); // clone object
if (this.config.hidePrivate && event.class === "PRIVATE") {
// do not add the current event, skip it
continue;
}
if (limitNumberOfEntries) {
if (event.endDate < maxPastDaysCompare) {
2020-04-20 22:16:23 +02:00
continue;
2018-04-08 14:57:28 +03:00
}
if (this.config.hideOngoing && event.startDate < now) {
continue;
}
if (this.config.hideDuplicates && this.listContainsEvent(events, event)) {
2018-04-08 14:57:28 +03:00
continue;
}
if (--remainingEntries < 0) {
break;
}
}
2021-02-09 17:37:43 +01:00
event.url = calendarUrl;
event.today = event.startDate >= today && event.startDate < today + ONE_DAY;
event.dayBeforeYesterday = event.startDate >= today - ONE_DAY * 2 && event.startDate < today - ONE_DAY;
event.yesterday = event.startDate >= today - ONE_DAY && event.startDate < today;
event.tomorrow = !event.today && event.startDate >= today + ONE_DAY && event.startDate < today + 2 * ONE_DAY;
event.dayAfterTomorrow = !event.tomorrow && event.startDate >= today + ONE_DAY * 2 && event.startDate < today + 3 * ONE_DAY;
/* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
* otherwise, esp. in dateheaders mode it is not clear how long these events are.
*/
const maxCount = Math.ceil((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / ONE_DAY) + 1;
if (this.config.sliceMultiDayEvents && maxCount > 1) {
2021-01-04 21:59:41 +01:00
const splitEvents = [];
let midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x");
let count = 1;
while (event.endDate > midnight) {
2021-02-09 17:37:43 +01:00
const thisEvent = JSON.parse(JSON.stringify(event)); // clone object
thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < today + ONE_DAY;
thisEvent.tomorrow = !thisEvent.today && thisEvent.startDate >= today + ONE_DAY && thisEvent.startDate < today + 2 * ONE_DAY;
thisEvent.endDate = midnight;
thisEvent.title += ` (${count}/${maxCount})`;
splitEvents.push(thisEvent);
event.startDate = midnight;
count += 1;
midnight = moment(midnight, "x").add(1, "day").format("x"); // next day
}
// Last day
event.title += ` (${count}/${maxCount})`;
event.today += event.startDate >= today && event.startDate < today + ONE_DAY;
event.tomorrow = !event.today && event.startDate >= today + ONE_DAY && event.startDate < today + 2 * ONE_DAY;
splitEvents.push(event);
2021-01-04 21:59:41 +01:00
for (let splitEvent of splitEvents) {
if (splitEvent.endDate > now && splitEvent.endDate <= future) {
events.push(splitEvent);
}
}
} else {
events.push(event);
}
2016-03-31 11:05:32 +02:00
}
}
events.sort(function (a, b) {
2016-03-31 11:05:32 +02:00
return a.startDate - b.startDate;
});
2022-01-17 10:48:16 -05:00
if (!limitNumberOfEntries) {
return events;
}
// Limit the number of days displayed
// If limitDays is set > 0, limit display to that number of days
if (this.config.limitDays > 0) {
2021-01-04 21:59:41 +01:00
let newEvents = [];
let lastDate = today.clone().subtract(1, "days").format("YYYYMMDD");
let days = 0;
for (const ev of events) {
let eventDate = moment(ev.startDate, "x").format("YYYYMMDD");
// if date of event is later than lastdate
// check if we already are showing max unique days
if (eventDate > lastDate) {
// if the only entry in the first day is a full day event that day is not counted as unique
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
if (!this.config.limitDaysNeverSkip && newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) {
days--;
}
days++;
if (days > this.config.limitDays) {
continue;
} else {
lastDate = eventDate;
}
}
newEvents.push(ev);
}
events = newEvents;
}
return events.slice(0, this.config.maximumEntries);
2016-03-31 11:05:32 +02:00
},
listContainsEvent: function (eventList, event) {
2021-01-04 21:59:41 +01:00
for (const evt of eventList) {
if (evt.title === event.title && parseInt(evt.startDate) === parseInt(event.startDate) && parseInt(evt.endDate) === parseInt(event.endDate)) {
return true;
}
}
return false;
},
2020-07-30 12:54:39 +02:00
/**
* Requests node helper to add calendar url.
* @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) {
2016-04-05 14:35:11 -04:00
this.sendSocketNotification("ADD_CALENDAR", {
id: this.identifier,
2016-03-31 11:05:32 +02:00
url: url,
excludedEvents: calendarConfig.excludedEvents || this.config.excludedEvents,
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
pastDaysCount: calendarConfig.pastDaysCount || this.config.pastDaysCount,
fetchInterval: calendarConfig.fetchInterval || this.config.fetchInterval,
symbolClass: calendarConfig.symbolClass,
titleClass: calendarConfig.titleClass,
timeClass: calendarConfig.timeClass,
auth: auth,
broadcastPastEvents: calendarConfig.broadcastPastEvents || this.config.broadcastPastEvents,
selfSignedCert: calendarConfig.selfSignedCert || this.config.selfSignedCert
2016-03-31 11:05:32 +02:00
});
},
/**
* Retrieves the symbols for a specific event.
* @param {object} event Event to look for.
2020-07-30 12:54:39 +02:00
* @returns {string[]} The symbols
*/
symbolsForEvent: function (event) {
2020-07-14 21:05:44 +02:00
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);
}
2020-07-14 21:05:44 +02:00
if (event.fullDayEvent === true && this.hasCalendarProperty(event.url, "fullDaySymbol")) {
symbols = this.mergeUnique(this.getCalendarPropertyAsArray(event.url, "fullDaySymbol", this.config.defaultSymbol), symbols);
}
// If custom symbol is set, replace event symbol
for (let ev of this.config.customEvents) {
if (typeof ev.symbol !== "undefined" && ev.symbol !== "") {
let needle = new RegExp(ev.keyword, "gi");
if (needle.test(event.title)) {
// Get the default prefix for this class name and add to the custom symbol provided
const className = this.getCalendarProperty(event.url, "symbolClassName", this.config.defaultSymbolClassName);
symbols[0] = className + ev.symbol;
break;
}
}
}
2020-07-14 21:05:44 +02:00
return symbols;
},
mergeUnique: function (arr1, arr2) {
return arr1.concat(
arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
})
);
2016-03-31 11:05:32 +02:00
},
/**
2020-07-30 12:54:39 +02:00
* Retrieves the symbolClass for a specific calendar url.
* @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", "");
},
/**
2020-07-30 12:54:39 +02:00
* Retrieves the titleClass for a specific calendar url.
* @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", "");
},
/**
2020-07-30 12:54:39 +02:00
* Retrieves the timeClass for a specific calendar url.
* @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", "");
},
2020-07-30 12:54:39 +02:00
/**
* Retrieves the calendar name for a specific calendar url.
* @param {string} url The calendar url
* @returns {string} The name of the calendar
*/
calendarNameForUrl: function (url) {
return this.getCalendarProperty(url, "name", "");
},
2020-07-30 12:54:39 +02:00
/**
* Retrieves the color for a specific calendar url.
* @param {string} url The calendar url
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
* @param {boolean} isBg Determines if we fetch the bgColor or not
2020-07-30 12:54:39 +02:00
* @returns {string} The color
*/
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
colorForUrl: function (url, isBg) {
return this.getCalendarProperty(url, isBg ? "bgColor" : "color", "#fff");
},
2017-02-07 23:51:13 +01:00
2020-07-30 12:54:39 +02:00
/**
* Retrieves the count title for a specific calendar url.
* @param {string} url The calendar url
* @returns {string} The title
*/
countTitleForUrl: function (url) {
2017-02-07 23:51:13 +01:00
return this.getCalendarProperty(url, "repeatingCountTitle", this.config.defaultRepeatingCountTitle);
},
/**
* Retrieves the maximum entry count for a specific calendar url.
* @param {string} url The calendar url
2022-08-08 10:30:37 +02:00
* @returns {number} The maximum entry count
*/
maximumEntriesForUrl: function (url) {
return this.getCalendarProperty(url, "maximumEntries", this.config.maximumEntries);
},
/**
* Retrieves the maximum count of past days which events of should be displayed for a specific calendar url.
* @param {string} url The calendar url
* @returns {number} The maximum past days count
*/
maximumPastDaysForUrl: function (url) {
return this.getCalendarProperty(url, "pastDaysCount", this.config.pastDaysCount);
},
2020-07-30 12:54:39 +02:00
/**
* Helper method to retrieve the property for a specific calendar url.
* @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
*/
2017-02-07 23:51:13 +01:00
getCalendarProperty: function (url, property, defaultValue) {
2021-01-04 21:59:41 +01:00
for (const calendar of this.config.calendars) {
2017-03-16 16:57:55 +01:00
if (calendar.url === url && calendar.hasOwnProperty(property)) {
2017-02-08 00:05:28 +01:00
return calendar[property];
}
}
return defaultValue;
},
2016-03-31 11:05:32 +02:00
2020-07-14 21:05:44 +02:00
getCalendarPropertyAsArray: function (url, property, defaultValue) {
let p = this.getCalendarProperty(url, property, defaultValue);
if (property === "symbol" || property === "recurringSymbol" || property === "fullDaySymbol") {
const className = this.getCalendarProperty(url, "symbolClassName", this.config.defaultSymbolClassName);
p = className + p;
}
2020-07-14 21:05:44 +02:00
if (!(p instanceof Array)) p = [p];
return p;
},
hasCalendarProperty: function (url, property) {
return !!this.getCalendarProperty(url, property, undefined);
},
2020-07-30 12:54:39 +02:00
/**
* Broadcasts the events to all other modules for reuse.
* The all events available in one array, sorted on startdate.
*/
broadcastEvents: function () {
const eventList = this.createEventList(false);
for (const event of eventList) {
event.symbol = this.symbolsForEvent(event);
event.calendarName = this.calendarNameForUrl(event.url);
Calendar Module QOL Features and Adjustments (#3033) This commit adds several QOL features and adjustments to the calendar module including: - **New Options** - ``coloredText``: ``(default: false)`` Determines if you want your entry text to be colored based on the calendar's color - ``coloredBorder``: ``(default: false)`` Determines if you want entry borders to be colored based on the calendar's color - ``coloredSymbol``: ``(default: false)`` Determines if you want entry symbols to be colored based on the calendar's color - ``coloredBackground``: ``(default: false)`` Determines if you want entry backgrounds to be colored based on the calendar's color > These new colored options allows for more out-of-box styling options for the calendar module. With this the ``coloredSymbolOnly`` option has been removed due to redundancy - ``limitDaysNeverSkip``: ``(default: false)`` show every event for every day regardless of if the day only has a single full day event - ``flipDateHeaderTitle``: ``(default: false)`` determines if the title for the date header in the ``dateheaders`` time format should align to the left ``[eg: false]`` or right ``[eg: true]`` - **Layout Changes** - ``dateheader`` is now a class avaliable for date headers in the ``dateheaders`` time format. - Event entries have been better *container-ized* for better styling (using the ``event-container`` class) - ``repeatingCountTitle`` now has a seperator between the ``yearDiff`` and ``repeatingCountTitle`` - ``endDate`` in ``dateheaders`` now capitalizes it's first letter
2023-02-15 15:53:24 -05:00
event.color = this.colorForUrl(event.url, false);
delete event.url;
}
this.sendNotification("CALENDAR_EVENTS", eventList);
},
/**
* Refresh the DOM every minute if needed: When using relative date format for events that start
* or end in less than an hour, the date shows minute granularity and we want to keep that accurate.
* --
* When updateOnFetch is not set, it will Avoid fade out/in on updateDom when many calendars are used
* and it's allow to refresh The DOM every minute with animation speed too
* (because updateDom is not set in CALENDAR_EVENTS for this case)
*/
selfUpdate: function () {
const ONE_MINUTE = 60 * 1000;
setTimeout(
() => {
setInterval(() => {
Log.debug("[Calendar] self update");
if (this.config.updateOnFetch) {
this.updateDom(1);
} else {
this.updateDom(this.config.animationSpeed);
}
}, ONE_MINUTE);
},
ONE_MINUTE - (new Date() % ONE_MINUTE)
);
2016-03-31 11:05:32 +02:00
}
});